1 | <?php |
---|
2 | |
---|
3 | class 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() ); |
---|