PluginProbe
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! / trunk
Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! vtrunk
3.8.0 3.7.5 3.7.4 3.7.3 3.7.2 1-final 3.7.1 3.7.0 3.6.8 3.6.7 3.6.6 3.6.5 3.6.4 3.6.3 3.6.2 3.6.1 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 All 112 releases
templately / modules / ai-editor / EditorPage.php

EditorPage.php in Templately – Elementor & Gutenberg Template Library: 6500+ Free & Pro Ready Templates And Cloud! trunk, at modules/ai-editor/EditorPage.php

159 lines 4.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Templately\Modules\AiEditor;
4
5 use Templately\Utils\Base;
6 use Templately\Utils\Helper;
7
8 /**
9 * The Templately AI Editor page (041 phase 1): a hidden, fullscreen admin page
10 * that iframes the post's NATIVE editor (post.php?action=elementor|edit) with
11 * the AI chat auto-docked inside via the templately_host=1 URL signal. The
12 * iframe loads the correct editor assets itself — no re-enqueueing, no
13 * embedded-editor maintenance; the shell is plain PHP + inline CSS.
14 */
15 class EditorPage extends Base {
16
17 const SLUG = 'templately-ai-editor';
18
19 public function __construct() {
20 add_action( 'admin_menu', [ $this, 'admin_menu' ] );
21 add_filter( 'admin_body_class', [ $this, 'body_class' ] );
22 add_filter( 'post_row_actions', [ $this, 'row_action' ], 10, 2 );
23 add_filter( 'page_row_actions', [ $this, 'row_action' ], 10, 2 );
24 }
25
26 /**
27 * Hidden page: empty parent slug registers the page + its hook
28 * (admin_page_{slug}) with NO menu entry. Never register-then-remove —
29 * remove_submenu_page() strips the entry user_can_access_admin_page()
30 * validates against, turning the page into a core 403.
31 */
32 public function admin_menu() {
33 add_submenu_page(
34 '',
35 __( 'AI Editor', 'templately' ),
36 __( 'AI Editor', 'templately' ),
37 'delete_posts',
38 self::SLUG,
39 [ $this, 'display' ]
40 );
41 }
42
43 /**
44 * The canonical URL of the editor page for a post.
45 */
46 public static function url( $post_id ) {
47 return add_query_arg(
48 [
49 'page' => self::SLUG,
50 'post' => absint( $post_id ),
51 ],
52 admin_url( 'admin.php' )
53 );
54 }
55
56 public function body_class( $classes ) {
57 if ( $this->is_current_screen() ) {
58 $classes .= ' templately-ai-editor-page';
59 }
60 return $classes;
61 }
62
63 private function is_current_screen() {
64 return is_admin() && isset( $_GET['page'] ) && self::SLUG === $_GET['page'];
65 }
66
67 public function display() {
68 $post_id = absint( $_GET['post'] ?? 0 );
69 $post = $post_id ? get_post( $post_id ) : null;
70
71 if ( ! $post || ! current_user_can( 'edit_post', $post_id ) ) {
72 wp_die( esc_html__( 'Sorry, you are not allowed to edit this page with Templately AI.', 'templately' ) );
73 }
74
75 $platform = $this->detect_platform( $post );
76 $edit_link = get_edit_post_link( $post_id, 'raw' );
77
78 if ( null === $platform ) {
79 // Classic-editor-only content — never iframe it; hand off cleanly.
80 wp_die(
81 sprintf(
82 /* translators: %s: edit-post URL */
83 wp_kses( __( 'This content uses the classic editor, which Templately AI cannot host. <a href="%s">Open it in its own editor</a>.', 'templately' ), [ 'a' => [ 'href' => [] ] ] ),
84 esc_url( $edit_link )
85 ),
86 esc_html__( 'Templately AI Editor', 'templately' )
87 );
88 }
89
90 $native_url = add_query_arg(
91 [
92 'post' => $post_id,
93 'action' => 'elementor' === $platform ? 'elementor' : 'edit',
94 ],
95 admin_url( 'post.php' )
96 );
97
98 Helper::views(
99 'ai-editor-page',
100 [
101 'src' => add_query_arg( 'templately_host', 1, $native_url ),
102 'exit_url' => $native_url,
103 'exit_wp_url' => $this->wordpress_exit_url( $post ),
104 'post_title' => get_the_title( $post ),
105 'platform' => $platform,
106 ]
107 );
108 }
109
110 /**
111 * Where "Exit to WordPress" goes: the list screen for THIS post's type when
112 * the user arrived from somewhere in wp-admin (Posts → edit.php, Pages →
113 * edit.php?post_type=page, other CPTs likewise); the main dashboard when the
114 * editor was opened cold (new tab / typed URL, so there is no referrer to
115 * come back to).
116 */
117 private function wordpress_exit_url( $post ) {
118 if ( ! wp_get_referer() ) {
119 return admin_url( 'index.php' );
120 }
121 $post_type = get_post_type( $post ) ?: 'post';
122 return 'post' === $post_type
123 ? admin_url( 'edit.php' )
124 : add_query_arg( 'post_type', $post_type, admin_url( 'edit.php' ) );
125 }
126
127 /**
128 * 'elementor' | 'gutenberg' | null (classic-only). Same signal
129 * Elementor's Document::is_built_with_elementor() reads.
130 */
131 private function detect_platform( $post ) {
132 if ( did_action( 'elementor/loaded' ) && 'builder' === get_post_meta( $post->ID, '_elementor_edit_mode', true ) ) {
133 return 'elementor';
134 }
135 if ( use_block_editor_for_post( $post ) ) {
136 return 'gutenberg';
137 }
138 return null;
139 }
140
141 /**
142 * "Edit with Templately AI" on the posts/pages list rows.
143 */
144 public function row_action( $actions, $post ) {
145 if (
146 current_user_can( 'edit_post', $post->ID ) &&
147 'trash' !== $post->post_status &&
148 null !== $this->detect_platform( $post )
149 ) {
150 $actions['templately_ai_edit'] = sprintf(
151 '<a href="%s">%s</a>',
152 esc_url( self::url( $post->ID ) ),
153 esc_html__( 'Edit with Templately AI', 'templately' )
154 );
155 }
156 return $actions;
157 }
158 }
159