preview.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. <?php
  2. namespace Elementor;
  3. if ( ! defined( 'ABSPATH' ) ) {
  4. exit; // Exit if accessed directly.
  5. }
  6. /**
  7. * Elementor preview.
  8. *
  9. * Elementor preview handler class is responsible for initializing Elementor in
  10. * preview mode.
  11. *
  12. * @since 1.0.0
  13. */
  14. class Preview {
  15. /**
  16. * Post ID.
  17. *
  18. * Holds the ID of the current post being previewed.
  19. *
  20. * @since 1.0.0
  21. * @access private
  22. *
  23. * @var int Post ID.
  24. */
  25. private $post_id;
  26. /**
  27. * Init.
  28. *
  29. * Initialize Elementor preview mode.
  30. *
  31. * Fired by `template_redirect` action.
  32. *
  33. * @since 1.0.0
  34. * @access public
  35. */
  36. public function init() {
  37. if ( is_admin() || ! $this->is_preview_mode() ) {
  38. return;
  39. }
  40. $this->post_id = get_the_ID();
  41. // Don't redirect to permalink.
  42. remove_action( 'template_redirect', 'redirect_canonical' );
  43. // Compatibility with Yoast SEO plugin when 'Removes unneeded query variables from the URL' enabled.
  44. // TODO: Move this code to `includes/compatibility.php`.
  45. if ( class_exists( 'WPSEO_Frontend' ) ) {
  46. remove_action( 'template_redirect', [ \WPSEO_Frontend::get_instance(), 'clean_permalink' ], 1 );
  47. }
  48. // Disable the WP admin bar in preview mode.
  49. add_filter( 'show_admin_bar', '__return_false' );
  50. add_action( 'wp_enqueue_scripts', function() {
  51. $this->enqueue_styles();
  52. $this->enqueue_scripts();
  53. } );
  54. add_filter( 'the_content', [ $this, 'builder_wrapper' ], 999999 );
  55. add_action( 'wp_footer', [ $this, 'wp_footer' ] );
  56. // Tell to WP Cache plugins do not cache this request.
  57. Utils::do_not_cache();
  58. /**
  59. * Preview init.
  60. *
  61. * Fires on Elementor preview init, after Elementor preview has finished
  62. * loading but before any headers are sent.
  63. *
  64. * @since 1.0.0
  65. *
  66. * @param Preview $this The current preview.
  67. */
  68. do_action( 'elementor/preview/init', $this );
  69. }
  70. /**
  71. * Retrieve post ID.
  72. *
  73. * Get the ID of the current post.
  74. *
  75. * @since 1.8.0
  76. * @access public
  77. *
  78. * @return int Post ID.
  79. */
  80. public function get_post_id() {
  81. return $this->post_id;
  82. }
  83. /**
  84. * Whether preview mode is active.
  85. *
  86. * Used to determine whether we are in the preview mode (iframe).
  87. *
  88. * @since 1.0.0
  89. * @access public
  90. *
  91. * @param int $post_id Optional. Post ID. Default is `0`.
  92. *
  93. * @return bool Whether preview mode is active.
  94. */
  95. public function is_preview_mode( $post_id = 0 ) {
  96. if ( empty( $post_id ) ) {
  97. $post_id = get_the_ID();
  98. }
  99. if ( ! User::is_current_user_can_edit( $post_id ) ) {
  100. return false;
  101. }
  102. if ( ! isset( $_GET['elementor-preview'] ) || $post_id !== (int) $_GET['elementor-preview'] ) {
  103. return false;
  104. }
  105. return true;
  106. }
  107. /**
  108. * Builder wrapper.
  109. *
  110. * Used to add an empty HTML wrapper for the builder, the javascript will add
  111. * the content later.
  112. *
  113. * @since 1.0.0
  114. * @access public
  115. *
  116. * @param string $content The content of the builder.
  117. *
  118. * @return string HTML wrapper for the builder.
  119. */
  120. public function builder_wrapper( $content ) {
  121. if ( get_the_ID() === $this->post_id ) {
  122. $classes = 'elementor-edit-mode';
  123. $document = Plugin::$instance->documents->get( $this->post_id );
  124. if ( $document ) {
  125. $classes .= ' ' . $document->get_container_classes();
  126. }
  127. $content = '<div id="elementor" class="' . $classes . '"></div>';
  128. }
  129. return $content;
  130. }
  131. /**
  132. * Enqueue preview styles.
  133. *
  134. * Registers all the preview styles and enqueues them.
  135. *
  136. * Fired by `wp_enqueue_scripts` action.
  137. *
  138. * @since 1.0.0
  139. * @access private
  140. */
  141. private function enqueue_styles() {
  142. // Hold-on all jQuery plugins after all HTML markup render.
  143. wp_add_inline_script( 'jquery-migrate', 'jQuery.holdReady( true );' );
  144. Plugin::$instance->frontend->enqueue_styles();
  145. $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
  146. $direction_suffix = is_rtl() ? '-rtl' : '';
  147. wp_register_style(
  148. 'elementor-select2',
  149. ELEMENTOR_ASSETS_URL . 'lib/e-select2/css/e-select2' . $suffix . '.css',
  150. [],
  151. '4.0.6-rc.1'
  152. );
  153. wp_register_style(
  154. 'editor-preview',
  155. ELEMENTOR_ASSETS_URL . 'css/editor-preview' . $direction_suffix . $suffix . '.css',
  156. [
  157. 'elementor-select2',
  158. ],
  159. ELEMENTOR_VERSION
  160. );
  161. wp_enqueue_style( 'editor-preview' );
  162. /**
  163. * Preview enqueue styles.
  164. *
  165. * Fires after Elementor preview styles are enqueued.
  166. *
  167. * @since 1.0.0
  168. */
  169. do_action( 'elementor/preview/enqueue_styles' );
  170. }
  171. /**
  172. * Enqueue preview scripts.
  173. *
  174. * Registers all the preview scripts and enqueues them.
  175. *
  176. * Fired by `wp_enqueue_scripts` action.
  177. *
  178. * @since 1.5.4
  179. * @access private
  180. */
  181. private function enqueue_scripts() {
  182. Plugin::$instance->frontend->register_scripts();
  183. Plugin::$instance->widgets_manager->enqueue_widgets_scripts();
  184. $suffix = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
  185. wp_enqueue_script(
  186. 'elementor-inline-editor',
  187. ELEMENTOR_ASSETS_URL . 'lib/inline-editor/js/inline-editor' . $suffix . '.js',
  188. [],
  189. ELEMENTOR_VERSION,
  190. true
  191. );
  192. /**
  193. * Preview enqueue scripts.
  194. *
  195. * Fires after Elementor preview scripts are enqueued.
  196. *
  197. * @since 1.5.4
  198. */
  199. do_action( 'elementor/preview/enqueue_scripts' );
  200. }
  201. /**
  202. * Elementor Preview footer scripts and styles.
  203. *
  204. * Handle styles and scripts from frontend.
  205. *
  206. * Fired by `wp_footer` action.
  207. *
  208. * @since 2.0.9
  209. * @access public
  210. */
  211. public function wp_footer() {
  212. $frontend = Plugin::$instance->frontend;
  213. if ( $frontend->has_elementor_in_page() ) {
  214. // Has header/footer/widget-template - enqueue all style/scripts/fonts.
  215. $frontend->wp_footer();
  216. } else {
  217. // Enqueue only scripts.
  218. $frontend->enqueue_scripts();
  219. }
  220. }
  221. /**
  222. * Preview constructor.
  223. *
  224. * Initializing Elementor preview.
  225. *
  226. * @since 1.0.0
  227. * @access public
  228. */
  229. public function __construct() {
  230. add_action( 'template_redirect', [ $this, 'init' ], 0 );
  231. }
  232. }