manager.php (8225B)
1 <?php 2 namespace Elementor\Core\Settings\Page; 3 4 use Elementor\Core\Base\Document; 5 use Elementor\Core\Files\CSS\Base; 6 use Elementor\Core\Files\CSS\Post; 7 use Elementor\Core\Files\CSS\Post_Preview; 8 use Elementor\Core\Settings\Base\CSS_Manager; 9 use Elementor\Core\Utils\Exceptions; 10 use Elementor\Core\Settings\Base\Model as BaseModel; 11 use Elementor\Plugin; 12 use Elementor\Utils; 13 14 if ( ! defined( 'ABSPATH' ) ) { 15 exit; // Exit if accessed directly. 16 } 17 18 /** 19 * Elementor page settings manager. 20 * 21 * Elementor page settings manager handler class is responsible for registering 22 * and managing Elementor page settings managers. 23 * 24 * @since 1.6.0 25 */ 26 class Manager extends CSS_Manager { 27 28 /** 29 * Meta key for the page settings. 30 */ 31 const META_KEY = '_elementor_page_settings'; 32 33 /** 34 * Get manager name. 35 * 36 * Retrieve page settings manager name. 37 * 38 * @since 1.6.0 39 * @access public 40 * 41 * @return string Manager name. 42 */ 43 public function get_name() { 44 return 'page'; 45 } 46 47 /** 48 * Get model for config. 49 * 50 * Retrieve the model for settings configuration. 51 * 52 * @since 1.6.0 53 * @access public 54 * 55 * @return BaseModel The model object. 56 */ 57 public function get_model_for_config() { 58 if ( ! is_singular() && ! Plugin::$instance->editor->is_edit_mode() ) { 59 return null; 60 } 61 62 if ( Plugin::$instance->editor->is_edit_mode() ) { 63 $post_id = Plugin::$instance->editor->get_post_id(); 64 $document = Plugin::$instance->documents->get_doc_or_auto_save( $post_id ); 65 } else { 66 $post_id = get_the_ID(); 67 $document = Plugin::$instance->documents->get_doc_for_frontend( $post_id ); 68 } 69 70 if ( ! $document ) { 71 return null; 72 } 73 74 $model = $this->get_model( $document->get_post()->ID ); 75 76 if ( $document->is_autosave() ) { 77 $model->set_settings( 'post_status', $document->get_main_post()->post_status ); 78 } 79 80 return $model; 81 } 82 83 /** 84 * Ajax before saving settings. 85 * 86 * Validate the data before saving it and updating the data in the database. 87 * 88 * @since 1.6.0 89 * @access public 90 * 91 * @param array $data Post data. 92 * @param int $id Post ID. 93 * 94 * @throws \Exception If invalid post returned using the `$id`. 95 * @throws \Exception If current user don't have permissions to edit the post. 96 */ 97 public function ajax_before_save_settings( array $data, $id ) { 98 $post = get_post( $id ); 99 100 if ( empty( $post ) ) { 101 throw new \Exception( 'Invalid post.', Exceptions::NOT_FOUND ); 102 } 103 104 if ( ! Utils::is_wp_cli() && ! current_user_can( 'edit_post', $id ) ) { 105 throw new \Exception( 'Access denied.', Exceptions::FORBIDDEN ); 106 } 107 108 // Avoid save empty post title. 109 if ( ! empty( $data['post_title'] ) ) { 110 $post->post_title = $data['post_title']; 111 } 112 113 if ( isset( $data['post_excerpt'] ) && post_type_supports( $post->post_type, 'excerpt' ) ) { 114 $post->post_excerpt = $data['post_excerpt']; 115 } 116 117 if ( isset( $data['post_status'] ) ) { 118 $this->save_post_status( $id, $data['post_status'] ); 119 unset( $post->post_status ); 120 } 121 122 wp_update_post( $post ); 123 124 // Check updated status 125 if ( Document::STATUS_PUBLISH === get_post_status( $id ) ) { 126 $autosave = wp_get_post_autosave( $post->ID ); 127 if ( $autosave ) { 128 wp_delete_post_revision( $autosave->ID ); 129 } 130 } 131 132 if ( isset( $data['post_featured_image'] ) && post_type_supports( $post->post_type, 'thumbnail' ) ) { 133 if ( empty( $data['post_featured_image']['id'] ) ) { 134 delete_post_thumbnail( $post->ID ); 135 } else { 136 set_post_thumbnail( $post->ID, $data['post_featured_image']['id'] ); 137 } 138 } 139 140 if ( Utils::is_cpt_custom_templates_supported() ) { 141 $template = get_metadata( 'post', $post->ID, '_wp_page_template', true ); 142 143 if ( isset( $data['template'] ) ) { 144 $template = $data['template']; 145 } 146 147 if ( empty( $template ) ) { 148 $template = 'default'; 149 } 150 151 // Use `update_metadata` in order to save also for revisions. 152 update_metadata( 'post', $post->ID, '_wp_page_template', $template ); 153 } 154 } 155 156 /** 157 * @inheritDoc 158 * 159 * Override parent because the page setting moved to document.settings. 160 */ 161 protected function print_editor_template_content( $name ) { 162 ?> 163 <# 164 const tabs = elementor.config.document.settings.tabs; 165 166 if ( Object.values( tabs ).length > 1 ) { #> 167 <div class="elementor-panel-navigation"> 168 <# _.each( tabs, function( tabTitle, tabSlug ) { 169 $e.bc.ensureTab( 'panel/page-settings', tabSlug ); #> 170 <div class="elementor-component-tab elementor-panel-navigation-tab elementor-tab-control-{{ tabSlug }}" data-tab="{{ tabSlug }}"> 171 <a href="#">{{{ tabTitle }}}</a> 172 </div> 173 <# } ); #> 174 </div> 175 <# } #> 176 <div id="elementor-panel-<?php echo esc_attr( $name ); ?>-settings-controls"></div> 177 <?php 178 } 179 180 /** 181 * Save settings to DB. 182 * 183 * Save page settings to the database, as post meta data. 184 * 185 * @since 1.6.0 186 * @access protected 187 * 188 * @param array $settings Settings. 189 * @param int $id Post ID. 190 */ 191 protected function save_settings_to_db( array $settings, $id ) { 192 // Use update/delete_metadata in order to handle also revisions. 193 if ( ! empty( $settings ) ) { 194 // Use `wp_slash` in order to avoid the unslashing during the `update_post_meta`. 195 update_metadata( 'post', $id, self::META_KEY, wp_slash( $settings ) ); 196 } else { 197 delete_metadata( 'post', $id, self::META_KEY ); 198 } 199 } 200 201 /** 202 * Get CSS file for update. 203 * 204 * Retrieve the CSS file before updating it. 205 * 206 * This method overrides the parent method to disallow updating CSS files for pages. 207 * 208 * @since 1.6.0 209 * @access protected 210 * 211 * @param int $id Post ID. 212 * 213 * @return false Disallow The updating CSS files for pages. 214 */ 215 protected function get_css_file_for_update( $id ) { 216 return false; 217 } 218 219 /** 220 * Get saved settings. 221 * 222 * Retrieve the saved settings from the post meta. 223 * 224 * @since 1.6.0 225 * @access protected 226 * 227 * @param int $id Post ID. 228 * 229 * @return array Saved settings. 230 */ 231 protected function get_saved_settings( $id ) { 232 $settings = get_post_meta( $id, self::META_KEY, true ); 233 234 if ( ! $settings ) { 235 $settings = []; 236 } 237 238 if ( Utils::is_cpt_custom_templates_supported() ) { 239 $saved_template = get_post_meta( $id, '_wp_page_template', true ); 240 241 if ( $saved_template ) { 242 $settings['template'] = $saved_template; 243 } 244 } 245 246 return $settings; 247 } 248 249 /** 250 * Get CSS file name. 251 * 252 * Retrieve CSS file name for the page settings manager. 253 * 254 * @since 1.6.0 255 * @access protected 256 * 257 * @return string CSS file name. 258 */ 259 protected function get_css_file_name() { 260 return 'post'; 261 } 262 263 /** 264 * Get model for CSS file. 265 * 266 * Retrieve the model for the CSS file. 267 * 268 * @since 1.6.0 269 * @access protected 270 * 271 * @param Base $css_file The requested CSS file. 272 * 273 * @return BaseModel The model object. 274 */ 275 protected function get_model_for_css_file( Base $css_file ) { 276 if ( ! $css_file instanceof Post ) { 277 return null; 278 } 279 280 $post_id = $css_file->get_post_id(); 281 282 if ( $css_file instanceof Post_Preview ) { 283 $autosave = Utils::get_post_autosave( $post_id ); 284 if ( $autosave ) { 285 $post_id = $autosave->ID; 286 } 287 } 288 289 return $this->get_model( $post_id ); 290 } 291 292 /** 293 * Get special settings names. 294 * 295 * Retrieve the names of the special settings that are not saved as regular 296 * settings. Those settings have a separate saving process. 297 * 298 * @since 1.6.0 299 * @access protected 300 * 301 * @return array Special settings names. 302 */ 303 protected function get_special_settings_names() { 304 return [ 305 'id', 306 'post_title', 307 'post_status', 308 'template', 309 'post_excerpt', 310 'post_featured_image', 311 ]; 312 } 313 314 /** 315 * @since 2.0.0 316 * @access public 317 * 318 * @param $post_id 319 * @param $status 320 */ 321 public function save_post_status( $post_id, $status ) { 322 $parent_id = wp_is_post_revision( $post_id ); 323 324 if ( $parent_id ) { 325 // Don't update revisions post-status 326 return; 327 } 328 329 $parent_id = $post_id; 330 331 $post = get_post( $parent_id ); 332 333 $allowed_post_statuses = get_post_statuses(); 334 335 if ( isset( $allowed_post_statuses[ $status ] ) ) { 336 $post_type_object = get_post_type_object( $post->post_type ); 337 if ( 'publish' !== $status || current_user_can( $post_type_object->cap->publish_posts ) ) { 338 $post->post_status = $status; 339 } 340 } 341 342 wp_update_post( $post ); 343 } 344 }