initial
This commit is contained in:
@@ -0,0 +1,247 @@
|
||||
# Changelog
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
|
||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [0.9.19] - 2026-06-08
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.18] - 2026-06-01
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.17] - 2026-05-19
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.16] - 2026-05-04
|
||||
### Changed
|
||||
- Internal: No longer require automattic/jetpack-changelogger as a per-project dev dependency. [#48225]
|
||||
|
||||
## [0.9.15] - 2026-02-23
|
||||
### Changed
|
||||
- Update dependencies. [#39303]
|
||||
|
||||
## [0.9.14] - 2026-02-02
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.13] - 2025-11-03
|
||||
### Fixed
|
||||
- Phan: Address PhanRedundantCondition, PhanRedundantArrayValuesCall, and PhanPluginRedundantAssignment violations. [#45681]
|
||||
|
||||
## [0.9.12] - 2025-10-27
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.11] - 2025-08-18
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.10] - 2025-08-11
|
||||
### Fixed
|
||||
- Prevent PHP errors when directly accessing various files. [#44646]
|
||||
|
||||
## [0.9.9] - 2025-08-04
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.8] - 2025-04-28
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.7] - 2025-03-24
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.6] - 2025-03-12
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.5] - 2025-03-10
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.4] - 2025-02-24
|
||||
### Fixed
|
||||
- Code: Prevent dynamic class properties. [#41857]
|
||||
|
||||
## [0.9.3] - 2025-01-27
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.9.2] - 2024-12-16
|
||||
### Fixed
|
||||
- Import: setting WP_IMPORTING when doing an import. [#40563]
|
||||
|
||||
## [0.9.1] - 2024-11-25
|
||||
### Changed
|
||||
- Updated dependencies. [#40286]
|
||||
|
||||
## [0.9.0] - 2024-11-18
|
||||
### Removed
|
||||
- General: Update minimum PHP version to 7.2. [#40147]
|
||||
|
||||
## [0.8.11] - 2024-11-04
|
||||
### Added
|
||||
- Enable test coverage. [#39961]
|
||||
|
||||
## [0.8.10] - 2024-10-29
|
||||
### Changed
|
||||
- Internal updates. [#39303]
|
||||
|
||||
## [0.8.9] - 2024-09-23
|
||||
### Changed
|
||||
- Update dependencies. [#39303]
|
||||
|
||||
## [0.8.8] - 2024-09-09
|
||||
### Changed
|
||||
- Update dependencies. [#39253]
|
||||
|
||||
## [0.8.7] - 2024-08-26
|
||||
### Changed
|
||||
- Updated package dependencies. [#39004]
|
||||
|
||||
## [0.8.6] - 2024-05-27
|
||||
### Changed
|
||||
- Update dependencies.
|
||||
|
||||
## [0.8.5] - 2024-05-06
|
||||
### Added
|
||||
- Add missing package dependencies. [#37141]
|
||||
|
||||
## [0.8.4] - 2024-04-29
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.8.3] - 2024-04-08
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.8.2] - 2024-03-18
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.8.1] - 2023-11-24
|
||||
### Changed
|
||||
- Replaced usage of strpos() with str_contains(). [#34137]
|
||||
|
||||
## [0.8.0] - 2023-11-20
|
||||
### Changed
|
||||
- Updated required PHP version to >= 7.0. [#34192]
|
||||
|
||||
## [0.7.4] - 2023-09-19
|
||||
|
||||
- Minor internal updates.
|
||||
|
||||
## [0.7.3] - 2023-09-11
|
||||
### Fixed
|
||||
- Handles scaled images for attachments [#32838]
|
||||
|
||||
## [0.7.2] - 2023-08-28
|
||||
### Changed
|
||||
- Updated package dependencies. [#32605]
|
||||
|
||||
## [0.7.1] - 2023-05-29
|
||||
### Changed
|
||||
- Internal updates.
|
||||
|
||||
## [0.7.0] - 2023-04-17
|
||||
### Added
|
||||
- Added Unified Importer end endpoint [#30087]
|
||||
- Add new start endpoint. [#30028]
|
||||
|
||||
## [0.6.1] - 2023-04-10
|
||||
### Added
|
||||
- Add Jetpack Autoloader package suggestion. [#29988]
|
||||
|
||||
## [0.6.0] - 2023-04-04
|
||||
### Added
|
||||
- Add support for wp_block, wp_navigation, wp_template, wp_template_part import. [#29744]
|
||||
- Align all HTTP codes to a standard 409. [#29869]
|
||||
|
||||
## [0.5.0] - 2023-03-29
|
||||
### Added
|
||||
- Prevent media duplication when it's already existed [#29646]
|
||||
|
||||
### Fixed
|
||||
- Remove process post meta function outside of hook [#29771]
|
||||
|
||||
## [0.4.0] - 2023-03-27
|
||||
### Added
|
||||
- Added global style import. [#29622]
|
||||
- Added import of custom CSS [#29595]
|
||||
- Adding functionality to create term on the fly [#29581]
|
||||
|
||||
### Changed
|
||||
- Updated package version [#29457]
|
||||
|
||||
### Fixed
|
||||
- Fixed post meta imports issue [#29497]
|
||||
- Fix wp_global_styles issue [#29686]
|
||||
|
||||
## [0.3.0] - 2023-03-20
|
||||
### Added
|
||||
- Add support for nav-menu and nav-menu-item import. [#29481]
|
||||
|
||||
### Fixed
|
||||
- Fix attachments path for import media endpoint [#29379]
|
||||
|
||||
## [0.2.0] - 2023-03-08
|
||||
### Added
|
||||
- Add the `/jetpack/v4/import/media/*` endpoints. [#29080]
|
||||
|
||||
## 0.1.0 - 2023-02-20
|
||||
### Added
|
||||
- Added import REST endpoints. [#28824]
|
||||
- Add new Jetpack Import package. [#28735]
|
||||
|
||||
### Fixed
|
||||
- Fixed various imported resources hierarchies [#29012]
|
||||
|
||||
[0.9.19]: https://github.com/Automattic/jetpack-import/compare/v0.9.18...v0.9.19
|
||||
[0.9.18]: https://github.com/Automattic/jetpack-import/compare/v0.9.17...v0.9.18
|
||||
[0.9.17]: https://github.com/Automattic/jetpack-import/compare/v0.9.16...v0.9.17
|
||||
[0.9.16]: https://github.com/Automattic/jetpack-import/compare/v0.9.15...v0.9.16
|
||||
[0.9.15]: https://github.com/Automattic/jetpack-import/compare/v0.9.14...v0.9.15
|
||||
[0.9.14]: https://github.com/Automattic/jetpack-import/compare/v0.9.13...v0.9.14
|
||||
[0.9.13]: https://github.com/Automattic/jetpack-import/compare/v0.9.12...v0.9.13
|
||||
[0.9.12]: https://github.com/Automattic/jetpack-import/compare/v0.9.11...v0.9.12
|
||||
[0.9.11]: https://github.com/Automattic/jetpack-import/compare/v0.9.10...v0.9.11
|
||||
[0.9.10]: https://github.com/Automattic/jetpack-import/compare/v0.9.9...v0.9.10
|
||||
[0.9.9]: https://github.com/Automattic/jetpack-import/compare/v0.9.8...v0.9.9
|
||||
[0.9.8]: https://github.com/Automattic/jetpack-import/compare/v0.9.7...v0.9.8
|
||||
[0.9.7]: https://github.com/Automattic/jetpack-import/compare/v0.9.6...v0.9.7
|
||||
[0.9.6]: https://github.com/Automattic/jetpack-import/compare/v0.9.5...v0.9.6
|
||||
[0.9.5]: https://github.com/Automattic/jetpack-import/compare/v0.9.4...v0.9.5
|
||||
[0.9.4]: https://github.com/Automattic/jetpack-import/compare/v0.9.3...v0.9.4
|
||||
[0.9.3]: https://github.com/Automattic/jetpack-import/compare/v0.9.2...v0.9.3
|
||||
[0.9.2]: https://github.com/Automattic/jetpack-import/compare/v0.9.1...v0.9.2
|
||||
[0.9.1]: https://github.com/Automattic/jetpack-import/compare/v0.9.0...v0.9.1
|
||||
[0.9.0]: https://github.com/Automattic/jetpack-import/compare/v0.8.11...v0.9.0
|
||||
[0.8.11]: https://github.com/Automattic/jetpack-import/compare/v0.8.10...v0.8.11
|
||||
[0.8.10]: https://github.com/Automattic/jetpack-import/compare/v0.8.9...v0.8.10
|
||||
[0.8.9]: https://github.com/Automattic/jetpack-import/compare/v0.8.8...v0.8.9
|
||||
[0.8.8]: https://github.com/Automattic/jetpack-import/compare/v0.8.7...v0.8.8
|
||||
[0.8.7]: https://github.com/Automattic/jetpack-import/compare/v0.8.6...v0.8.7
|
||||
[0.8.6]: https://github.com/Automattic/jetpack-import/compare/v0.8.5...v0.8.6
|
||||
[0.8.5]: https://github.com/Automattic/jetpack-import/compare/v0.8.4...v0.8.5
|
||||
[0.8.4]: https://github.com/Automattic/jetpack-import/compare/v0.8.3...v0.8.4
|
||||
[0.8.3]: https://github.com/Automattic/jetpack-import/compare/v0.8.2...v0.8.3
|
||||
[0.8.2]: https://github.com/Automattic/jetpack-import/compare/v0.8.1...v0.8.2
|
||||
[0.8.1]: https://github.com/Automattic/jetpack-import/compare/v0.8.0...v0.8.1
|
||||
[0.8.0]: https://github.com/Automattic/jetpack-import/compare/v0.7.4...v0.8.0
|
||||
[0.7.4]: https://github.com/Automattic/jetpack-import/compare/v0.7.3...v0.7.4
|
||||
[0.7.3]: https://github.com/Automattic/jetpack-import/compare/v0.7.2...v0.7.3
|
||||
[0.7.2]: https://github.com/Automattic/jetpack-import/compare/v0.7.1...v0.7.2
|
||||
[0.7.1]: https://github.com/Automattic/jetpack-import/compare/v0.7.0...v0.7.1
|
||||
[0.7.0]: https://github.com/Automattic/jetpack-import/compare/v0.6.1...v0.7.0
|
||||
[0.6.1]: https://github.com/Automattic/jetpack-import/compare/v0.6.0...v0.6.1
|
||||
[0.6.0]: https://github.com/Automattic/jetpack-import/compare/v0.5.0...v0.6.0
|
||||
[0.5.0]: https://github.com/Automattic/jetpack-import/compare/v0.4.0...v0.5.0
|
||||
[0.4.0]: https://github.com/Automattic/jetpack-import/compare/v0.3.0...v0.4.0
|
||||
[0.3.0]: https://github.com/Automattic/jetpack-import/compare/v0.2.0...v0.3.0
|
||||
[0.2.0]: https://github.com/Automattic/jetpack-import/compare/v0.1.0...v0.2.0
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* Set of REST API routes used in WPCOM Unified Importer.
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import;
|
||||
|
||||
use Automattic\Jetpack\Connection\Manager as Connection_Manager;
|
||||
use Automattic\Jetpack\Connection\Rest_Authentication;
|
||||
|
||||
/**
|
||||
* This class will provide endpoint for the Unified Importer.
|
||||
*/
|
||||
class Main {
|
||||
|
||||
/**
|
||||
* Package version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const PACKAGE_VERSION = '0.9.19';
|
||||
|
||||
/**
|
||||
* A list of all the routes.
|
||||
*
|
||||
* @var \WP_REST_Controller[]
|
||||
*/
|
||||
private static $routes = array();
|
||||
|
||||
/**
|
||||
* Before everything else starts getting initalized, we need to initialize Jetpack using the
|
||||
* Config object.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function configure() {
|
||||
if ( did_action( 'jetpack_import_initialized' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$connection = new Connection_Manager();
|
||||
|
||||
// Initialize the REST API only if the user is connected.
|
||||
if ( $connection->has_connected_owner() ) {
|
||||
add_action( 'rest_api_init', array( __CLASS__, 'initialize_rest_api' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs right after the Jetpack Import package is initialized.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*/
|
||||
do_action( 'jetpack_import_initialized' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Register import related REST routes.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public static function initialize_rest_api() {
|
||||
// Set up the REST authentication hooks.
|
||||
Rest_Authentication::init();
|
||||
|
||||
$routes = array(
|
||||
'blocks' => new Endpoints\Block(),
|
||||
'categories' => new Endpoints\Category(),
|
||||
'comments' => new Endpoints\Comment(),
|
||||
'custom-css' => new Endpoints\Custom_CSS(),
|
||||
'end' => new Endpoints\End(),
|
||||
'global-styles' => new Endpoints\Global_Style(),
|
||||
'media' => new Endpoints\Attachment(),
|
||||
'menu-items' => new Endpoints\Menu_Item(),
|
||||
'menus' => new Endpoints\Menu(),
|
||||
'navigation' => new Endpoints\Navigation(),
|
||||
'pages' => new Endpoints\Page(),
|
||||
'posts' => new Endpoints\Post(),
|
||||
'start' => new Endpoints\Start(),
|
||||
'tags' => new Endpoints\Tag(),
|
||||
'template-parts' => new Endpoints\Template_Part(),
|
||||
'templates' => new Endpoints\Template(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Allow other plugins to modify import routes.
|
||||
*
|
||||
* @since 0.1.0
|
||||
*
|
||||
* @param array $routes Array of import routes.
|
||||
*/
|
||||
self::$routes = apply_filters( 'jetpack_import_types', $routes );
|
||||
|
||||
// Register all the routes.
|
||||
foreach ( self::$routes as $route ) {
|
||||
$route->register_routes();
|
||||
}
|
||||
}
|
||||
}
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
<?php
|
||||
/**
|
||||
* Attachments REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Attachment
|
||||
*/
|
||||
class Attachment extends \WP_REST_Attachments_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching. Default false.
|
||||
*
|
||||
* @var false
|
||||
*/
|
||||
protected $allow_batch = false;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'attachment' );
|
||||
|
||||
// @see add_term_meta
|
||||
$this->import_id_meta_type = 'post';
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the routes for the objects of the controller.
|
||||
*
|
||||
* @see WP_REST_Terms_Controller::register_rest_route()
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
self::$rest_namespace,
|
||||
'/' . $this->rest_base,
|
||||
$this->get_route_options()
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
self::$rest_namespace,
|
||||
'/' . $this->rest_base . '/(?P<id>[\d]+)',
|
||||
array(
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the attachment.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
),
|
||||
array(
|
||||
'methods' => \WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_item' ),
|
||||
'permission_callback' => array( $this, 'update_item_permissions_check' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::EDITABLE ),
|
||||
),
|
||||
'allow_batch' => array( 'v1' => true ),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
self::$rest_namespace,
|
||||
'/' . $this->rest_base . '/(?P<id>[\d]+)/post-process',
|
||||
array(
|
||||
'methods' => \WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'post_process_item' ),
|
||||
'permission_callback' => array( $this, 'import_permissions_callback' ),
|
||||
'args' => array(
|
||||
'id' => array(
|
||||
'description' => __( 'Unique identifier for the attachment.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
),
|
||||
'action' => array(
|
||||
'type' => 'string',
|
||||
'enum' => array( 'create-image-subsizes' ),
|
||||
'required' => true,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a single attachment.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
$file_info = $this->get_file_info( $request );
|
||||
$attachment = $this->get_attachment_by_file_info( $file_info );
|
||||
if ( $attachment ) {
|
||||
$response = $this->prepare_attachment_for_response( $attachment, $request );
|
||||
|
||||
if ( \is_wp_error( $response ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return new WP_Error(
|
||||
'attachment_exists',
|
||||
__( 'The attachment already exists.', 'jetpack-import' ),
|
||||
array(
|
||||
'status' => 409,
|
||||
'attachment' => $response,
|
||||
'attachment_id' => $attachment->ID,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$this->set_upload_dir( $request );
|
||||
// Disable scaled image generation.
|
||||
add_filter( 'big_image_size_threshold', '__return_false' );
|
||||
return parent::create_item( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a single attachment.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function update_item( $request ) {
|
||||
$response = parent::update_item( $request );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the schema from additional fields to a schema array.
|
||||
*
|
||||
* The type of object is inferred from the passed schema.
|
||||
*
|
||||
* @param array $schema Schema array.
|
||||
* @return array Modified Schema array.
|
||||
*/
|
||||
public function add_additional_fields_schema( $schema ) {
|
||||
// Validate the upload_date, used for placing the uploaded file in the correct upload directory.
|
||||
$schema['properties']['upload_date'] = array(
|
||||
'description' => __( 'The date for the upload directory of the attachment.', 'jetpack-import' ),
|
||||
'type' => array( 'string', 'null' ),
|
||||
'pattern' => '^\d{4}\/\d{2}$',
|
||||
'required' => false,
|
||||
);
|
||||
|
||||
// The unique identifier is only required for PUT requests.
|
||||
return $this->add_unique_identifier_to_schema( $schema, isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'PUT' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs post-processing on an attachment.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, WP_Error object on failure.
|
||||
*/
|
||||
public function post_process_item( $request ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/image.php';
|
||||
|
||||
\wp_update_image_subsizes( $request['id'] );
|
||||
$request['context'] = 'edit';
|
||||
|
||||
return $this->prepare_item_for_response( \get_post( $request['id'] ), $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter that rewrites the upload path.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception If the date is invalid.
|
||||
*/
|
||||
protected function set_upload_dir( $request ) {
|
||||
|
||||
if ( ! $request->get_param( 'upload_date' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
add_filter(
|
||||
'upload_dir',
|
||||
static function ( $data ) use ( $request ) {
|
||||
$date = $request->get_param( 'upload_date' );
|
||||
$fields_to_rewrite = array( 'path', 'url', 'subdir' );
|
||||
foreach ( $fields_to_rewrite as $field ) {
|
||||
$data[ $field ] = preg_replace( '/\d{4}\/\d{2}$/', $date, $data[ $field ] );
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a single attachment for create or update. This function overrides the parent function
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return \stdClass|WP_Error Post object.
|
||||
*/
|
||||
protected function prepare_item_for_database( $request ) {
|
||||
$prepared_attachment = parent::prepare_item_for_database( $request );
|
||||
// date_gmt is equal to the date by default, so we need to override it.
|
||||
if ( $request->get_param( 'date_gmt' ) ) {
|
||||
$prepared_attachment->post_date_gmt = $request->get_param( 'date_gmt' );
|
||||
}
|
||||
return $prepared_attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the filename and MIME type from the request headers.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
*
|
||||
* @return array An associative array containing the filename and MIME type.
|
||||
*/
|
||||
protected function get_file_info( $request ) {
|
||||
// Get the filename from the Content-Disposition header.
|
||||
$filename_header = $request->get_header( 'content_disposition' );
|
||||
$filename = self::get_filename_from_disposition( (array) $filename_header );
|
||||
$post_date_gmt = $request->get_param( 'date_gmt' );
|
||||
|
||||
// Get the MIME type from the Content-Type header.
|
||||
$mime_type = $request->get_header( 'content_type' );
|
||||
|
||||
return array(
|
||||
'filename' => $filename,
|
||||
'mime_type' => $mime_type,
|
||||
'post_date_gmt' => $post_date_gmt,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve attachment metadata by file information.
|
||||
*
|
||||
* This function retrieves attachment metadata for a given file based on its filename, MIME type, and creation date.
|
||||
*
|
||||
* @param array $fileinfo An associative array containing information about the file. The array must contain the following keys:
|
||||
* - 'filename': The name of the file.
|
||||
* - 'mime_type': The MIME type of the file (e.g. 'image/jpeg').
|
||||
* - 'date': The creation date of the file (e.g. '2022-01-01 12:00:00').
|
||||
*
|
||||
* @return mixed An associative array containing metadata for the attachment, or false if no attachment was found.
|
||||
*/
|
||||
protected function get_attachment_by_file_info( $fileinfo ) {
|
||||
// Make sure all required variables are set and not empty
|
||||
if ( empty( $fileinfo['filename'] ) || empty( $fileinfo['mime_type'] ) ) {
|
||||
return false;
|
||||
}
|
||||
$original_filename = $fileinfo['filename'];
|
||||
$mime_type = $fileinfo['mime_type'];
|
||||
$post_date_gmt = $fileinfo['post_date_gmt'];
|
||||
// From WordPress 5.3, we introduced the scaled image feature, so we'll also need to check for the scaled filename.
|
||||
// https://make.wordpress.org/core/2019/10/09/introducing-handling-of-big-images-in-wordpress-5-3/
|
||||
$extension_pos = strrpos( $original_filename, '.' );
|
||||
$scaled_filename = substr( $original_filename, 0, $extension_pos ) . '-scaled' . substr( $original_filename, $extension_pos );
|
||||
$filename_check_array = array( $original_filename, $scaled_filename );
|
||||
|
||||
$args = array(
|
||||
'post_type' => 'attachment',
|
||||
'post_mime_type' => $mime_type,
|
||||
'date_query' => array(
|
||||
array(
|
||||
'after' => $post_date_gmt,
|
||||
'before' => $post_date_gmt,
|
||||
'inclusive' => true,
|
||||
'column' => 'post_date_gmt',
|
||||
),
|
||||
),
|
||||
'posts_per_page' => 1,
|
||||
);
|
||||
|
||||
$args['meta_query'] = array( 'relation' => 'OR' );
|
||||
foreach ( $filename_check_array as $filename ) {
|
||||
$args['meta_query'][] = array(
|
||||
'key' => '_wp_attached_file',
|
||||
'value' => preg_quote( $filename, '/' ),
|
||||
'compare' => 'REGEXP',
|
||||
);
|
||||
}
|
||||
|
||||
$attachments = \get_posts( $args );
|
||||
|
||||
if ( ! empty( $attachments ) ) {
|
||||
// Return the first attachment data found
|
||||
return $attachments[0];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares an attachment object for REST API response and returns the resulting data as an array.
|
||||
*
|
||||
* @param object $attachment The attachment object to be prepared for response.
|
||||
* @param object $request The REST API request object.
|
||||
*
|
||||
* @return array|WP_Error The prepared data as an array, or a WP_Error object if there was an error preparing the data.
|
||||
*/
|
||||
private function prepare_attachment_for_response( $attachment, $request ) {
|
||||
// Prepare attachment data for response
|
||||
$response = $this->prepare_item_for_response( $attachment, $request );
|
||||
|
||||
// Check if there was an error preparing the data
|
||||
if ( \is_wp_error( $response ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
return (array) $response->get_data();
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Blocks REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Block
|
||||
*/
|
||||
class Block extends \WP_REST_Blocks_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'wp_block' );
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/**
|
||||
* Categories REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Category
|
||||
*/
|
||||
class Category extends \WP_REST_Terms_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching. Default true.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'category' );
|
||||
|
||||
// @see add_term_meta
|
||||
$this->import_id_meta_type = 'term';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the schema from additional fields to a schema array.
|
||||
*
|
||||
* The type of object is inferred from the passed schema.
|
||||
*
|
||||
* @param array $schema Schema array.
|
||||
* @return array Modified Schema array.
|
||||
*/
|
||||
public function add_additional_fields_schema( $schema ) {
|
||||
// Parent term is saved like a slug in WXR so we have to rewrite the schema.
|
||||
$schema['properties']['parent']['description'] = __( 'The parent category slug.', 'jetpack-import' );
|
||||
$schema['properties']['parent']['type'] = 'string';
|
||||
|
||||
// Add the import unique ID to the schema.
|
||||
return $this->add_unique_identifier_to_schema( $schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single category.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
if ( ! empty( $request['parent'] ) ) {
|
||||
$parent = get_term_by( 'slug', $request['parent'], 'category' );
|
||||
|
||||
// Overwrite the parent ID with the parent term ID found using the slug.
|
||||
$request['parent'] = $parent ? $parent->term_id : 0;
|
||||
}
|
||||
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
// Ensure that the HTTP status is a valid one.
|
||||
$response = $this->ensure_http_status( $response, 'term_exists', 409 );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/**
|
||||
* Comments REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Comment
|
||||
*/
|
||||
class Comment extends \WP_REST_Comments_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
// @see add_comment_meta
|
||||
$this->import_id_meta_type = 'comment';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a comment.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
// Resolve comment post ID.
|
||||
if ( ! empty( $request['post'] ) ) {
|
||||
$posts = \get_posts( $this->get_import_db_query( $request['post'] ) );
|
||||
|
||||
// Overwrite the comment parent post ID.
|
||||
$request['post'] = is_array( $posts ) && count( $posts ) ? $posts[0] : 0;
|
||||
}
|
||||
|
||||
// Resolve comment parent ID.
|
||||
if ( ! empty( $request['parent'] ) ) {
|
||||
$comments = \get_comments( $this->get_import_db_query( $request['parent'] ) );
|
||||
|
||||
// Overwrite the comment parent post ID.
|
||||
$request['parent'] = is_array( $comments ) && count( $comments ) ? $comments[0] : 0;
|
||||
}
|
||||
|
||||
$duplicated_id = null;
|
||||
|
||||
/**
|
||||
* Core comment creation function doesn't return the duplicated comment ID.
|
||||
* Add a filter to get the ID.
|
||||
*
|
||||
* phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
*/
|
||||
$get_id_func = function ( $dupe_id, $commentdata ) use ( &$duplicated_id ) {
|
||||
if ( $dupe_id !== null ) {
|
||||
$duplicated_id = $dupe_id;
|
||||
}
|
||||
|
||||
return $dupe_id;
|
||||
};
|
||||
|
||||
// Add the filter.
|
||||
\add_filter( 'duplicate_comment_id', $get_id_func, 10, 2 );
|
||||
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
// Check if the comment is duplicated.
|
||||
if (
|
||||
$duplicated_id !== null &&
|
||||
is_wp_error( $response ) &&
|
||||
$response->get_error_code() === 'comment_duplicate' ) {
|
||||
$data = $response->get_error_data( 'comment_duplicate' );
|
||||
|
||||
// Add the comment ID.
|
||||
$data['comment_id'] = $duplicated_id;
|
||||
|
||||
$response->add_data( $data );
|
||||
}
|
||||
|
||||
// Remove the filter.
|
||||
\remove_filter( 'duplicate_comment_id', $get_id_func );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* Custom CSS REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-includes/theme.php';
|
||||
|
||||
/**
|
||||
* Class Custom_CSS
|
||||
*/
|
||||
class Custom_CSS extends \WP_REST_Posts_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'custom_css' );
|
||||
|
||||
$this->rest_base = 'custom-css';
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the custom CSS post.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
$args = array(
|
||||
'stylesheet' => $request['title'],
|
||||
);
|
||||
|
||||
$post = wp_update_custom_css_post( $request['content'], $args );
|
||||
|
||||
if ( is_wp_error( $post ) ) {
|
||||
return $post;
|
||||
}
|
||||
|
||||
$response = $this->prepare_item_for_response( $post, $request );
|
||||
$response = rest_ensure_response( $response );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
<?php // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
|
||||
/**
|
||||
* End REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class End
|
||||
*
|
||||
* This class is used to start the import process.
|
||||
*/
|
||||
class End extends \WP_REST_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->rest_base = 'end';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the register route options.
|
||||
*
|
||||
* @see register_rest_route()
|
||||
*
|
||||
* @return array The options.
|
||||
*/
|
||||
protected function get_route_options() {
|
||||
return array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'cleanup_database' ),
|
||||
'permission_callback' => array( $this, 'import_permissions_callback' ),
|
||||
'args' => array(),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the start values schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array Item schema data.
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
if ( $this->schema ) {
|
||||
return $this->add_additional_fields_schema( $this->schema );
|
||||
}
|
||||
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'import-end',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'commentmeta_count' => array(
|
||||
'description' => __( 'Comment meta deleted count.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'postmeta_count' => array(
|
||||
'description' => __( 'Post meta deleted count.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'termmeta_count' => array(
|
||||
'description' => __( 'Term meta deleted count.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$this->schema = $schema;
|
||||
|
||||
return $this->add_additional_fields_schema( $this->schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all meta values from database.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or error object on failure.
|
||||
*
|
||||
* phpcs:disable VariableAnalysis.CodeAnalysis.VariableAnalysis.UnusedVariable
|
||||
*/
|
||||
public function cleanup_database( $request ) {
|
||||
global $wpdb;
|
||||
|
||||
$where = array( 'meta_key' => $this->import_id_field_name );
|
||||
|
||||
return array(
|
||||
'commentmeta_count' => $wpdb->delete( $wpdb->commentmeta, $where ),
|
||||
'postmeta_count' => $wpdb->delete( $wpdb->postmeta, $where ),
|
||||
'termmeta_count' => $wpdb->delete( $wpdb->termmeta, $where ),
|
||||
);
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
/**
|
||||
* Global style REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
require_once ABSPATH . 'wp-includes/class-wp-theme-json-resolver.php';
|
||||
require_once ABSPATH . 'wp-includes/theme.php';
|
||||
|
||||
/**
|
||||
* Class Global_Style
|
||||
*/
|
||||
class Global_Style extends \WP_REST_Posts_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'wp_global_styles' );
|
||||
|
||||
$this->rest_base = 'global-styles';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the schema from additional fields to a schema array.
|
||||
*
|
||||
* The type of object is inferred from the passed schema.
|
||||
*
|
||||
* @param array $schema Schema array.
|
||||
* @return array Modified Schema array.
|
||||
*/
|
||||
public function add_additional_fields_schema( $schema ) {
|
||||
$schema['properties']['theme'] = array(
|
||||
'description' => __( 'The name of the theme.', 'jetpack-import' ),
|
||||
'type' => 'string',
|
||||
'required' => true,
|
||||
);
|
||||
|
||||
// The unique identifier is only required for PUT requests.
|
||||
return $this->add_unique_identifier_to_schema( $schema, isset( $_SERVER['REQUEST_METHOD'] ) && $_SERVER['REQUEST_METHOD'] === 'PUT' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the globals style post.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
|
||||
if ( ! class_exists( 'WP_Theme_JSON_Resolver' ) ) {
|
||||
require_once ABSPATH . 'wp-includes/class-wp-theme-json-resolver.php';
|
||||
}
|
||||
|
||||
$theme = \wp_get_theme( $request['theme'] );
|
||||
|
||||
// Check if the theme exists.
|
||||
if ( ! $theme->exists() ) {
|
||||
return new WP_Error(
|
||||
'theme_not_found',
|
||||
__( 'Theme not found.', 'jetpack-import' ),
|
||||
array(
|
||||
'status' => 400,
|
||||
'theme' => $request['theme'],
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the global styles post, or create it.
|
||||
*
|
||||
* A global style post is a post with wp-global-styles-{stylesheet} as post slug.
|
||||
*/
|
||||
$post = \WP_Theme_JSON_Resolver::get_user_data_from_wp_global_styles( $theme, true );
|
||||
|
||||
if ( \is_wp_error( $post ) ) {
|
||||
return $post;
|
||||
}
|
||||
|
||||
$args = array(
|
||||
'ID' => $post['ID'],
|
||||
'post_content' => $request['content'],
|
||||
);
|
||||
|
||||
// Update the post with the passed data.
|
||||
$post_id = wp_update_post( $args, true, false );
|
||||
|
||||
if ( is_wp_error( $post_id ) ) {
|
||||
$post_id->add_data( array( 'status' => 400 ) );
|
||||
|
||||
return $post_id;
|
||||
}
|
||||
|
||||
// Get the post.
|
||||
$post = get_post( $post_id );
|
||||
|
||||
$response = $this->prepare_item_for_response( $post, $request );
|
||||
$response = rest_ensure_response( $response );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
<?php
|
||||
/**
|
||||
* Menu items REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Menu_Item
|
||||
*/
|
||||
class Menu_Item extends \WP_REST_Menu_Items_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching. Default true.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'nav_menu_item' );
|
||||
|
||||
// @see add_term_meta
|
||||
$this->import_id_meta_type = 'post';
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the schema from additional fields to a schema array.
|
||||
*
|
||||
* The type of object is inferred from the passed schema.
|
||||
*
|
||||
* @param array $schema Schema array.
|
||||
* @return array Modified Schema array.
|
||||
*/
|
||||
public function add_additional_fields_schema( $schema ) {
|
||||
// WXR saves menu parent as slug, so we need to overwrite the schema.
|
||||
$schema['properties']['menus']['description'] = __( 'The parent menu slug.', 'jetpack-import' );
|
||||
$schema['properties']['menus']['type'] = 'string';
|
||||
|
||||
// Add the import unique ID to the schema.
|
||||
return $this->add_unique_identifier_to_schema( $schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single menu item.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
|
||||
if ( ! empty( $request['menus'] ) ) {
|
||||
$menu_id = \term_exists( $request['menus'], 'nav_menu' );
|
||||
|
||||
if ( $menu_id ) {
|
||||
// Overwrite the menu item parent menu ID.
|
||||
$request['menus'] = is_array( $menu_id ) ? $menu_id['term_id'] : $menu_id;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! empty( $request['parent'] ) ) {
|
||||
$query = $this->get_import_db_query( $request['parent'] );
|
||||
$query['post_type'] = 'nav_menu_item';
|
||||
$parent = \get_posts( $query );
|
||||
|
||||
// Overwrite the parent ID.
|
||||
$request['parent'] = is_array( $parent ) && count( $parent ) ? $parent[0] : 0;
|
||||
}
|
||||
|
||||
// A menu item can be a custom link or a post, page, category or attachment.
|
||||
if ( ! empty( $request['object_id'] ) ) {
|
||||
$id = null;
|
||||
|
||||
if ( $request['object'] === 'category' ) {
|
||||
if ( $request['object_id'] === 1 ) {
|
||||
// The default category is always ID 1, no need to search.
|
||||
$id = 1;
|
||||
} else {
|
||||
$query = $this->get_import_db_query( $request['object_id'] );
|
||||
$categories = \get_categories( $this->get_import_db_query( $request['object_id'] ) );
|
||||
|
||||
// Overwrite the category ID.
|
||||
$id = is_array( $categories ) && count( $categories ) ? $categories[0] : null;
|
||||
}
|
||||
} elseif ( $request['object'] === 'page' ) {
|
||||
$pages = \get_pages( $this->get_import_db_query( $request['object_id'] ) );
|
||||
|
||||
// Overwrite the page ID.
|
||||
$id = is_array( $pages ) && count( $pages ) ? $pages[0]->ID : null;
|
||||
} elseif ( $request['object'] === 'post' || $request['object'] === 'attachment' ) {
|
||||
$posts = \get_posts( $this->get_import_db_query( $request['object_id'] ) );
|
||||
|
||||
// Overwrite the post ID.
|
||||
$id = is_array( $posts ) && count( $posts ) ? $posts[0] : null;
|
||||
}
|
||||
|
||||
if ( empty( $id ) ) {
|
||||
// Not found the object or a custom menu item, remove the fields.
|
||||
unset( $request['object_id'] );
|
||||
unset( $request['object'] );
|
||||
} else {
|
||||
$request['object_id'] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Menus REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Menu
|
||||
*/
|
||||
class Menu extends \WP_REST_Menus_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching. Default true.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'nav_menu' );
|
||||
|
||||
// @see add_term_meta
|
||||
$this->import_id_meta_type = 'term';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single menu.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
// Ensure that the HTTP status is a valid one.
|
||||
$response = $this->ensure_http_status( $response, 'menu_exists', 409 );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Navigation REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigation Block
|
||||
*/
|
||||
class Navigation extends \WP_REST_Posts_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'wp_navigation' );
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
/**
|
||||
* Pages REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Page
|
||||
*/
|
||||
class Page extends Post {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'page' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single page.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
|
||||
if ( ! empty( $request['parent'] ) ) {
|
||||
$pages = \get_pages( $this->get_import_db_query( $request['parent'] ) );
|
||||
|
||||
// Overwrite the page parent page ID.
|
||||
$request['parent'] = is_array( $pages ) && count( $pages ) ? $pages[0]->ID : 0;
|
||||
}
|
||||
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
<?php
|
||||
/**
|
||||
* Posts REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use Automattic\Jetpack\Sync\Settings;
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'post_exists' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/post.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Post
|
||||
*/
|
||||
class Post extends \WP_REST_Posts_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param string $post_type Post type.
|
||||
*/
|
||||
public function __construct( $post_type = 'post' ) {
|
||||
parent::__construct( $post_type );
|
||||
|
||||
// @see add_post_meta
|
||||
$this->import_id_meta_type = $post_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the schema from additional fields to a schema array.
|
||||
*
|
||||
* The type of object is inferred from the passed schema.
|
||||
*
|
||||
* @param array $schema Schema array.
|
||||
* @return array Modified Schema array.
|
||||
*/
|
||||
public function add_additional_fields_schema( $schema ) {
|
||||
// WXR saves terms as slugs, so we need to overwrite the schema.
|
||||
$schema['properties']['categories']['items']['type'] = 'string';
|
||||
$schema['properties']['tags']['items']['type'] = 'string';
|
||||
|
||||
// Add the import unique ID to the schema.
|
||||
return $this->add_unique_identifier_to_schema( $schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single post.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
|
||||
// Skip if the post already exists.
|
||||
$post_id = \post_exists(
|
||||
$request['title'],
|
||||
'',
|
||||
$request['date'],
|
||||
$this->post_type,
|
||||
$request['status']
|
||||
);
|
||||
|
||||
if ( $post_id ) {
|
||||
return new WP_Error(
|
||||
'post_exists',
|
||||
__( 'Cannot create existing post.', 'jetpack-import' ),
|
||||
array(
|
||||
'status' => 409,
|
||||
'post_id' => $post_id,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// WXR saves terms as slugs, so we need to convert them to IDs before send the data to the legacy endpoint.
|
||||
foreach ( array( 'categories', 'tags' ) as $taxonomy ) {
|
||||
$request[ $taxonomy ] = $this->extract_terms_ids( $request, $taxonomy );
|
||||
}
|
||||
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
// Process post metadata.
|
||||
if ( ! is_wp_error( $response ) && isset( $response->data ) && isset( $response->data['id'] ) ) {
|
||||
$this->process_post_meta( $response->data['id'], $request );
|
||||
}
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract terms IDs from slugs.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @param string $taxonomy Taxonomy name.
|
||||
* @return array List of terms IDs.
|
||||
*/
|
||||
protected function extract_terms_ids( $request, $taxonomy ) {
|
||||
$ret = is_array( $request[ $taxonomy ] ) ? $request[ $taxonomy ] : array();
|
||||
|
||||
if ( ! count( $ret ) ) {
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$taxonomy_name = $taxonomy === 'tags' ? 'post_tag' : 'category';
|
||||
|
||||
// Extract the terms by ID.
|
||||
$ids = $this->get_term_ids_from_slugs( $ret, $taxonomy_name );
|
||||
|
||||
// Create missing terms and add their IDs to the $ids array.
|
||||
$ids = $this->create_missing_terms( $ret, $ids, $taxonomy_name );
|
||||
|
||||
if ( is_array( $ids ) ) {
|
||||
return $ids;
|
||||
} else {
|
||||
// Flush away any invalid terms.
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the metadata of a WordPress post when creating it.
|
||||
*
|
||||
* @param int $post_id The post ID.
|
||||
* @param mixed $request An object containing the metadata being added to the post.
|
||||
* @return void
|
||||
*/
|
||||
public function process_post_meta( $post_id, $request ) {
|
||||
$metas = $request->get_param( 'meta' );
|
||||
|
||||
if ( empty( $metas ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$meta_keys_array = $this->filter_post_meta_keys( $metas );
|
||||
// Adding it to the whitelist
|
||||
Settings::update_settings( array( 'post_meta_whitelist' => $meta_keys_array ) );
|
||||
|
||||
if ( is_array( $metas ) ) {
|
||||
foreach ( $metas as $meta_key => $meta_value ) {
|
||||
|
||||
$meta_value = maybe_unserialize( $meta_value );
|
||||
if ( $meta_key === '_edit_last' ) {
|
||||
update_post_meta( $post_id, $meta_key, $meta_value );
|
||||
} else {
|
||||
// Add the meta data to the post
|
||||
add_post_meta( $post_id, $meta_key, $meta_value );
|
||||
}
|
||||
|
||||
do_action( 'import_post_meta', $post_id, $meta_key, $meta_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters an array of post meta keys.
|
||||
*
|
||||
* @param array $metas An array of metas to filter.
|
||||
* @return array The filtered array of meta keys.
|
||||
*/
|
||||
private function filter_post_meta_keys( $metas ) {
|
||||
// Convert array of keys to a plain array of key strings
|
||||
$meta_keys = array_unique( array_keys( $metas ) );
|
||||
// // Filter the array by removing the excluded keys and any keys that include '_oembed'
|
||||
$filtered_keys = array_filter(
|
||||
$meta_keys,
|
||||
function ( $key ) {
|
||||
// We also don't want to include any oembed post meta because it gets created after a post created
|
||||
return ! str_contains( $key, '_oembed' );
|
||||
}
|
||||
);
|
||||
// Return the filtered array
|
||||
return $filtered_keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get term IDs from slugs.
|
||||
*
|
||||
* @param array $term_slugs Array of term slugs.
|
||||
* @param string $taxonomy_name Taxonomy name.
|
||||
*
|
||||
* @return array Array of term IDs.
|
||||
*/
|
||||
protected function get_term_ids_from_slugs( $term_slugs, $taxonomy_name ) {
|
||||
return get_terms(
|
||||
array(
|
||||
'fields' => 'ids',
|
||||
'hide_empty' => false,
|
||||
'slug' => $term_slugs,
|
||||
'taxonomy' => $taxonomy_name,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create any missing terms in the given taxonomy.
|
||||
*
|
||||
* @param array $term_slugs The slugs of the terms to check for.
|
||||
* @param array $existing_ids The IDs of any terms that already exist.
|
||||
* @param string $taxonomy_name The name of the taxonomy.
|
||||
*
|
||||
* @return array The IDs of any terms that are now in the taxonomy.
|
||||
*/
|
||||
protected function create_missing_terms( $term_slugs, $existing_ids, $taxonomy_name ) {
|
||||
$ids = $existing_ids;
|
||||
|
||||
foreach ( $term_slugs as $term_slug ) {
|
||||
if ( ! term_exists( $term_slug, $taxonomy_name ) ) {
|
||||
$term_name = $this->slug_to_readable_name( $term_slug );
|
||||
$new_term = wp_insert_term( $term_name, $taxonomy_name, array( 'slug' => $term_slug ) );
|
||||
if ( ! is_wp_error( $new_term ) && isset( $new_term['term_id'] ) ) {
|
||||
$ids[] = $new_term['term_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a slug to a readable name.
|
||||
*
|
||||
* @param string $slug Slug to convert.
|
||||
* @return string Converted name.
|
||||
*/
|
||||
protected function slug_to_readable_name( $slug ) {
|
||||
$name = str_replace( array( '-', '_' ), ' ', $slug );
|
||||
$name = ucwords( $name );
|
||||
return $name;
|
||||
}
|
||||
}
|
||||
+158
@@ -0,0 +1,158 @@
|
||||
<?php
|
||||
/**
|
||||
* Start REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use Automattic\Jetpack\Import\Main;
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Start
|
||||
*
|
||||
* This class is used to start the import process.
|
||||
*/
|
||||
class Start extends \WP_REST_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->rest_base = 'start';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the register route options.
|
||||
*
|
||||
* @see register_rest_route()
|
||||
*
|
||||
* @return array The options.
|
||||
*/
|
||||
protected function get_route_options() {
|
||||
return array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_item' ),
|
||||
'permission_callback' => array( $this, 'import_permissions_callback' ),
|
||||
'args' => array(),
|
||||
),
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves main informations.
|
||||
*
|
||||
* @since 4.7.0
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function get_item( $request ) {
|
||||
$items = array(
|
||||
'max_batch_items' => apply_filters( 'rest_get_max_batch_size', 25 ),
|
||||
'max_execution_time' => (int) ini_get( 'max_execution_time' ),
|
||||
'max_input_time' => (int) ini_get( 'max_input_time' ),
|
||||
'mime_types' => get_allowed_mime_types(),
|
||||
'posts_max_id' => (int) $this->get_posts_max_id(),
|
||||
'version' => Main::PACKAGE_VERSION,
|
||||
);
|
||||
|
||||
$response = array();
|
||||
|
||||
foreach ( $items as $name => $value ) {
|
||||
/**
|
||||
* Filters the value of a item recognized by the REST API.
|
||||
*/
|
||||
$response[ $name ] = apply_filters( 'jetpack_import_rest_get_start', $value, $name, $request );
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the start values schema, conforming to JSON Schema.
|
||||
*
|
||||
* @return array Item schema data.
|
||||
*/
|
||||
public function get_item_schema() {
|
||||
if ( $this->schema ) {
|
||||
return $this->add_additional_fields_schema( $this->schema );
|
||||
}
|
||||
|
||||
$schema = array(
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => 'import-start',
|
||||
'type' => 'object',
|
||||
'properties' => array(
|
||||
'max_batch_items' => array(
|
||||
'description' => __( 'Max batch size.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'max_execution_time' => array(
|
||||
'description' => __( 'Max execution time.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'max_input_time' => array(
|
||||
'description' => __( 'Max execution input time.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'mime_types' => array(
|
||||
'description' => __( 'Upload accepted mime types.', 'jetpack-import' ),
|
||||
'type' => 'array',
|
||||
'items' => array( 'type' => 'string' ),
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'posts_max_id' => array(
|
||||
'description' => __( 'Last posts autogenerated ID.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
'version' => array(
|
||||
'description' => __( 'Version of the import package.', 'jetpack-import' ),
|
||||
'type' => 'string',
|
||||
'context' => array( 'view' ),
|
||||
'readonly' => true,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
$this->schema = $schema;
|
||||
|
||||
return $this->add_additional_fields_schema( $this->schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the last posts autogenerated ID.
|
||||
*/
|
||||
private function get_posts_max_id() {
|
||||
global $wpdb;
|
||||
|
||||
// phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
|
||||
$max_id = $wpdb->get_var( "SELECT MAX(ID) FROM $wpdb->posts" );
|
||||
|
||||
return $max_id;
|
||||
}
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
/**
|
||||
* Tags REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Tag
|
||||
*/
|
||||
class Tag extends \WP_REST_Terms_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching. Default true.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'post_tag' );
|
||||
|
||||
// @see add_term_meta
|
||||
$this->import_id_meta_type = 'term';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a tag.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
// Ensure that the HTTP status is a valid one.
|
||||
$response = $this->ensure_http_status( $response, 'term_exists', 409 );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Template parts REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Template_Part
|
||||
*/
|
||||
class Template_Part extends \WP_REST_Templates_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'wp_template_part' );
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Templates REST route
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Template
|
||||
*/
|
||||
class Template extends \WP_REST_Templates_Controller {
|
||||
|
||||
/**
|
||||
* Base class
|
||||
*/
|
||||
use Import;
|
||||
|
||||
/**
|
||||
* The Import ID add a new item to the schema.
|
||||
*/
|
||||
use Import_ID;
|
||||
|
||||
/**
|
||||
* Whether the controller supports batching.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $allow_batch = array( 'v1' => true );
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( 'wp_template' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the template post.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
// Set the WP_IMPORTING constant to prevent sync notifications
|
||||
$this->set_importing();
|
||||
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Import unique import ID.
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import ID trait. Add a unique import ID to the items schema.
|
||||
*/
|
||||
trait Import_ID {
|
||||
|
||||
/**
|
||||
* Meta and REST property name used for storing the WXR import ID.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $import_id_field_name = 'unified_importer_id';
|
||||
|
||||
/**
|
||||
* Import ID meta name.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $import_id_meta_type;
|
||||
|
||||
/**
|
||||
* Adds the schema from additional fields to a schema array.
|
||||
*
|
||||
* The type of object is inferred from the passed schema.
|
||||
*
|
||||
* @param array $schema Schema array.
|
||||
* @return array Modified Schema array.
|
||||
*/
|
||||
public function add_additional_fields_schema( $schema ) {
|
||||
// Add the import unique ID to the schema.
|
||||
return $this->add_unique_identifier_to_schema( $schema );
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a resource.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function create_item( $request ) {
|
||||
$response = parent::create_item( $request );
|
||||
|
||||
return $this->add_import_id_metadata( $request, $response );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the unique identifier to the schema array.
|
||||
*
|
||||
* @param array $schema Schema array.
|
||||
* @param bool $required Whether the field is required.
|
||||
* @return array Modified Schema array.
|
||||
*/
|
||||
protected function add_unique_identifier_to_schema( $schema, $required = true ) {
|
||||
// Add the import unique ID to the schema.
|
||||
$schema['properties'][ $this->import_id_field_name ] = array(
|
||||
'description' => __( 'Jetpack Import unique identifier for the term.', 'jetpack-import' ),
|
||||
'type' => 'integer',
|
||||
'context' => array( 'view', 'embed', 'edit' ),
|
||||
'required' => $required,
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the import unique ID to the resource metadata.
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @param WP_REST_Response $response Response object.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
protected function add_import_id_metadata( $request, $response ) {
|
||||
// Skip on error.
|
||||
if ( is_wp_error( $response ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
$data = $response->get_data();
|
||||
$status = $response->get_status();
|
||||
|
||||
// Skip if the resource has not been added or modified.
|
||||
if ( ! ( $status === 200 || $status === 201 ) ) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Add the import unique ID to the resource metadata.
|
||||
\add_metadata( $this->import_id_meta_type, $data['id'], $this->import_id_field_name, $request[ $this->import_id_field_name ], true );
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the import DB query. This is used to get the items with a specific
|
||||
* meta key that have been imported.
|
||||
*
|
||||
* @param int $parent_import_id The parent import ID.
|
||||
* @return array The query.
|
||||
*/
|
||||
protected function get_import_db_query( $parent_import_id ) {
|
||||
// Get the only one item with the parent import ID.
|
||||
return array(
|
||||
'number' => 1,
|
||||
'fields' => 'ids',
|
||||
'meta_query' => array(
|
||||
array(
|
||||
'key' => $this->import_id_field_name,
|
||||
'value' => $parent_import_id,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/**
|
||||
* Jetpack Import unique import ID.
|
||||
*
|
||||
* @package automattic/jetpack-import
|
||||
*/
|
||||
|
||||
namespace Automattic\Jetpack\Import\Endpoints;
|
||||
|
||||
use WP_Error;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Import trait. Base class for all import endpoints.
|
||||
*
|
||||
* @property array|false $allow_batch Batching details.
|
||||
*/
|
||||
trait Import {
|
||||
/**
|
||||
* REST API namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private static $rest_namespace = 'jetpack/v4/import';
|
||||
|
||||
/**
|
||||
* REST base path.
|
||||
*
|
||||
* @var ?string
|
||||
*/
|
||||
protected $rest_base;
|
||||
|
||||
/**
|
||||
* Registers the routes for the objects of the controller.
|
||||
*
|
||||
* @see WP_REST_Controller::register_rest_route()
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
self::$rest_namespace,
|
||||
'/' . $this->rest_base,
|
||||
$this->get_route_options()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the user has permissions to import.
|
||||
*
|
||||
* @return bool|WP_Error
|
||||
*/
|
||||
public function import_permissions_callback() {
|
||||
// The permission check is done in the REST API authentication. It's the same
|
||||
// as the one used in wp-admin/import.php.
|
||||
if ( \current_user_can( 'import' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$error_msg = \esc_html__(
|
||||
'You are not allowed to perform this action.',
|
||||
'jetpack-import'
|
||||
);
|
||||
|
||||
return new WP_Error( 'rest_forbidden', $error_msg, array( 'status' => \rest_authorization_required_code() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the register route options.
|
||||
*
|
||||
* @see register_rest_route()
|
||||
*
|
||||
* @return array The options.
|
||||
*/
|
||||
protected function get_route_options() {
|
||||
return array(
|
||||
array(
|
||||
'methods' => \WP_REST_Server::CREATABLE,
|
||||
'callback' => array( $this, 'create_item' ),
|
||||
'permission_callback' => array( $this, 'import_permissions_callback' ),
|
||||
'args' => $this->get_endpoint_args_for_item_schema( \WP_REST_Server::CREATABLE ),
|
||||
),
|
||||
'allow_batch' => $this->allow_batch,
|
||||
'schema' => array( $this, 'get_public_item_schema' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the HTTP status is correct.
|
||||
*
|
||||
* @param WP_Error $response Response error object.
|
||||
* @param int $error_code Error code.
|
||||
* @param int $status HTTP status.
|
||||
*/
|
||||
protected function ensure_http_status( $response, $error_code, $status ) {
|
||||
if ( is_wp_error( $response ) && in_array( $error_code, $response->get_error_codes(), true ) ) {
|
||||
$data = $response->get_error_data( $error_code );
|
||||
|
||||
if ( isset( $data['status'] ) ) {
|
||||
$data['status'] = $status;
|
||||
|
||||
$response->add_data( $data );
|
||||
}
|
||||
}
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the importing constant.
|
||||
*/
|
||||
public function set_importing() {
|
||||
if ( ! defined( 'WP_IMPORTING' ) ) {
|
||||
define( 'WP_IMPORTING', true );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user