Divi.php
204 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Handles divi integration related functionality. |
| 4 | * |
| 5 | * @package presto-player |
| 6 | */ |
| 7 | |
| 8 | namespace PrestoPlayer\Integrations\Divi; |
| 9 | |
| 10 | use PrestoPlayer\Models\ReusableVideo; |
| 11 | use PrestoPlayer\Models\Post; |
| 12 | |
| 13 | /** |
| 14 | * Handles divi-related functionality |
| 15 | */ |
| 16 | class Divi { |
| 17 | |
| 18 | /** |
| 19 | * Registers the Divi integration. |
| 20 | */ |
| 21 | public function register() { |
| 22 | add_action( 'divi_module_library_modules_dependency_tree', array( $this, 'register_d5_modules' ) ); |
| 23 | add_action( 'et_fb_framework_loaded', array( $this, 'register_d5_builder_assets' ) ); |
| 24 | add_action( 'divi_extensions_init', array( $this, 'init' ) ); |
| 25 | add_action( 'wp_ajax_presto_get_media_attributes', array( $this, 'getMediaItemAttributes' ) ); |
| 26 | } |
| 27 | |
| 28 | /** |
| 29 | * Registers D5 module dependencies with the Divi module library. |
| 30 | * |
| 31 | * @param object $tree The Divi module dependency tree. |
| 32 | * @return void |
| 33 | */ |
| 34 | public function register_d5_modules( $tree ) { |
| 35 | $tree->add_dependency( new D5\PrestoVideoModule() ); |
| 36 | } |
| 37 | |
| 38 | /** |
| 39 | * Registers and enqueues the D5 builder script package. |
| 40 | * |
| 41 | * @return void |
| 42 | */ |
| 43 | public function register_d5_builder_assets() { |
| 44 | if ( ! class_exists( 'ET\\Builder\\VisualBuilder\\Assets\\PackageBuildManager' ) ) { |
| 45 | return; |
| 46 | } |
| 47 | $asset_file = PRESTO_PLAYER_PLUGIN_DIR . 'dist/divi-d5.asset.php'; |
| 48 | if ( ! file_exists( $asset_file ) ) { |
| 49 | return; |
| 50 | } |
| 51 | $asset = include $asset_file; |
| 52 | if ( ! is_array( $asset ) || empty( $asset['version'] ) || ! isset( $asset['dependencies'] ) ) { |
| 53 | return; |
| 54 | } |
| 55 | $data = array( |
| 56 | 'ajaxurl' => admin_url( 'admin-ajax.php' ), |
| 57 | 'nonce' => wp_create_nonce( 'wp_rest' ), |
| 58 | ); |
| 59 | // PackageBuildManager localizes data_top_window/data_app_window under a global named |
| 60 | // pascal_case( name . 'Data' ) — so 'presto-player-divi-d5' exposes window.PrestoPlayerDiviD5Data, |
| 61 | // which is exactly what MediaHubField.jsx / PlayerEdit.jsx read. Keep the name in sync with that. |
| 62 | \ET\Builder\VisualBuilder\Assets\PackageBuildManager::register_package_build( |
| 63 | array( |
| 64 | 'name' => 'presto-player-divi-d5', |
| 65 | 'version' => $asset['version'], |
| 66 | 'script' => array( |
| 67 | 'src' => PRESTO_PLAYER_PLUGIN_URL . 'dist/divi-d5.js', |
| 68 | 'deps' => array_merge( $asset['dependencies'], array( 'divi-module-library' ) ), |
| 69 | 'args' => array( 'in_footer' => true ), |
| 70 | 'enqueue_top_window' => true, |
| 71 | 'enqueue_app_window' => true, |
| 72 | 'data_top_window' => $data, |
| 73 | 'data_app_window' => $data, |
| 74 | ), |
| 75 | ) |
| 76 | ); |
| 77 | } |
| 78 | |
| 79 | /** |
| 80 | * Initializes the Divi integration. |
| 81 | */ |
| 82 | public function init() { |
| 83 | // require our module. |
| 84 | include_once 'includes/PrestoDiviExtension.php'; |
| 85 | |
| 86 | // enqueue the scripts. |
| 87 | add_action( 'wp_enqueue_scripts', array( $this, 'enqueueScripts' ) ); |
| 88 | |
| 89 | // fix rankmath conflict. |
| 90 | add_filter( 'script_loader_tag', array( $this, 'rankMathFix' ), 11, 3 ); |
| 91 | |
| 92 | // parse the divi block to get the inner media hub block. |
| 93 | add_filter( 'presto_player_get_block_from_content', array( $this, 'getInnerBlockFromDiviContent' ) ); |
| 94 | } |
| 95 | |
| 96 | /** |
| 97 | * Gets the inner media hub block from the divi content for lessons and topics. |
| 98 | * |
| 99 | * @param array $block the Divi block array. |
| 100 | * |
| 101 | * @return array $block the filtered media hub inner block array. |
| 102 | */ |
| 103 | public function getInnerBlockFromDiviContent( $block ) { |
| 104 | // bail if block is empty. |
| 105 | if ( empty( $block ) ) { |
| 106 | return $block; |
| 107 | } |
| 108 | |
| 109 | $pattern = get_shortcode_regex( array( 'prpl_presto_player' ) ); |
| 110 | $block_id = false; |
| 111 | if ( $block['innerHTML'] && preg_match( "/$pattern/", $block['innerHTML'], $matches ) ) { |
| 112 | $shortcode = $matches[0] ?? ''; |
| 113 | if ( ! empty( $shortcode ) ) { |
| 114 | $atts = shortcode_parse_atts( $shortcode ); |
| 115 | $block_id = isset( $atts['video_id'] ) ? (int) $atts['video_id'] : false; |
| 116 | } |
| 117 | } |
| 118 | if ( ! empty( $block_id ) ) { |
| 119 | $post_model = new Post( get_post( $block_id ) ); |
| 120 | $block = $post_model->getMediaHubBlockFromPost( $block_id ); |
| 121 | if ( ! empty( $block ) ) { |
| 122 | return $block; |
| 123 | } |
| 124 | } |
| 125 | return $block; |
| 126 | } |
| 127 | |
| 128 | /** |
| 129 | * Fixes rankmath excluding wp-i18n script from iframe. |
| 130 | * |
| 131 | * @param string $tag The <script> tag for the enqueued script. |
| 132 | * @param string $handle The script's registered handle. |
| 133 | * @param string $src The script's source URL. |
| 134 | * |
| 135 | * @return string |
| 136 | */ |
| 137 | public function rankMathFix( $tag, $handle, $src ) { |
| 138 | if ( 'wp-i18n' === $handle ) { |
| 139 | return '<script type="text/javascript" src="' . $src . '"></script>' . "\n"; // phpcs:ignore |
| 140 | } |
| 141 | return $tag; |
| 142 | } |
| 143 | |
| 144 | /** |
| 145 | * Get attributes to inject into JSX component. |
| 146 | * |
| 147 | * AJAX callback (wp_ajax_presto_get_media_attributes); reads the id from $_POST |
| 148 | * and always responds via wp_send_json_*. |
| 149 | * |
| 150 | * @return void |
| 151 | */ |
| 152 | public function getMediaItemAttributes() { |
| 153 | // D4 sends et_admin_load_nonce; D5 sends wp_rest nonce via prestoPlayer.nonce. |
| 154 | // wp_rest is a broad, shared nonce, so the current_user_can() check below is the real |
| 155 | // authorization gate here — don't drop it assuming the nonce alone scopes access. |
| 156 | $nonce = isset( $_POST['_wpnonce'] ) ? sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ) : ''; |
| 157 | $valid = wp_verify_nonce( $nonce, 'et_admin_load_nonce' ) |
| 158 | || wp_verify_nonce( $nonce, 'wp_rest' ); |
| 159 | if ( ! $valid ) { |
| 160 | wp_send_json_error( array( 'message' => __( 'Invalid nonce.', 'presto-player' ) ), 403 ); |
| 161 | } |
| 162 | |
| 163 | if ( ! current_user_can( 'edit_posts' ) ) { |
| 164 | wp_send_json_error( array( 'message' => __( 'You are not allowed to do this.', 'presto-player' ) ), 403 ); |
| 165 | } |
| 166 | |
| 167 | $id = isset( $_POST['id'] ) ? absint( wp_unslash( $_POST['id'] ) ) : 0; |
| 168 | |
| 169 | if ( ! $id ) { |
| 170 | wp_send_json_error( array( 'message' => __( 'You must provide an id.', 'presto-player' ) ), 400 ); |
| 171 | } |
| 172 | |
| 173 | $video = new ReusableVideo( $id ); |
| 174 | if ( ! $video->post || 'pp_video_block' !== $video->post->post_type ) { |
| 175 | wp_send_json_error( array( 'message' => __( 'Video not found.', 'presto-player' ) ), 404 ); |
| 176 | } |
| 177 | |
| 178 | wp_send_json_success( $video->getAttributes() ); |
| 179 | } |
| 180 | |
| 181 | /** |
| 182 | * Enqueues scripts for Divi integration. |
| 183 | */ |
| 184 | public function enqueueScripts() { |
| 185 | if ( ! et_core_is_fb_enabled() ) { |
| 186 | return; |
| 187 | } |
| 188 | |
| 189 | $assets = include trailingslashit( PRESTO_PLAYER_PLUGIN_DIR ) . 'dist/divi.asset.php'; |
| 190 | wp_enqueue_script( |
| 191 | 'surecart/divi/admin', |
| 192 | trailingslashit( PRESTO_PLAYER_PLUGIN_URL ) . 'dist/divi.js', |
| 193 | array_merge( array( 'react-dom', 'jquery', 'hls.js' ), $assets['dependencies'] ), |
| 194 | $assets['version'], |
| 195 | true |
| 196 | ); |
| 197 | wp_enqueue_style( 'surecart/divi/admin', trailingslashit( PRESTO_PLAYER_PLUGIN_URL ) . 'dist/divi.css', array(), $assets['version'] ); |
| 198 | |
| 199 | if ( function_exists( 'wp_set_script_translations' ) ) { |
| 200 | wp_set_script_translations( 'surecart/divi/admin', 'presto-player' ); |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 |