Make WordPress Core

Ticket #32967: class-wp-site-icon-admin-ui.php

File class-wp-site-icon-admin-ui.php, 12.1 KB (added by obenland, 10 years ago)

Authored by Frank Klein

Line 
1<?php
2
3class WP_Site_Icon_Admin_UI {
4        /**
5         * The size to which to crop the image so that we can display it in the UI nicely.
6         *
7         * @since 4.3.0
8         *
9         * @var int
10         *
11         * TO DO: Rename
12         */
13        public $page_crop = 512;
14
15        var $admin_ui_processing;
16        var $site_icon;
17        var $admin_page_hook;
18
19        public function __construct( $admin_ui_processing, $site_icon ) {
20                $this->admin_ui_processing = $admin_ui_processing;
21                $this->site_icon = $site_icon;
22
23                // Add the favicon to the backend.
24                add_action( 'admin_head', 'wp_site_icon' );
25
26                add_action( 'admin_menu', array( $this, 'add_site_icon_page_to_menu' ) );
27                add_action( 'admin_init', array( $this, 'add_upload_page_settings' ) );
28
29                add_action( 'admin_action_set_site_icon',    array( $this, 'set_site_icon'    ) );
30                add_action( 'admin_action_remove_site_icon', array( $this, 'remove_site_icon' ) );
31        }
32
33        // To Do: nonce checking
34        public function site_icon_page_controller() {
35                $action = isset( $_GET['action'] ) ? $_GET['action'] : 'select-site-icon';
36
37                switch ( $action ) {
38                        case 'select-site-icon':
39                                $this->display_upload_page();
40                                break;
41
42                        case 'crop-site-icon':
43                                // Handle image upload for the no Javascript version.
44                                if ( isset ( $_GET['upload'] ) ) {
45                                        $attachment_id = $this->admin_ui_processing->upload_site_icon_image();
46                                } else {
47                                        // The Javascript upload skips the select and upload steps, providing the attachment ID.
48                                        $attachment_id = $_GET['file'];
49                                }
50
51                                // Verify that the image is large enough.
52                                $image_size = $this->admin_ui_processing->get_image_size_from_attachment( $attachment_id );
53
54                                // TO DO: Move this to a method.
55                                if ( $image_size[0] < $this->site_icon->min_size ) {
56                                        add_settings_error( 'site-icon', 'too-small', sprintf( __( 'The selected image is smaller than %upx in width.' ), $this->site_icon->min_size ) );
57                                        $this->display_upload_page();
58                                } elseif ( $image_size[1] < $this->site_icon->min_size ) {
59                                        add_settings_error( 'site-icon', 'too-small', sprintf( __( 'The selected image is smaller than %upx in height.' ), $this->site_icon->min_size ) );
60                                        $this->display_upload_page();
61                                } else {
62                                        // TO DO: Move this to a method.
63                                        // URL of the uploaded image.
64                                        $image_url = $this->admin_ui_processing->get_site_icon_image_url( $attachment_id );
65                                        // Dimensions of the uploaded image adapted to the admin.
66                                        $max_height = $this->admin_ui_processing->calculate_height_of_image_for_cropping( $attachment_id, $this->page_crop );
67                                        // Add the default crop values for the no JS version.
68                                        $default_crop = $this->admin_ui_processing->calculate_default_values_for_crop( $this->page_crop, $max_height );
69                                        // Ratio for cropping
70                                        $crop_ratio = $image_size[0] / $this->page_crop;
71
72                                        $this->display_crop_page( $attachment_id, $image_url, $this->page_crop, $max_height, $default_crop, $crop_ratio );
73                                }
74                                break;
75
76                        default:
77                                wp_safe_redirect( admin_url( 'options-general.php#site-icon' ) );
78                                exit;
79                }
80        }
81
82        /**
83         * Adds the Site Icon Page to the admin menu.
84         *
85         * The `parent_slug` argument in `add_menu_page()` is set to `null`, so that no link is added in the admin interface.
86         *
87         * @since 4.3.0
88         */
89        public function add_site_icon_page_to_menu() {
90                $hook = add_submenu_page( null, __( 'Site Icon' ), __( 'Site Icon' ), 'manage_options', 'site-icon', array( $this, 'site_icon_page_controller' ) );
91
92                add_action( "admin_print_scripts-$hook", array( $this, 'enqueue_scripts' ) );
93        }
94
95        /**
96         * Register a settings section for uploading a Site Icon image.
97         *
98         * @since 4.3.0
99         */
100        public function add_upload_page_settings() {
101                add_settings_section( 'site-icon-upload', false, false, 'site-icon-upload' );
102                add_settings_field( 'site-icon-upload', __( 'Upload Image' ), array( $this, 'display_upload_page_image_selection' ), 'site-icon-upload', 'site-icon-upload', array(
103                        'label_for' => 'site-icon-upload',
104                ) );
105        }
106
107        /**
108         * Add scripts to admin settings pages.
109         *
110         * @since 4.3.0
111         */
112        public function enqueue_scripts() {
113                wp_enqueue_style( 'jcrop' );
114                wp_enqueue_script( 'site-icon-crop' );
115        }
116
117        /**
118         * Display the admin page for uploading a Site Icon image.
119         *
120         * This screen is only visible when Javascript is deactivated.
121         *
122         * @since 4.3.0
123         */
124        public function display_upload_page() {
125                ?>
126                <div class="wrap">
127                        <h2><?php _e( 'Add Site Icon' ); ?></h2>
128                        <?php settings_errors( 'site-icon' ); ?>
129                        <?php do_settings_sections( 'site-icon-upload' ); ?>
130                </div>
131        <?php
132        }
133
134        /**
135         * Settings field for file upload.
136         *
137         * @since 4.3.0
138         */
139        public function display_upload_page_image_selection() {
140                // Render modal for uploading via Javascript.
141                // TO DO: Script enqueuing should be done in a single method.
142                wp_enqueue_media();
143                wp_enqueue_script( 'site-icon' );
144                wp_dequeue_script( 'site-icon-crop' );
145
146                $update_url = esc_url( add_query_arg( array(
147                        'page' => 'site-icon',
148                        'action' => 'crop-site-icon',
149                ), wp_nonce_url( admin_url( 'options-general.php' ), 'crop-site-icon' ) ) );
150                ?>
151                <p class="hide-if-no-js">
152                        <label class="screen-reader-text" for="choose-from-library-link"><?php _e( 'Choose an image from your media library:' ); ?></label>
153                        <?php
154                                printf( '<button type="button" id="choose-from-library-link" class="button" data-update-link="%$1s" data-choose="%$2s" data-update="%$3s">%$4s</button>',
155                                        esc_attr( $update_url ),
156                                        esc_attr__( 'Choose a Site Icon' ),
157                                        esc_attr__( 'Set as Site Icon' ),
158                                        __( 'Choose Image' )
159                                );
160                        ?>
161                </p>
162
163                <?php // Upload form for when Javascript is deactivated ?>
164                <form class="hide-if-js" action="<?php echo esc_url( admin_url( 'options-general.php?page=site-icon&action=crop-site-icon&upload' ) ); ?>" method="post" enctype="multipart/form-data">
165                        <input name="action" value="crop_site_icon" type="hidden" />
166                        <input name="site-icon" type="file" />
167                        <input name="submit" value="<?php esc_attr_e( 'Upload Image' ); ?>" type="submit" class="button button-primary" />
168                        <p class="description">
169                                <?php printf( __( 'The image is recommended to be a square image of at least %spx in both width and height.' ), "<strong>" . absint( $this->site_icon->min_size ) . '</strong>' ); ?>
170                        </p>
171                        <?php wp_nonce_field( 'crop-site-icon' ); ?>
172                </form>
173        <?php
174        }
175
176        public function display_crop_page( $attachment_id, $image_url, $resized_image_width, $resized_image_height, $default_crop, $crop_ratio ) {
177                check_admin_referer( 'crop-site-icon' );
178
179                // TO DO: Script enqueuing should be done in a single method.
180                $image_size = $this->admin_ui_processing->get_attachment_image_size( $attachment_id );
181                wp_localize_script( 'site-icon-crop', 'wpSiteIconCropData', $this->admin_ui_processing->calculate_default_values_for_javascript_cropper( $crop_ratio, $this->page_crop, $resized_image_width, $resized_image_height, $image_size[0], $image_size[1] ) );
182        ?>
183                <div class="wrap">
184                        <h2 class="site-icon-title"><?php _e( 'Site Icon' ); ?></h2>
185                        <?php settings_errors( 'site-icon' ); ?>
186
187                        <div class="site-icon-crop-shell">
188                                <form action="options-general.php" method="post" enctype="multipart/form-data">
189                                        <p class="hide-if-no-js description"><?php _e('Choose the part of the image you want to use as your site icon.'); ?></p>
190                                        <p class="hide-if-js description"><strong><?php _e( 'You need Javascript to choose a part of the image.'); ?></strong></p>
191                                        <?php
192                                                // Image which is used to select the right cropping.
193                                                // This image needs to be resized to allow for easy cropping.
194                                                printf( '<img src="%1$s" id="crop-image" class="site-icon-crop-image" width="%2$s" height="%3$s" alt="%4$s" />',
195                                                        esc_url( $image_url ),
196                                                        absint( $resized_image_width ),
197                                                        absint( $resized_image_height ),
198                                                        esc_attr__( 'Image to be cropped' )
199                                                );
200
201                                                // Site icon preview in browser bar and on mobile.
202                                        ?>
203                                        <div class="site-icon-crop-preview-shell hide-if-no-js">
204                                                <h3><?php _e( 'Preview' ); ?></h3>
205                                                <strong><?php _e( 'As your favicon' ); ?></strong>
206                                                <div class="site-icon-crop-favicon-preview-shell">
207                                                        <img src="images/browser.png" class="site-icon-browser-preview" width="182" height="" alt="<?php esc_attr_e( 'Browser Chrome' ); ?>"/>
208                                                        <div class="site-icon-crop-preview-favicon">
209                                                                <img src="<?php echo esc_url( $image_url ); ?>" id="preview-favicon" alt="<?php esc_attr_e( 'Preview Favicon' ); ?>"/>
210                                                        </div>
211                                                        <span class="site-icon-browser-title"><?php bloginfo( 'name' ); ?></span>
212                                                </div>
213                                                <strong><?php _e( 'As a mobile icon' ); ?></strong>
214                                                <div class="site-icon-crop-preview-homeicon">
215                                                        <img src="<?php echo esc_url( $image_url ); ?>" id="preview-homeicon" alt="<?php esc_attr_e( 'Preview Home Icon' ); ?>"/>
216                                                </div>
217                                        </div>
218
219                                        <?php // Default crop values for no JS fallback. ?>
220                                        <input type="hidden" id="crop-x" name="crop-x" value="<?php echo absint( $default_crop['crop_x'] ); ?>" />
221                                        <input type="hidden" id="crop-y" name="crop-y" value="<?php echo absint( $default_crop['crop_y'] ); ?>" />
222                                        <input type="hidden" id="crop-width" name="crop-w" value="<?php echo absint( $default_crop['crop_size'] ); ?>" />
223                                        <input type="hidden" id="crop-height" name="crop-h" value="<?php echo absint( $default_crop['crop_size'] ); ?>" />
224
225                                        <input type="hidden" name="action" value="set_site_icon" />
226                                        <input type="hidden" name="attachment_id" value="<?php echo esc_attr( $attachment_id ); ?>" />
227
228                                        <input type="hidden" name="crop_ratio" value="<?php echo esc_attr( $crop_ratio ); ?>" />
229                                        <?php if ( empty( $_POST ) && isset( $_GET['file'] ) ) : ?>
230                                                <input type="hidden" name="create-new-attachment" value="true" />
231                                        <?php endif; ?>
232                                        <?php wp_nonce_field( 'set-site-icon' ); ?>
233
234                                        <p class="submit">
235                                                <?php submit_button( __( 'Crop and Publish' ), 'primary hide-if-no-js', 'submit', false ); ?>
236                                                <?php submit_button( __( 'Publish' ), 'primary hide-if-js', 'submit', false ); ?>
237                                                <a class="button secondary" href="options-general.php"><?php _e( 'Cancel' ); ?></a>
238                                        </p>
239                                </form>
240                        </div>
241                </div>
242        <?php
243        }
244
245        /**
246         * Saves a new Site Icon.
247         *
248         * TO DO: Split this apart, and move code to smaller methods in `WP_Site_Icon_Admin_Processing`.
249         *
250         * @since 4.3.0
251         */
252        public function set_site_icon() {
253                check_admin_referer( 'set-site-icon' );
254
255                // Delete any existing site icon images.
256                $this->admin_ui_processing->delete_site_icon();
257
258                $attachment_id = absint( $_POST['attachment_id'] );
259
260                // TODO
261                if ( empty( $_POST['skip-cropping'] ) ) {
262                        $crop_ratio = (float) $_POST['crop_ratio'];
263                        $crop_data = $this->admin_ui_processing->convert_coordinates_from_resized_to_full( $_POST['crop-x'], $_POST['crop-y'], $_POST['crop-w'], $_POST['crop-h'], $crop_ratio );
264                        $cropped = wp_crop_image( $attachment_id, $crop_data['crop_x'], $crop_data['crop_y'], $crop_data['crop_width'], $crop_data['crop_height'], $this->site_icon->min_size, $this->site_icon->min_size );
265                } elseif ( ! empty( $_POST['create-new-attachment'] ) ) {
266                        $cropped = _copy_image_file( $attachment_id );
267                } else {
268                        $cropped = get_attached_file( $attachment_id );
269                }
270
271                if ( ! $cropped || is_wp_error( $cropped ) ) {
272                        wp_die( __( 'Image could not be processed. Please go back and try again.' ), __( 'Image Processing Error' ) );
273                }
274
275                $object = $this->admin_ui_processing->create_attachment_object( $cropped, $attachment_id );
276
277                if ( ! empty( $_POST['create-new-attachment'] ) ) {
278                        unset( $object['ID'] );
279                }
280
281                // Update the attachment
282                add_filter( 'intermediate_image_sizes_advanced', array( $this->site_icon, 'additional_sizes' ) );
283                $attachment_id = $this->admin_ui_processing->insert_attachment( $object, $cropped );
284                remove_filter( 'intermediate_image_sizes_advanced', array( $this->site_icon, 'additional_sizes' ) );
285
286                // Save the site_icon data into option
287                update_option( 'site_icon', $attachment_id );
288
289                add_settings_error( 'site-icon', 'icon-updated', __( 'Site Icon updated.' ), 'updated' );
290        }
291
292        /**
293         * Removes site icon.
294         *
295         * @since 4.3.0
296         */
297        public function remove_site_icon() {
298                check_admin_referer( 'remove-site-icon' );
299
300                // TO DO: Check return value to display success message.
301                $this->admin_ui_processing->delete_site_icon();
302
303                add_settings_error( 'site-icon', 'icon-removed', __( 'Site Icon removed.' ), 'updated' );
304        }
305
306}
307
308$site_icon_admin = new WP_Site_Icon_Admin_UI( new WP_Site_Icon_Admin_Processing(), WP_Site_Icon::get_instance() );