diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 9814f0fb7..35cfb260a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -71,6 +71,9 @@ jobs: - name: Check PHPCS standard run: ./vendor/bin/phpcs -i + - name: Check Compatibility of main plugin file. + run: ./vendor/bin/phpcs ./distributor.php --runtime-set testVersion 5.6- --standard=PHPCompatibilityWP + - name: PHPCS check uses: chekalsky/phpcs-action@v1 with: diff --git a/Dockunit.json b/Dockunit.json index 2ecfa7c25..2f8d8533c 100644 --- a/Dockunit.json +++ b/Dockunit.json @@ -1,8 +1,8 @@ { "containers": [ { - "prettyName": "PHP 5.6", - "image": "php:5.6", + "prettyName": "PHP 7.4", + "image": "php:7.4", "beforeScripts": [ "php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\"", "php composer-setup.php --install-dir=/usr/local/bin --filename=composer", @@ -14,8 +14,8 @@ "testCommand": "phpunit" }, { - "prettyName": "PHP 7.0", - "image": "php:7.0", + "prettyName": "PHP 8.1", + "image": "php:8.1", "beforeScripts": [ "php -r \"copy('https://getcomposer.org/installer', 'composer-setup.php');\"", "php composer-setup.php --install-dir=/usr/local/bin --filename=composer", @@ -27,4 +27,4 @@ "testCommand": "phpunit" } ] -} \ No newline at end of file +} diff --git a/README.md b/README.md index 267bda9c9..5c518a7d0 100644 --- a/README.md +++ b/README.md @@ -54,9 +54,9 @@ Distributor is built with the same extensible approach as WordPress itself, with ## Requirements -* PHP 5.6+ -* [WordPress](http://wordpress.org) 4.7+ -* External connections require HTTP Basic Authentication or [WordPress.com OAuth2](https://developer.wordpress.com/docs/oauth2/) (must be on [WordPress VIP](https://wpvip.com/)) be set up on the remote website. For Basic Auth, we recommend the [Application Passwords](https://wordpress.org/plugins/application-passwords/) plugin (note that other plugins like JWT Auth will likely cause issues for external connections) though if you're running WordPress 5.6 or above then Application Passwords is already installed. +* PHP 7.4+ +* [WordPress](http://wordpress.org) 5.7+ +* External connections require HTTP Basic Authentication or [WordPress.com OAuth2](https://developer.wordpress.com/docs/oauth2/) (must be on [WordPress VIP](https://wpvip.com/)) be set up on the remote website. For Basic Auth, we recommend using [Application Passwords](https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/#Getting-Credentials) built in to WordPress. * For external connections, Distributor needs to be installed on BOTH sides of the connection. ## Installation @@ -169,9 +169,15 @@ Enabling this will also provide more debugging information in your error log for ### Application Passwords and WordPress 5.6 -In WordPress 5.6, Application Passwords was merged into WordPress core with some limitations. From 5.6, Application Passwords is enabled by default only for live sites with HTTPS. To enable Application Passwords for development sites, you will need the following snippet: +Application passwords are only available for live sites running over an HTTPS connection. + +For your local development environment, you will need these snippets to enable application passwords without the need for an HTTPS connection. A local development environment is one that "can reach the internet but **is not reachable from the internet**". ```php +// In your local environment's wp-config.php file. +define( 'WP_ENVIRONMENT_TYPE', 'local' ); + +// In a custom plugin on your local environment. add_filter( 'wp_is_application_passwords_available', '__return_true' ); add_action( 'wp_authorize_application_password_request_errors', function( $error ) { diff --git a/assets/js/gutenberg-syndicated-post.js b/assets/js/gutenberg-syndicated-post.js index 55d9b0347..c307368ca 100644 --- a/assets/js/gutenberg-syndicated-post.js +++ b/assets/js/gutenberg-syndicated-post.js @@ -1,10 +1,8 @@ import { dispatch } from '@wordpress/data'; -import { __, setLocaleData, sprintf } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; const { dtGutenberg } = window; -setLocaleData( dtGutenberg.i18n, 'distributor' ); - if ( '0' !== dtGutenberg.originalSourceId || '0' !== dtGutenberg.originalBlogId diff --git a/composer.json b/composer.json index b7564a321..5b59beb1c 100644 --- a/composer.json +++ b/composer.json @@ -10,24 +10,9 @@ "email": "opensource@10up.com" } ], - "repositories": [ - { - "type":"package", - "package": { - "name": "georgestephanis/application-passwords", - "version":"0.1.3", - "source": { - "url": "https://github.com/WordPress/application-passwords.git", - "type": "git", - "reference":"0eef095b4dc984c26ee8149c01a323be83da715a" - } - } - } - ], "require": { - "php": ">=5.6", + "php": ">=7.4", "yahnis-elsts/plugin-update-checker": "4.9", - "georgestephanis/application-passwords": "0.1.3", "ext-json": "*" }, "autoload": { @@ -43,7 +28,7 @@ "automattic/vipwpcs": "^2.3" }, "scripts": { - "lint": "phpcs . --runtime-set testVersion 5.6-", + "lint": "phpcs . --runtime-set testVersion 7.4-", "lint-fix": "phpcbf .", "test": "@php phpunit" }, diff --git a/composer.lock b/composer.lock index 59d752e75..3404d815b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,18 +4,8 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a9a94024c09ec4b273a1af6556928861", + "content-hash": "37702a48014cfd9fd912b833973a3064", "packages": [ - { - "name": "georgestephanis/application-passwords", - "version": "0.1.3", - "source": { - "type": "git", - "url": "https://github.com/WordPress/application-passwords.git", - "reference": "0eef095b4dc984c26ee8149c01a323be83da715a" - }, - "type": "library" - }, { "name": "yahnis-elsts/plugin-update-checker", "version": "v4.9", @@ -95,10 +85,6 @@ "email": "ephraim.gregor@10up.com" } ], - "support": { - "issues": "https://github.com/10up/phpcs-composer/issues", - "source": "https://github.com/10up/phpcs-composer/tree/master" - }, "time": "2021-01-08T03:03:06+00:00" }, { @@ -140,10 +126,6 @@ "GPL-2.0-or-later" ], "description": "A mocking library to take the pain out of unit testing for WordPress", - "support": { - "issues": "https://github.com/10up/wp_mock/issues", - "source": "https://github.com/10up/wp_mock/tree/master" - }, "time": "2019-03-16T03:44:39+00:00" }, { @@ -188,6 +170,10 @@ "runkit", "testing" ], + "support": { + "issues": "https://github.com/antecedent/patchwork/issues", + "source": "https://github.com/antecedent/patchwork/tree/2.1.21" + }, "time": "2022-02-07T07:28:34+00:00" }, { @@ -311,6 +297,10 @@ "stylecheck", "tests" ], + "support": { + "issues": "https://github.com/dealerdirect/phpcodesniffer-composer-installer/issues", + "source": "https://github.com/dealerdirect/phpcodesniffer-composer-installer" + }, "time": "2022-02-04T12:51:07+00:00" }, { @@ -363,6 +353,10 @@ "constructor", "instantiate" ], + "support": { + "issues": "https://github.com/doctrine/instantiator/issues", + "source": "https://github.com/doctrine/instantiator/tree/1.4.1" + }, "funding": [ { "url": "https://www.doctrine-project.org/sponsorship.html", @@ -424,6 +418,10 @@ "keywords": [ "test" ], + "support": { + "issues": "https://github.com/hamcrest/hamcrest-php/issues", + "source": "https://github.com/hamcrest/hamcrest-php/tree/v2.0.1" + }, "time": "2020-07-09T08:09:16+00:00" }, { @@ -492,6 +490,10 @@ "test double", "testing" ], + "support": { + "issues": "https://github.com/mockery/mockery/issues", + "source": "https://github.com/mockery/mockery/tree/1.5.0" + }, "time": "2022-01-20T13:18:17+00:00" }, { @@ -541,6 +543,10 @@ "object", "object graph" ], + "support": { + "issues": "https://github.com/myclabs/DeepCopy/issues", + "source": "https://github.com/myclabs/DeepCopy/tree/1.11.0" + }, "funding": [ { "url": "https://tidelift.com/funding/github/packagist/myclabs/deep-copy", @@ -603,6 +609,10 @@ } ], "description": "Component for reading phar.io manifest information from a PHP Archive (PHAR)", + "support": { + "issues": "https://github.com/phar-io/manifest/issues", + "source": "https://github.com/phar-io/manifest/tree/2.0.3" + }, "time": "2021-07-20T11:28:43+00:00" }, { @@ -650,6 +660,10 @@ } ], "description": "Library for handling version information and constraints", + "support": { + "issues": "https://github.com/phar-io/version/issues", + "source": "https://github.com/phar-io/version/tree/3.2.1" + }, "time": "2022-02-21T01:04:05+00:00" }, { @@ -708,10 +722,6 @@ "phpcs", "standards" ], - "support": { - "issues": "https://github.com/PHPCompatibility/PHPCompatibility/issues", - "source": "https://github.com/PHPCompatibility/PHPCompatibility" - }, "time": "2019-12-27T09:44:58+00:00" }, { @@ -764,6 +774,10 @@ "polyfill", "standards" ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityParagonie" + }, "time": "2021-02-15T10:24:51+00:00" }, { @@ -814,6 +828,10 @@ "standards", "wordpress" ], + "support": { + "issues": "https://github.com/PHPCompatibility/PHPCompatibilityWP/issues", + "source": "https://github.com/PHPCompatibility/PHPCompatibilityWP" + }, "time": "2021-12-30T16:37:40+00:00" }, { @@ -863,6 +881,10 @@ "reflection", "static analysis" ], + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionCommon/issues", + "source": "https://github.com/phpDocumentor/ReflectionCommon/tree/2.x" + }, "time": "2020-06-27T09:03:43+00:00" }, { @@ -916,6 +938,10 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", + "support": { + "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.3.0" + }, "time": "2021-10-19T17:43:47+00:00" }, { @@ -962,6 +988,10 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", + "support": { + "issues": "https://github.com/phpDocumentor/TypeResolver/issues", + "source": "https://github.com/phpDocumentor/TypeResolver/tree/1.6.1" + }, "time": "2022-03-15T21:29:03+00:00" }, { @@ -1025,6 +1055,10 @@ "spy", "stub" ], + "support": { + "issues": "https://github.com/phpspec/prophecy/issues", + "source": "https://github.com/phpspec/prophecy/tree/v1.15.0" + }, "time": "2021-12-08T12:19:24+00:00" }, { @@ -1088,6 +1122,10 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/7.0.15" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1144,6 +1182,10 @@ "filesystem", "iterator" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/2.0.5" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1191,10 +1233,6 @@ "keywords": [ "template" ], - "support": { - "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/1.2.1" - }, "time": "2015-06-21T13:50:34+00:00" }, { @@ -1244,6 +1282,10 @@ "keywords": [ "timer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-timer/issues", + "source": "https://github.com/sebastianbergmann/php-timer/tree/2.1.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1299,6 +1341,10 @@ "keywords": [ "tokenizer" ], + "support": { + "issues": "https://github.com/sebastianbergmann/php-token-stream/issues", + "source": "https://github.com/sebastianbergmann/php-token-stream/tree/master" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1389,6 +1435,10 @@ "testing", "xunit" ], + "support": { + "issues": "https://github.com/sebastianbergmann/phpunit/issues", + "source": "https://github.com/sebastianbergmann/phpunit/tree/8.5.26" + }, "funding": [ { "url": "https://phpunit.de/sponsors.html", @@ -1444,6 +1494,10 @@ ], "description": "Looks up which function or method a line of code belongs to", "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", + "support": { + "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/1.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1514,6 +1568,10 @@ "compare", "equality" ], + "support": { + "issues": "https://github.com/sebastianbergmann/comparator/issues", + "source": "https://github.com/sebastianbergmann/comparator/tree/3.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1576,6 +1634,10 @@ "unidiff", "unified diff" ], + "support": { + "issues": "https://github.com/sebastianbergmann/diff/issues", + "source": "https://github.com/sebastianbergmann/diff/tree/3.0.3" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1635,6 +1697,10 @@ "environment", "hhvm" ], + "support": { + "issues": "https://github.com/sebastianbergmann/environment/issues", + "source": "https://github.com/sebastianbergmann/environment/tree/4.2.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1708,6 +1774,10 @@ "export", "exporter" ], + "support": { + "issues": "https://github.com/sebastianbergmann/exporter/issues", + "source": "https://github.com/sebastianbergmann/exporter/tree/3.1.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1768,6 +1838,10 @@ "keywords": [ "global state" ], + "support": { + "issues": "https://github.com/sebastianbergmann/global-state/issues", + "source": "https://github.com/sebastianbergmann/global-state/tree/3.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1821,6 +1895,10 @@ ], "description": "Traverses array structures and object graphs to enumerate all referenced objects", "homepage": "https://github.com/sebastianbergmann/object-enumerator/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/3.0.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1872,6 +1950,10 @@ ], "description": "Allows reflection of object attributes, including inherited and non-public ones", "homepage": "https://github.com/sebastianbergmann/object-reflector/", + "support": { + "issues": "https://github.com/sebastianbergmann/object-reflector/issues", + "source": "https://github.com/sebastianbergmann/object-reflector/tree/1.1.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1931,6 +2013,10 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", + "support": { + "issues": "https://github.com/sebastianbergmann/recursion-context/issues", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/3.0.1" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -1979,6 +2065,10 @@ ], "description": "Provides a list of PHP built-in functions that operate on resources", "homepage": "https://www.github.com/sebastianbergmann/resource-operations", + "support": { + "issues": "https://github.com/sebastianbergmann/resource-operations/issues", + "source": "https://github.com/sebastianbergmann/resource-operations/tree/2.0.2" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -2031,6 +2121,10 @@ ], "description": "Collection of value objects that represent the types of the PHP type system", "homepage": "https://github.com/sebastianbergmann/type", + "support": { + "issues": "https://github.com/sebastianbergmann/type/issues", + "source": "https://github.com/sebastianbergmann/type/tree/1.1.4" + }, "funding": [ { "url": "https://github.com/sebastianbergmann", @@ -2080,10 +2174,6 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "support": { - "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/master" - }, "time": "2016-10-03T07:35:21+00:00" }, { @@ -2188,6 +2278,11 @@ "phpcs", "standards" ], + "support": { + "issues": "https://github.com/squizlabs/PHP_CodeSniffer/issues", + "source": "https://github.com/squizlabs/PHP_CodeSniffer", + "wiki": "https://github.com/squizlabs/PHP_CodeSniffer/wiki" + }, "time": "2022-06-13T06:31:38+00:00" }, { @@ -2228,6 +2323,10 @@ } ], "description": "A small library for converting tokenized PHP source code into XML and potentially other formats", + "support": { + "issues": "https://github.com/theseer/tokenizer/issues", + "source": "https://github.com/theseer/tokenizer/tree/1.2.1" + }, "funding": [ { "url": "https://github.com/theseer", @@ -2288,6 +2387,10 @@ "check", "validate" ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.11.0" + }, "time": "2022-06-03T18:03:27+00:00" }, { @@ -2334,11 +2437,6 @@ "standards", "wordpress" ], - "support": { - "issues": "https://github.com/WordPress/WordPress-Coding-Standards/issues", - "source": "https://github.com/WordPress/WordPress-Coding-Standards", - "wiki": "https://github.com/WordPress/WordPress-Coding-Standards/wiki" - }, "time": "2020-05-13T23:57:56+00:00" }, { @@ -2396,6 +2494,10 @@ "polyfill", "testing" ], + "support": { + "issues": "https://github.com/Yoast/PHPUnit-Polyfills/issues", + "source": "https://github.com/Yoast/PHPUnit-Polyfills" + }, "time": "2021-11-23T01:37:03+00:00" } ], diff --git a/distributor.php b/distributor.php index bd030597b..f6d5eea40 100644 --- a/distributor.php +++ b/distributor.php @@ -5,6 +5,8 @@ * Update URI: https://distributorplugin.com * Description: Makes it easy to distribute and reuse content across your websites, whether inside of a multisite or across the web. * Version: 1.7.1 + * Requires at least: 5.7 + * Requires PHP: 7.4 * Author: 10up Inc. * Author URI: https://distributorplugin.com * License: GPLv2 or later @@ -12,8 +14,16 @@ * Domain Path: /lang/ * * @package distributor + * + * Developer note: This file is used to test whether the user's server supports + * the minimum software requirements for this plugin prior to bootstrapping. + * + * Unlike the rest of the plugin, this file needs to be compatible with PHP 5.6 + * and WordPress 4.7.0. */ +namespace Distributor; + if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly. } @@ -21,6 +31,7 @@ define( 'DT_VERSION', '1.7.1' ); define( 'DT_PLUGIN_FILE', preg_replace( '#^.*plugins/(.*)$#i', '$1', __FILE__ ) ); define( 'DT_PLUGIN_PATH', plugin_dir_path( __FILE__ ) ); +define( 'DT_PLUGIN_FULL_FILE', __FILE__ ); // Define a constant if we're network activated to allow plugin to respond accordingly. $active_plugins = get_site_option( 'active_sitewide_plugins' ); @@ -32,230 +43,164 @@ } /** - * PSR-4 autoloading + * Get the minimum version of WordPress required by this plugin. + * + * @since x.x.x + * + * @return string Minimum version required. */ -spl_autoload_register( - function( $class ) { - // Project-specific namespace prefix. - $prefix = 'Distributor\\'; - // Base directory for the namespace prefix. - $base_dir = __DIR__ . '/includes/classes/'; - // Does the class use the namespace prefix? - $len = strlen( $prefix ); - if ( strncmp( $prefix, $class, $len ) !== 0 ) { - return; - } - $relative_class = substr( $class, $len ); - $file = $base_dir . str_replace( '\\', '/', $relative_class ) . '.php'; - // If the file exists, require it. - if ( file_exists( $file ) ) { - require $file; - } - } -); +function minimum_wp_requirement() { + return '5.7'; +} /** - * Require PHP version 5.6 - throw an error if the plugin is activated on an older version. + * Get the minimum version of PHP required by this plugin. + * + * @since x.x.x + * + * @return string Minimum version required. */ -register_activation_hook( - __FILE__, - function() { - if ( version_compare( PHP_VERSION, '5.6.0', '<' ) ) { - wp_die( - esc_html__( 'Distributor requires PHP version 5.6.', 'distributor' ), - esc_html__( 'Error Activating', 'distributor' ) - ); - } - } -); +function minimum_php_requirement() { + return '7.4'; +} /** - * Tell the world this site supports Distributor. We need this for external connections. + * Whether WP installation meets the minimum requirements + * + * @since x.x.x + * + * @return bool True if meets minimum requirements, false otherwise. */ -add_action( - 'send_headers', - function() { - if ( ! headers_sent() ) { - header( 'X-Distributor: yes' ); - } - } -); +function site_meets_wp_requirements() { + global $wp_version; + return version_compare( $wp_version, minimum_wp_requirement(), '>=' ); +} /** - * Set Distributor header in all API responses. + * Whether PHP installation meets the minimum requirements + * + * @since x.x.x + * + * @return bool True if meets minimum requirements, false otherwise. */ -add_filter( - 'rest_post_dispatch', - function( $response ) { - $response->header( 'X-Distributor', 'yes' ); - - return $response; - } -); - -\Distributor\Connections::factory(); - -// Include in case we have composer issues. -require_once __DIR__ . '/vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php'; - -require_once __DIR__ . '/includes/utils.php'; -require_once __DIR__ . '/includes/global-functions.php'; -require_once __DIR__ . '/includes/external-connection-cpt.php'; -require_once __DIR__ . '/includes/push-ui.php'; -require_once __DIR__ . '/includes/pull-ui.php'; -require_once __DIR__ . '/includes/rest-api.php'; -require_once __DIR__ . '/includes/subscriptions.php'; -require_once __DIR__ . '/includes/syndicated-post-ui.php'; -require_once __DIR__ . '/includes/distributed-post-ui.php'; -require_once __DIR__ . '/includes/settings.php'; -require_once __DIR__ . '/includes/template-tags.php'; -require_once __DIR__ . '/includes/debug-info.php'; +function site_meets_php_requirements() { + return version_compare( phpversion(), minimum_php_requirement(), '>=' ); +} -// Include application passwords. -add_action( - 'plugins_loaded', +/** + * Require PHP 7.4+, WP 5.7+ - throw an error if the plugin is activated on an older version. + */ +register_activation_hook( + __FILE__, function() { - if ( function_exists( 'wp_is_application_passwords_available' ) ) { - if ( ! wp_is_application_passwords_available() ) { - add_action( - 'admin_notices', - function() { - if ( get_current_screen()->id !== 'toplevel_page_distributor' ) { - return; - } - ?> -
-

- guide to enable Application Passwords.', 'distributor' ), - 'https://github.com/10up/distributor#application-passwords-and-wordpress-56' - ) - ); - ?> -

-
- DT_VERSION, - 'dependencies' => array(), - ); - if ( file_exists( $asset_file ) ) { - $asset_data = require $asset_file; + if ( site_meets_wp_requirements() && site_meets_php_requirements() ) { + // Do nothing, everything is fine. + return; } - // Dependencies only apply to JavaScript, not CSS files. - wp_enqueue_style( 'dt-admin-settings', plugins_url( '/dist/css/admin.min.css', __FILE__ ), array(), $asset_data['version'] ); - } -); - -if ( class_exists( 'Puc_v4_Factory' ) ) { - /** - * Enable updates if we have a valid license - */ - $valid_license = false; - - if ( ! DT_IS_NETWORK ) { - $valid_license = \Distributor\Utils\get_settings()['valid_license']; - } else { - $valid_license = \Distributor\Utils\get_network_settings()['valid_license']; - } - - if ( $valid_license ) { - // @codingStandardsIgnoreStart - $updateChecker = Puc_v4_Factory::buildUpdateChecker( - 'https://github.com/10up/distributor/', - __FILE__, - 'distributor' - ); - - $updateChecker->getVcsApi()->enableReleaseAssets(); - - $updateChecker->addResultFilter( - function( $plugin_info, $http_response = null ) { - $plugin_info->icons = array( - 'svg' => plugins_url( '/assets/img/icon.svg', __FILE__ ), - ); - return $plugin_info; - } - ); - - add_filter( - 'pre_set_site_transient_update_plugins', - function( $transient ) use ( $updateChecker ) { - $update = $updateChecker->getUpdate(); + add_action( + 'admin_notices', + function() { + if ( + ! site_meets_wp_requirements() && + ! site_meets_php_requirements() + ) { + ?> +
+

+ +

+
+ response[ $update->filename ] = $update->toWpFormat(); - } else { - // No update is available. - $update = $updateChecker->getUpdateState()->getUpdate(); - // Adding the plugin info to the `no_update` property is required - // for the enable/disable auto-updates links to correctly appear in UI. - $transient->no_update[ $update->filename ] = $update; + if ( ! site_meets_wp_requirements() ) { + ?> +
+

+ +

+
+ +
+

+ +

+
+ register( '\Distributor\ExternalConnections\WordPressExternalConnection' ); - \Distributor\Connections::factory()->register( '\Distributor\ExternalConnections\WordPressDotcomExternalConnection' ); - if ( - /** - * Filter whether the network connection type is enabled. Enabled by default, return false to disable. - * - * @since 1.0.0 - * @hook dt_network_site_connection_enabled - * - * @param {bool} true Whether the network connection should be enabled. - * - * @return {bool} Whether the network connection should be enabled. - */ - apply_filters( 'dt_network_site_connection_enabled', true ) - ) { - \Distributor\Connections::factory()->register( '\Distributor\InternalConnections\NetworkSiteConnection' ); - } - }, - 1 ); -/** - * We use setup functions to avoid unit testing WP_Mock strict mode errors. - */ -\Distributor\ExternalConnectionCPT\setup(); -\Distributor\PushUI\setup(); -\Distributor\PullUI\setup(); -\Distributor\RestApi\setup(); -\Distributor\Subscriptions\setup(); -\Distributor\SyndicatedPostUI\setup(); -\Distributor\DistributedPostUI\setup(); -\Distributor\Settings\setup(); -\Distributor\DebugInfo\setup(); +if ( ! site_meets_wp_requirements() || ! site_meets_php_requirements() ) { + return; +} + +require_once __DIR__ . '/includes/bootstrap.php'; diff --git a/includes/bootstrap.php b/includes/bootstrap.php new file mode 100644 index 000000000..a61098066 --- /dev/null +++ b/includes/bootstrap.php @@ -0,0 +1,278 @@ +header( 'X-Distributor', 'yes' ); + + return $response; + } +); + +\Distributor\Connections::factory(); + +// Include in case we have composer issues. +require_once DT_PLUGIN_PATH . 'vendor/yahnis-elsts/plugin-update-checker/plugin-update-checker.php'; + +require_once __DIR__ . '/utils.php'; +require_once __DIR__ . '/global-functions.php'; +require_once __DIR__ . '/external-connection-cpt.php'; +require_once __DIR__ . '/push-ui.php'; +require_once __DIR__ . '/pull-ui.php'; +require_once __DIR__ . '/rest-api.php'; +require_once __DIR__ . '/subscriptions.php'; +require_once __DIR__ . '/syndicated-post-ui.php'; +require_once __DIR__ . '/distributed-post-ui.php'; +require_once __DIR__ . '/settings.php'; +require_once __DIR__ . '/template-tags.php'; +require_once __DIR__ . '/debug-info.php'; + +// Include application passwords. +add_action( + 'plugins_loaded', + function() { + if ( ! wp_is_application_passwords_available() ) { + add_action( + 'admin_notices', + function() { + if ( get_current_screen()->id !== 'toplevel_page_distributor' ) { + return; + } + ?> +
+

