Commit realizado el 12:13:52 08-04-2024
This commit is contained in:
523
wp-content/plugins/web-stories/includes/Admin/Editor.php
Normal file
523
wp-content/plugins/web-stories/includes/Admin/Editor.php
Normal file
@@ -0,0 +1,523 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Editor
|
||||
*
|
||||
* @link https://github.com/googleforcreators/web-stories-wp
|
||||
*
|
||||
* @copyright 2020 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2020 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Google\Web_Stories\Admin;
|
||||
|
||||
use Google\Web_Stories\Assets;
|
||||
use Google\Web_Stories\Context;
|
||||
use Google\Web_Stories\Decoder;
|
||||
use Google\Web_Stories\Experiments;
|
||||
use Google\Web_Stories\Font_Post_Type;
|
||||
use Google\Web_Stories\Infrastructure\HasRequirements;
|
||||
use Google\Web_Stories\Locale;
|
||||
use Google\Web_Stories\Media\Types;
|
||||
use Google\Web_Stories\Model\Story;
|
||||
use Google\Web_Stories\Page_Template_Post_Type;
|
||||
use Google\Web_Stories\Service_Base;
|
||||
use Google\Web_Stories\Settings;
|
||||
use Google\Web_Stories\Story_Post_Type;
|
||||
use Google\Web_Stories\Tracking;
|
||||
use WP_Post;
|
||||
|
||||
/**
|
||||
* Class Editor
|
||||
*/
|
||||
class Editor extends Service_Base implements HasRequirements {
|
||||
|
||||
/**
|
||||
* Web Stories editor script handle.
|
||||
*/
|
||||
public const SCRIPT_HANDLE = 'web-stories-editor';
|
||||
|
||||
/**
|
||||
* AMP validator script handle.
|
||||
*/
|
||||
public const AMP_VALIDATOR_SCRIPT_HANDLE = 'amp-validator';
|
||||
|
||||
/**
|
||||
* The libheif script handle.
|
||||
*/
|
||||
public const LIBHEIF_SCRIPT_HANDLE = 'web-stories-libheif';
|
||||
|
||||
/**
|
||||
* Experiments instance.
|
||||
*
|
||||
* @var Experiments Experiments instance.
|
||||
*/
|
||||
private Experiments $experiments;
|
||||
|
||||
/**
|
||||
* Decoder instance.
|
||||
*
|
||||
* @var Decoder Decoder instance.
|
||||
*/
|
||||
private Decoder $decoder;
|
||||
|
||||
/**
|
||||
* Meta boxes instance.
|
||||
*
|
||||
* @var Meta_Boxes Meta_Boxes instance.
|
||||
*/
|
||||
private Meta_Boxes $meta_boxes;
|
||||
|
||||
/**
|
||||
* Locale instance.
|
||||
*
|
||||
* @var Locale Locale instance.
|
||||
*/
|
||||
private Locale $locale;
|
||||
|
||||
/**
|
||||
* Google_Fonts instance.
|
||||
*
|
||||
* @var Google_Fonts Google_Fonts instance.
|
||||
*/
|
||||
private Google_Fonts $google_fonts;
|
||||
|
||||
/**
|
||||
* Assets instance.
|
||||
*
|
||||
* @var Assets Assets instance.
|
||||
*/
|
||||
private Assets $assets;
|
||||
|
||||
/**
|
||||
* Story_Post_Type instance.
|
||||
*
|
||||
* @var Story_Post_Type Story_Post_Type instance.
|
||||
*/
|
||||
private Story_Post_Type $story_post_type;
|
||||
|
||||
/**
|
||||
* Page_Template_Post_Type instance.
|
||||
*
|
||||
* @var Page_Template_Post_Type Page_Template_Post_Type instance.
|
||||
*/
|
||||
private Page_Template_Post_Type $page_template_post_type;
|
||||
|
||||
/**
|
||||
* Font_Post_Type instance.
|
||||
*
|
||||
* @var Font_Post_Type Font_Post_Type instance.
|
||||
*/
|
||||
private Font_Post_Type $font_post_type;
|
||||
|
||||
/**
|
||||
* Context instance.
|
||||
*
|
||||
* @var Context Context instance.
|
||||
*/
|
||||
private Context $context;
|
||||
|
||||
/**
|
||||
* Types instance.
|
||||
*
|
||||
* @var Types Types instance.
|
||||
*/
|
||||
private Types $types;
|
||||
|
||||
/**
|
||||
* Settings instance.
|
||||
*
|
||||
* @var Settings Settings instance.
|
||||
*/
|
||||
private Settings $settings;
|
||||
|
||||
/**
|
||||
* Dashboard constructor.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param Experiments $experiments Experiments instance.
|
||||
* @param Meta_Boxes $meta_boxes Meta_Boxes instance.
|
||||
* @param Decoder $decoder Decoder instance.
|
||||
* @param Locale $locale Locale instance.
|
||||
* @param Google_Fonts $google_fonts Google_Fonts instance.
|
||||
* @param Assets $assets Assets instance.
|
||||
* @param Story_Post_Type $story_post_type Story_Post_Type instance.
|
||||
* @param Page_Template_Post_Type $page_template_post_type Page_Template_Post_Type instance.
|
||||
* @param Font_Post_Type $font_post_type Font_Post_Type instance.
|
||||
* @param Context $context Context instance.
|
||||
* @param Types $types Types instance.
|
||||
* @param Settings $settings Settings instance.
|
||||
*/
|
||||
public function __construct(
|
||||
Experiments $experiments,
|
||||
Meta_Boxes $meta_boxes,
|
||||
Decoder $decoder,
|
||||
Locale $locale,
|
||||
Google_Fonts $google_fonts,
|
||||
Assets $assets,
|
||||
Story_Post_Type $story_post_type,
|
||||
Page_Template_Post_Type $page_template_post_type,
|
||||
Font_Post_Type $font_post_type,
|
||||
Context $context,
|
||||
Types $types,
|
||||
Settings $settings
|
||||
) {
|
||||
$this->experiments = $experiments;
|
||||
$this->meta_boxes = $meta_boxes;
|
||||
$this->decoder = $decoder;
|
||||
$this->locale = $locale;
|
||||
$this->google_fonts = $google_fonts;
|
||||
$this->assets = $assets;
|
||||
$this->story_post_type = $story_post_type;
|
||||
$this->page_template_post_type = $page_template_post_type;
|
||||
$this->font_post_type = $font_post_type;
|
||||
$this->context = $context;
|
||||
$this->types = $types;
|
||||
$this->settings = $settings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the Editor logic.
|
||||
*
|
||||
* @since 1.7.0
|
||||
*/
|
||||
public function register(): void {
|
||||
add_action( 'admin_enqueue_scripts', [ $this, 'admin_enqueue_scripts' ] );
|
||||
add_filter( 'replace_editor', [ $this, 'replace_editor' ], 10, 2 );
|
||||
add_filter( 'use_block_editor_for_post_type', [ $this, 'filter_use_block_editor_for_post_type' ], 10, 2 );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of service IDs required for this service to be registered.
|
||||
*
|
||||
* Needed because the story and page template post types need to be registered first.
|
||||
*
|
||||
* @since 1.14.0
|
||||
*
|
||||
* @return string[] List of required services.
|
||||
*/
|
||||
public static function get_requirements(): array {
|
||||
return [ 'page_template_post_type', 'story_post_type' ];
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace default post editor with our own implementation.
|
||||
*
|
||||
* @codeCoverageIgnore
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param bool|mixed $replace Bool if to replace editor or not.
|
||||
* @param WP_Post $post Current post object.
|
||||
* @return bool|mixed Whether the editor has been replaced.
|
||||
*/
|
||||
public function replace_editor( $replace, WP_Post $post ) {
|
||||
if ( $this->story_post_type->get_slug() === get_post_type( $post ) ) {
|
||||
|
||||
$script_dependencies = [
|
||||
Tracking::SCRIPT_HANDLE,
|
||||
'postbox',
|
||||
self::AMP_VALIDATOR_SCRIPT_HANDLE,
|
||||
self::LIBHEIF_SCRIPT_HANDLE,
|
||||
];
|
||||
|
||||
// Registering here because the script handle is required for wp_add_inline_script in edit-story.php.
|
||||
$this->assets->register_script_asset( self::SCRIPT_HANDLE, $script_dependencies, false );
|
||||
|
||||
// Since the 'replace_editor' filter can be run multiple times, only load the
|
||||
// custom editor after the 'current_screen' action and when we can be certain the
|
||||
// $post_type, $post_type_object, $post globals are all set by WordPress.
|
||||
if ( isset( $GLOBALS['post'] ) && $post === $GLOBALS['post'] && did_action( 'current_screen' ) ) {
|
||||
require_once WEBSTORIES_PLUGIN_DIR_PATH . 'includes/templates/admin/edit-story.php';
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return $replace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters whether post type supports the block editor.
|
||||
*
|
||||
* Disables the block editor and associated logic (like enqueueing assets)
|
||||
* for the story post type.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param bool|mixed $use_block_editor Whether the post type can be edited or not. Default true.
|
||||
* @param string $post_type The post type being checked.
|
||||
* @return false|mixed Whether to use the block editor.
|
||||
*/
|
||||
public function filter_use_block_editor_for_post_type( $use_block_editor, string $post_type ) {
|
||||
if ( $this->story_post_type->get_slug() === $post_type ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $use_block_editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue scripts for the element editor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param string $hook The current admin page.
|
||||
*/
|
||||
public function admin_enqueue_scripts( string $hook ): void {
|
||||
if ( ! $this->context->is_story_editor() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only output scripts and styles where in edit screens.
|
||||
if ( ! \in_array( $hook, [ 'post.php', 'post-new.php' ], true ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Force media model to load.
|
||||
wp_enqueue_media();
|
||||
|
||||
wp_enqueue_script(
|
||||
self::AMP_VALIDATOR_SCRIPT_HANDLE,
|
||||
'https://cdn.ampproject.org/v0/validator_wasm.js',
|
||||
[],
|
||||
WEBSTORIES_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
|
||||
wp_enqueue_script(
|
||||
self::LIBHEIF_SCRIPT_HANDLE,
|
||||
trailingslashit( WEBSTORIES_CDN_URL ) . 'js/libheif-js@1.14.0/libheif.js',
|
||||
[],
|
||||
WEBSTORIES_VERSION,
|
||||
true
|
||||
);
|
||||
|
||||
wp_enqueue_script( self::SCRIPT_HANDLE );
|
||||
$this->assets->enqueue_style_asset( self::SCRIPT_HANDLE, [ $this->google_fonts::SCRIPT_HANDLE ] );
|
||||
|
||||
wp_localize_script(
|
||||
self::SCRIPT_HANDLE,
|
||||
'webStories',
|
||||
[
|
||||
'publicPath' => $this->assets->get_base_url( 'assets/js/' ), // Required before the editor script is enqueued.
|
||||
'localeData' => $this->assets->get_translations( self::SCRIPT_HANDLE ), // Required for i18n setLocaleData.
|
||||
]
|
||||
);
|
||||
|
||||
// Dequeue forms.css, see https://github.com/googleforcreators/web-stories-wp/issues/349 .
|
||||
$this->assets->remove_admin_style( [ 'forms' ] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get editor settings as an array.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @return array<string,mixed> Editor settings.
|
||||
*/
|
||||
public function get_editor_settings(): array {
|
||||
$post = get_post();
|
||||
$story_id = $post->ID ?? null;
|
||||
$general_settings_url = admin_url( 'options-general.php' );
|
||||
|
||||
if ( $story_id ) {
|
||||
$this->setup_lock( $story_id );
|
||||
}
|
||||
|
||||
// Media settings.
|
||||
$max_upload_size = wp_max_upload_size();
|
||||
if ( ! $max_upload_size ) {
|
||||
$max_upload_size = 0;
|
||||
}
|
||||
|
||||
$dashboard_url = add_query_arg(
|
||||
[
|
||||
'post_type' => $this->story_post_type->get_slug(),
|
||||
'page' => 'stories-dashboard',
|
||||
],
|
||||
admin_url( 'edit.php' )
|
||||
);
|
||||
|
||||
$revision_url = admin_url( 'revision.php' );
|
||||
|
||||
$dashboard_settings_url = add_query_arg(
|
||||
[
|
||||
'post_type' => $this->story_post_type->get_slug(),
|
||||
'page' => 'stories-dashboard#/editor-settings',
|
||||
],
|
||||
admin_url( 'edit.php' )
|
||||
);
|
||||
|
||||
$user = wp_get_current_user();
|
||||
|
||||
/** This filter is documented in wp-admin/includes/post.php */
|
||||
$show_locked_dialog = apply_filters( 'show_post_locked_dialog', true, $post, $user );
|
||||
$nonce = wp_create_nonce( 'wp_rest' );
|
||||
|
||||
$story = new Story();
|
||||
$story->load_from_post( $post );
|
||||
|
||||
// Explicitly setting these flags which became the default in PHP 8.1.
|
||||
// Needed for correct single quotes in the editor & output.
|
||||
// See https://github.com/GoogleForCreators/web-stories-wp/issues/10809.
|
||||
$publisher_name = html_entity_decode( $story->get_publisher_name(), ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 );
|
||||
|
||||
$shopping_provider = $this->settings->get_setting( $this->settings::SETTING_NAME_SHOPPING_PROVIDER );
|
||||
|
||||
$auto_advance = $this->settings->get_setting( $this->settings::SETTING_NAME_AUTO_ADVANCE );
|
||||
|
||||
$page_duration = $this->settings->get_setting( $this->settings::SETTING_NAME_DEFAULT_PAGE_DURATION );
|
||||
|
||||
$auto_save_link = '';
|
||||
|
||||
if ( isset( $story_id ) ) {
|
||||
|
||||
$auto_save = wp_get_post_autosave( $story_id );
|
||||
|
||||
if ( $auto_save && $post ) {
|
||||
if ( mysql2date( 'U', $auto_save->post_modified_gmt, false ) > mysql2date( 'U', $post->post_modified_gmt, false ) ) {
|
||||
$auto_save_link = get_edit_post_link( $auto_save->ID );
|
||||
} else {
|
||||
wp_delete_post_revision( $auto_save->ID );
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Revision.
|
||||
*
|
||||
* @var int $revision
|
||||
*/
|
||||
$revision = isset( $_GET['revision'] ) ? absint( $_GET['revision'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
$revision_message = ! empty( $revision ) ?
|
||||
sprintf(
|
||||
/* translators: %s: Date and time of the revision. */
|
||||
__( 'Story restored to revision from %s.', 'web-stories' ),
|
||||
wp_post_revision_title( $revision, false )
|
||||
)
|
||||
: false;
|
||||
|
||||
$settings = [
|
||||
'autoSaveInterval' => \defined( 'AUTOSAVE_INTERVAL' ) ? AUTOSAVE_INTERVAL : null,
|
||||
'localAutoSaveInterval' => 15,
|
||||
'autoSaveLink' => $auto_save_link,
|
||||
'isRTL' => is_rtl(),
|
||||
'locale' => $this->locale->get_locale_settings(),
|
||||
'allowedMimeTypes' => $this->types->get_allowed_mime_types(),
|
||||
'postType' => $this->story_post_type->get_slug(),
|
||||
'storyId' => $story_id,
|
||||
'dashboardLink' => $dashboard_url,
|
||||
'revisionLink' => $revision_url,
|
||||
'revisionMessage' => $revision_message,
|
||||
'dashboardSettingsLink' => $dashboard_settings_url,
|
||||
'generalSettingsLink' => $general_settings_url,
|
||||
'cdnURL' => trailingslashit( WEBSTORIES_CDN_URL ),
|
||||
'maxUpload' => $max_upload_size,
|
||||
'editPostsCapabilityName' => $this->story_post_type->get_cap_name( 'edit_posts' ),
|
||||
'capabilities' => [
|
||||
'hasUploadMediaAction' => current_user_can( 'upload_files' ),
|
||||
'canManageSettings' => current_user_can( 'manage_options' ),
|
||||
],
|
||||
'api' => [
|
||||
'users' => '/web-stories/v1/users/',
|
||||
'currentUser' => '/web-stories/v1/users/me/',
|
||||
'stories' => trailingslashit( $this->story_post_type->get_rest_url() ),
|
||||
'pageTemplates' => trailingslashit( $this->page_template_post_type->get_rest_url() ),
|
||||
'media' => '/web-stories/v1/media/',
|
||||
'hotlink' => '/web-stories/v1/hotlink/validate/',
|
||||
'publisherLogos' => '/web-stories/v1/publisher-logos/',
|
||||
'products' => '/web-stories/v1/products/',
|
||||
'proxy' => rest_url( '/web-stories/v1/hotlink/proxy/' ),
|
||||
'link' => '/web-stories/v1/link/',
|
||||
'statusCheck' => '/web-stories/v1/status-check/',
|
||||
'taxonomies' => '/web-stories/v1/taxonomies/',
|
||||
'fonts' => trailingslashit( $this->font_post_type->get_rest_url() ),
|
||||
'metaBoxes' => $this->meta_boxes->get_meta_box_url( (int) $story_id ),
|
||||
'storyLocking' => rest_url( sprintf( '%s/%s/lock/', $this->story_post_type->get_rest_url(), $story_id ) ),
|
||||
],
|
||||
'metadata' => [
|
||||
'publisher' => $publisher_name,
|
||||
],
|
||||
'postLock' => [
|
||||
'interval' => 60,
|
||||
'showLockedDialog' => $show_locked_dialog,
|
||||
],
|
||||
'canViewDefaultTemplates' => true,
|
||||
'version' => WEBSTORIES_VERSION,
|
||||
'nonce' => $nonce,
|
||||
'showMedia3p' => true,
|
||||
'globalAutoAdvance' => (bool) $auto_advance,
|
||||
'globalPageDuration' => (float) $page_duration,
|
||||
'shoppingProvider' => $shopping_provider,
|
||||
'encodeMarkup' => $this->decoder->supports_decoding(),
|
||||
'metaBoxes' => $this->meta_boxes->get_meta_boxes_per_location(),
|
||||
'ffmpegCoreUrl' => trailingslashit( WEBSTORIES_CDN_URL ) . 'js/@ffmpeg/core@0.11.0/dist/ffmpeg-core.js',
|
||||
'mediainfoUrl' => trailingslashit( WEBSTORIES_CDN_URL ) . 'js/mediainfo.js@0.1.9/dist/MediaInfoModule.wasm',
|
||||
'flags' => array_merge(
|
||||
$this->experiments->get_experiment_statuses( 'general' ),
|
||||
$this->experiments->get_experiment_statuses( 'editor' ),
|
||||
),
|
||||
];
|
||||
|
||||
/**
|
||||
* Filters settings passed to the web stories editor.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
* @param array $settings Array of settings passed to web stories editor.
|
||||
*/
|
||||
return apply_filters( 'web_stories_editor_settings', $settings );
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup up post lock.
|
||||
*
|
||||
* @since 1.5.0
|
||||
*
|
||||
* @param int $story_id Post id of story.
|
||||
*/
|
||||
protected function setup_lock( int $story_id ): void {
|
||||
if ( ! $this->story_post_type->has_cap( 'edit_posts' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure these functions are loaded.
|
||||
if (
|
||||
! \function_exists( '\wp_check_post_lock' ) ||
|
||||
! \function_exists( '\wp_set_post_lock' )
|
||||
) {
|
||||
require_once ABSPATH . 'wp-admin/includes/post.php';
|
||||
}
|
||||
|
||||
// Check current lock.
|
||||
$lock_user_id = wp_check_post_lock( $story_id );
|
||||
if ( ! $lock_user_id ) {
|
||||
// If no lock set, create new lock.
|
||||
wp_set_post_lock( $story_id );
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user