+ guide to enable Application Passwords.', 'distributor' ), + 'https://github.com/10up/distributor#application-passwords-and-wordpress-56' + ) + ); + ?> +

+
+ DT_VERSION, + 'dependencies' => array(), + ); + if ( file_exists( $asset_file ) ) { + $asset_data = require $asset_file; + } + + // Dependencies only apply to JavaScript, not CSS files. + wp_enqueue_style( 'dt-admin-settings', plugins_url( '/dist/css/admin.min.css', __DIR__ ), array(), $asset_data['version'] ); + } +); + +if ( class_exists( '\\Puc_v4_Factory' ) ) { + /** + * Enable updates if we have a valid license + */ + $valid_license = false; + + if ( ! DT_IS_NETWORK ) { + $valid_license = \Distributor\Utils\get_settings()['valid_license']; + } else { + $valid_license = \Distributor\Utils\get_network_settings()['valid_license']; + } + + if ( $valid_license ) { + // @codingStandardsIgnoreStart + $updateChecker = \Puc_v4_Factory::buildUpdateChecker( + 'https://github.com/10up/distributor/', + DT_PLUGIN_FULL_FILE, + 'distributor' + ); + + $updateChecker->getVcsApi()->enableReleaseAssets(); + + $updateChecker->addResultFilter( + function( $plugin_info, $http_response = null ) { + $plugin_info->icons = array( + 'svg' => plugins_url( '/assets/img/icon.svg', __DIR__ ), + ); + return $plugin_info; + } + ); + + add_filter( + 'pre_set_site_transient_update_plugins', + function( $transient ) use ( $updateChecker ) { + $update = $updateChecker->getUpdate(); + + if ( $update ) { + // Update is available. + $transient->response[ $update->filename ] = $update->toWpFormat(); + } else { + // No update is available. + $update = $updateChecker->getUpdateState()->getUpdate(); + // Adding the plugin info to the `no_update` property is required + // for the enable/disable auto-updates links to correctly appear in UI. + $transient->no_update[ $update->filename ] = $update; + } + + return $transient; + } + ); + // @codingStandardsIgnoreEnd + } +} + +/** + * Register connections + */ +add_action( + 'init', + function() { + \Distributor\Connections::factory()->register( '\Distributor\ExternalConnections\WordPressExternalConnection' ); + \Distributor\Connections::factory()->register( '\Distributor\ExternalConnections\WordPressDotcomExternalConnection' ); + if ( + /** + * Filter whether the network connection type is enabled. Enabled by default, return false to disable. + * + * @since 1.0.0 + * @hook dt_network_site_connection_enabled + * + * @param {bool} true Whether the network connection should be enabled. + * + * @return {bool} Whether the network connection should be enabled. + */ + apply_filters( 'dt_network_site_connection_enabled', true ) + ) { + \Distributor\Connections::factory()->register( '\Distributor\InternalConnections\NetworkSiteConnection' ); + } + }, + 1 +); + +/** + * We use setup functions to avoid unit testing WP_Mock strict mode errors. + */ +\Distributor\ExternalConnectionCPT\setup(); +\Distributor\PushUI\setup(); +\Distributor\PullUI\setup(); +\Distributor\RestApi\setup(); +\Distributor\Subscriptions\setup(); +\Distributor\SyndicatedPostUI\setup(); +\Distributor\DistributedPostUI\setup(); +\Distributor\Settings\setup(); +\Distributor\DebugInfo\setup(); diff --git a/includes/classes/Authentications/WordPressBasicAuth.php b/includes/classes/Authentications/WordPressBasicAuth.php index 6f20d40bb..6854284ee 100644 --- a/includes/classes/Authentications/WordPressBasicAuth.php +++ b/includes/classes/Authentications/WordPressBasicAuth.php @@ -113,10 +113,15 @@ public static function credentials_form( $args = array() ) { Important: We strongly recommend using the Application Passwords plugin on the site you are connecting to in order to create a unique password for this connection. This helps limit the use of your primary password and will allow you to revoke access in the future if needed.', 'distributor' ) ), esc_url( $plugin_link ) ); + $plugin_link = 'https://make.wordpress.org/core/2020/11/05/application-passwords-integration-guide/'; + + printf( + wp_kses_post( + /* translators: %s: Application Passwords documentation URL */ + __( 'Important: We strongly recommend using the Application Passwords feature on the site you are connecting to in order to create a unique password for this connection. This helps limit the use of your primary password and will allow you to revoke access in the future if needed.', 'distributor' ) + ), + esc_url( $plugin_link ) + ); ?>

diff --git a/includes/rest-api.php b/includes/rest-api.php index 80aa3f914..3d05ee2ea 100644 --- a/includes/rest-api.php +++ b/includes/rest-api.php @@ -371,8 +371,9 @@ function register_endpoints() { function distributor_meta() { return array( 'version' => DT_VERSION, - 'core_has_application_passwords' => function_exists( 'wp_is_application_passwords_available' ), - 'core_application_passwords_available' => function_exists( 'wp_is_application_passwords_available' ) && ! wp_is_application_passwords_available() ? false : true, + 'core_has_application_passwords' => true, + 'core_application_passwords_available' => ! wp_is_application_passwords_available() ? false : true, + 'core_application_passwords_endpoint' => admin_url( 'authorize-application.php' ), ); } diff --git a/includes/syndicated-post-ui.php b/includes/syndicated-post-ui.php index 98336c18f..642eb6eed 100644 --- a/includes/syndicated-post-ui.php +++ b/includes/syndicated-post-ui.php @@ -7,6 +7,8 @@ namespace Distributor\SyndicatedPostUI; +use Distributor\Utils; + /** * Setup actions and filters * @@ -26,12 +28,8 @@ function() { add_filter( 'admin_body_class', __NAMESPACE__ . '\add_linked_class' ); add_filter( 'post_row_actions', __NAMESPACE__ . '\remove_quick_edit', 10, 2 ); - $post = isset( $_GET['post'] ) ? get_post( (int) $_GET['post'] ) : false; // @codingStandardsIgnoreLine Nonce not required - - if ( $post && ! \Distributor\Utils\is_using_gutenberg( $post ) ) { - add_action( 'do_meta_boxes', __NAMESPACE__ . '\replace_revisions_meta_box', 10, 3 ); - add_action( 'add_meta_boxes', __NAMESPACE__ . '\add_revisions_meta_box' ); - } + add_action( 'do_meta_boxes', __NAMESPACE__ . '\replace_revisions_meta_box', 10, 3 ); + add_action( 'add_meta_boxes', __NAMESPACE__ . '\add_revisions_meta_box' ); add_action( 'admin_init', __NAMESPACE__ . '\setup_columns' ); } @@ -256,6 +254,10 @@ function replace_revisions_meta_box( $post_type, $context, $post ) { return; } + if ( Utils\is_using_gutenberg( $post ) ) { + return; + } + $original_blog_id = get_post_meta( $post->ID, 'dt_original_blog_id', true ); $original_post_id = get_post_meta( $post->ID, 'dt_original_post_id', true ); $original_source_id = get_post_meta( $post->ID, 'dt_original_source_id', true ); @@ -570,17 +572,6 @@ function enqueue_gutenberg_edit_scripts() { $post_type_singular = $post_type_object->labels->singular_name; - if ( function_exists( 'gutenberg_get_jed_locale_data' ) ) { - $i18n_locale = gutenberg_get_jed_locale_data( 'distributor' ); - } else { - $i18n_locale = [ - '' => [ - 'domain' => 'distributor', - 'lang' => get_user_locale(), - ], - ]; // this is a temp hacky substitute for gutenberg_get_jed_locale_data() - } - $asset_file = DT_PLUGIN_PATH . '/dist/js/gutenberg-syndicated-post.min.asset.php'; // Fallback asset data. $asset_data = array( @@ -592,6 +583,7 @@ function enqueue_gutenberg_edit_scripts() { } wp_enqueue_script( 'dt-gutenberg-syndicated-post', plugins_url( '/dist/js/gutenberg-syndicated-post.min.js', __DIR__ ), $asset_data['dependencies'], $asset_data['version'], true ); + wp_set_script_translations( 'dt-gutenberg-syndicated-post', 'distributor', DT_PLUGIN_PATH . 'lang' ); $asset_file = DT_PLUGIN_PATH . '/dist/js/gutenberg-plugin.min.asset.php'; // Fallback asset data. @@ -603,6 +595,7 @@ function enqueue_gutenberg_edit_scripts() { $asset_data = require $asset_file; } wp_enqueue_script( 'dt-gutenberg-plugin', plugins_url( '/dist/js/gutenberg-plugin.min.js', __DIR__ ), $asset_data['dependencies'], $asset_data['version'], true ); + wp_set_script_translations( 'dt-gutenberg-plugin', 'distributor', DT_PLUGIN_PATH . 'lang' ); wp_localize_script( 'dt-gutenberg-syndicated-post', diff --git a/includes/utils.php b/includes/utils.php index 4118e0f2c..024490723 100644 --- a/includes/utils.php +++ b/includes/utils.php @@ -20,79 +20,35 @@ function is_vip_com() { /** * Determine if Gutenberg is being used. * - * There are several possible variations that need to be accounted for: - * - * - WordPress 4.9, Gutenberg plugin is not active. - * - WordPress 4.9, Gutenberg plugin is active. - * - WordPress 5.0, block editor by default. - * - WordPress 5.0, Classic editor plugin active, using classic editor. - * - WordPress 5.0, Classic editor plugin active, using the block editor. + * This duplicates the check from `use_block_editor_for_post()` in WordPress + * but removes the check for the `meta-box-loader` querystring parameter as + * it is not required for Distributor. * * @since 1.2 * @since 1.7 Update Gutenberg plugin sniff to avoid deprecated function. * Update Classic Editor sniff to account for mu-plugins. + * @since 2.0 Duplicate the check from WordPress Core's `use_block_editor_for_post()`. * - * @param object $post The post object. - * @return boolean + * @param int|WP_Post $post The post ID or object. + * @return boolean Whether post is using the block editor/Gutenberg. */ function is_using_gutenberg( $post ) { - global $wp_version; - - $gutenberg_available = function_exists( 'gutenberg_pre_init' ); - $version_5_plus = version_compare( $wp_version, '5', '>=' ); - - if ( ! $gutenberg_available && ! $version_5_plus ) { - return false; - } - $post = get_post( $post ); if ( ! $post ) { return false; } - // This duplicates the check from `use_block_editor_for_post()` as of WP 5.0. - // We duplicate this here to remove the $_GET['meta-box-loader'] check - if ( function_exists( 'use_block_editor_for_post_type' ) ) { - // The posts page can't be edited in the block editor. - if ( absint( get_option( 'page_for_posts' ) ) === $post->ID && empty( $post->post_content ) ) { - return false; - } - - // Make sure this post type supports Gutenberg - $use_block_editor = use_block_editor_for_post_type( $post->post_type ); - - /** This filter is documented in wp-admin/includes/post.php */ - return apply_filters( 'use_block_editor_for_post', $use_block_editor, $post ); - } - - // This duplicates the check from `has_blocks()` as of WP 5.2. - if ( ! empty( $post->post_content ) ) { - return false !== strpos( (string) $post->post_content, '