admin_url('admin-ajax.php'), 'nonce' => wp_create_nonce('wp2048_ajax'), 'media_modal_title' => __('Add Image to 2048 Tile', 'wp2048'), 'media_modal_button' => __('Assign Image', 'wp2048'), 'alert_image_size' => __('Minimum image dimension is 107px width and height.', 'wp2048'), 'alert_not_image' => __('Selected media not a valid image format.', 'wp2048'), ) ); } /** * Add settings menu and page */ public function settings_menu() { // This page will be under "Settings" $page = add_options_page( 'Settings Admin', '2048 Number Game', 'manage_options', 'wp2048', array( $this, 'settings_page' ) ); add_action( 'admin_print_styles-' . $page, array( $this, 'settings_enqueue' ) ); } /** * Settings page callback */ public function settings_page() { // Set the active tabs $active_tab = ( isset($_GET['tab']) ) ? $_GET['tab'] : ''; ?>

'customization', 'label' => 'Checking this will make default shortcode to use customizations' ) ); add_settings_field( 'hide_howto', // ID 'Hide How-To', // Title array( $this, 'checkbox_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_general', // Section array( 'field' => 'hide_howto', 'label' => 'Hide game instructions below game board' ) ); add_settings_field( 'scoreboard', // ID 'Score Board', // Title array( $this, 'checkbox_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_general', // Section array( 'field' => 'scoreboard', 'label' => 'Check to enable storing each user\'s high score' ) ); add_settings_field( 'displayname', // ID 'Display Name', // Title array( $this, 'checkbox_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_general', // Section array( 'field' => 'displayname', 'label' => 'Score board will list user by their display name option. Can be overridden in shortcode.' ) ); add_settings_field( 'guest_highscore', // ID 'Guest High Score', // Title array( $this, 'checkbox_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_general', // Section array( 'field' => 'guest_highscore', 'label' => 'Allow non logged-in user to submit high score' ) ); add_settings_field( 'notify', // ID 'Notify High Score', // Title array( $this, 'notify_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_general' // Section ); add_settings_field( 'userscore', // ID 'User Score', // Title array( $this, 'checkbox_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_general', // Section array( 'field' => 'userscore', 'label' => 'Notify users when they update own high score' ) ); // Email Templates add_settings_section( 'wp2048_options_email', // ID 'Email Templates', // Title array( $this, 'print_section_email' ), // Callback 'wp2048_options_page' // Page ); add_settings_field( 'highscore_new', 'New High Score', array( $this, 'email_template_callback' ), 'wp2048_options_page', 'wp2048_options_email', array( 'field' => 'highscore_new', 'desc' => 'Congratulates on achieving site\'s new high score' ) ); add_settings_field( 'highscore_lost', 'Lost High Score', array( $this, 'email_template_callback' ), 'wp2048_options_page', 'wp2048_options_email', array( 'field' => 'highscore_lost', 'desc' => 'Sent to previous user their high score just broken' ) ); add_settings_field( 'highscore_user', 'User High Score', array( $this, 'email_template_callback' ), 'wp2048_options_page', 'wp2048_options_email', array( 'field' => 'highscore_user', 'desc' => 'Congratulates on updating own high score' ) ); // Advanced Options add_settings_section( 'wp2048_options_advanced', // ID 'Advanced Options', // Title array( $this, 'print_section_advanced' ), // Callback 'wp2048_options_page' // Page ); add_settings_field( 'tx_viewport', 'Meta Viewport', array( $this, 'text_callback' ), 'wp2048_options_page', 'wp2048_options_advanced', array( 'field' => 'tx_viewport', 'desc' => 'Only applies to page with [2048] shortcode. If left blank, it will not modify (or add into) your theme\'s viewport.' ) ); add_settings_field( 'metahead', // ID 'Disable Mobile Friendly', // Title array( $this, 'checkbox_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_advanced', // Section array( 'field' => 'metahead', 'label' => 'Do not add meta for mobile friendly. Only applies to page with [2048] shortcode.' ) ); add_settings_field( 'delete', // ID 'Delete Plugin Data', // Title array( $this, 'checkbox_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_advanced', // Section array( 'field' => 'delete', 'label' => 'Remove plugin settings and customizations (excluding high scores) upon de-activation. Re-activation will reset plugin settings to default.' ) ); add_settings_field( 'delscores', // ID 'Delete High Scores', // Title array( $this, 'checkbox_callback' ), // Callback 'wp2048_options_page', // Page 'wp2048_options_advanced', // Section array( 'field' => 'delscores', 'label' => 'WARNING! Remove all stored high scores upon plugin un-installation.' ) ); /** * Customizations Tab */ register_setting( 'wp2048_customize_settings', 'wp2048_custom', array( $this, 'sanitize_customize' ) ); add_settings_section( 'wp2048_customize_section', // ID '', // Title array( $this, 'print_section_customize' ), // Callback 'wp2048_customize_page' // Page ); add_settings_field( 'feature', // ID 'Enabled Features', // Title array( $this, 'features_callback' ), // Callback 'wp2048_customize_page', // Page 'wp2048_customize_section' // Section ); add_settings_field( 'color_font', // ID 'Font Color', // Title array( $this, 'colorpicker_callback' ), // Callback 'wp2048_customize_page', // Page 'wp2048_customize_section', // Section array( 'type' => 'font' ) ); add_settings_field( 'color_bg', // ID 'Background Color', // Title array( $this, 'colorpicker_callback' ), // Callback 'wp2048_customize_page', // Page 'wp2048_customize_section', // Section array( 'type' => 'bg' ) ); add_settings_field( 'color_grid', // ID 'Grid Color', // Title array( $this, 'colorpicker_callback' ), // Callback 'wp2048_customize_page', // Page 'wp2048_customize_section', // Section array( 'type' => 'grid' ) ); foreach($this->tiles as $tile) { add_settings_field( $tile, 'Tile '.$tile, array( $this, 'customize_callback' ), 'wp2048_customize_page', 'wp2048_customize_section', array( 'tile' => $tile ) ); } add_settings_section( 'wp2048_custom_shortcode', // ID '', // Title array( $this, 'print_section_shortcode' ), // Callback 'wp2048_customize_page' // Page ); } /** * Sanitize each setting field as needed * * @param array $input Contains all settings fields as array keys */ public function sanitize( $input ) { $new_input = array(); $blank_subject = false; foreach ($input as $field => $value) { if ($field == 'email_template') { $email_template = $value; foreach ($email_template as $etype => $template) { if ( !empty($template['subject']) ) { $sanitized_template[$etype]['subject'] = sanitize_text_field($template['subject']); } else { $sanitized_template[$etype]['subject'] = $this->option['email_template'][$etype]['subject']; $blank_subject = true; } $sanitized_template[$etype]['message'] = isset($template['message']) ? esc_textarea($template['message']) : ''; } $new_input[$field] = $sanitized_template; } else { $exp = explode('_',$field); if ($exp[0] == 'ta') { $new_input[$field] = esc_textarea($value); } elseif ($exp[0] == 'tx') { $new_input[$field] = sanitize_text_field($value); } else { $new_input[$field] = absint($value); } } } // email subject cannot be blank if ($blank_subject) { add_settings_error( 'wp2048_blanksubject', esc_attr( 'settings_updated' ), __('Email subject cannot be left blank. Affected field(s) reverted to previous setting.','wp2048'), 'error' ); } return $new_input; } /** * Sanitize function for Customizer */ public function sanitize_customize( $input ) { $new_input = array(); if ( !empty($input['feature']) ) foreach($input['feature'] as $type => $feature) { $new_input['feature'][$type] = absint($feature); } // Custom Text Sanitization $texts = $input['text']; foreach ($texts as $tkey => $text) { if ( empty($text) ) { //fill-in blank input with defaults $new_input['text'][$tkey] = (string)$tkey; $partial = true; } else { $new_input['text'][$tkey] = sanitize_text_field($text); } } // Custom Font Size $error_size = false; $sizes = $input['size']; foreach ($sizes as $skey => $size) { $new_input['size'][$skey] = absint($size); if ( !empty($size) && !is_numeric($size) ) { $error_size = true; } } if ($error_size) { add_settings_error( 'wp2048_fontsize', esc_attr( 'settings_updated' ), __('Font size accepts positive integer only. Invalid input has been discarded.','wp2048'), 'error' ); } // Image uploads $images = $input['image']; foreach ($images as $ikey => $image){ if ( empty($image) ) { //fill-in blank input with defaults $new_input['image'][$ikey] = 0; } else { // allow only jpg, png and gif images $new_input['image'][$ikey] = in_array(strtolower(end(explode('.', $image))), array('jpg', 'jpeg', 'png', 'gif')) ? $image : ''; } } // Custom Colors $error_color = array(); $colors = $input['color']; foreach ($colors as $ckey => $color) { if ( !empty($color) ) { $color = sanitize_text_field($color); if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color) ) { $new_input['color'][$ckey] = $color; } else { $error_color[] = $ckey; } } } if ( !empty($error_color) ) { $error_color = implode(", ",$error_color); add_settings_error( 'wp2048_hexcolor', esc_attr( 'settings_updated' ), __('Some color fields contains invalid HEX values. Invalid input has been discarded. Check tile ','wp2048').$error_color, 'error' ); } return $new_input; } /** * Function to sanitize color picker */ private function sanitize_colorpicker( $input ) { $output = array(); $error = false; foreach ($input as $key => $color) { if ( !empty($color) ) { $color = sanitize_text_field($color); if ( preg_match('|^#([A-Fa-f0-9]{3}){1,2}$|', $color) ) { $output['color'][$key] = $color; } else { $error = true; } } } return array( 'output' => $output, 'error' => $error ); } /** * Print the Section text */ public function print_section_general() { // Some know-how echo '

To add 2048 Number Game on your WordPress site, simply use [2048] shortcode into any page or post. You can also add the shortcode using the button on post editor when you are creating or updating a page or post. Configure the default settings on this page.

'; // Show High Score if ( 0 === $this->highscore['uid'] ) { //$hs_user = 'Guest ('.$this->highscore['email'].')'; $hs_user = 'Guest'; } else { $get_user = get_user_by( 'id', $this->highscore['uid'] ); //$hs_user = $get_user->display_name.' ('.$get_user->user_email.')'; $hs_user = $get_user->display_name; } echo '

How the high score works?

'; echo '
'.$this->highscore['score'].'
'.$hs_user.'
'; echo 'The game keep the site\'s high score and every logged-in user\'s high score when score board is enabled. When someone ended a game (either won or game over) and if their high score more than your site\'s high score or their personal high score record, the game will save the new score. It is automatically saved for any logged-in users. If you enable to allow guest users to submit high score, an email field will appear to them before the score submission. The email address is required to notify them of new high score updates.'; } public function print_section_email() { echo 'Use %%SCORE%% in the email template below to replace with the new high score.'; } public function print_section_advanced() { echo '

Only modify the following options if you have compatibility issues or know what you are doing.

'; } public function print_section_customize() { echo '

This settings page is for default values when you are using shortcode [2048 custom=1] or when you have set to default the game to use the custom features on the settings tab. You able to customize various cosmetic elements of the game. For any fields you left blank or did not check the box(es) of enabled features, that particular option will fall back into the original 2048 appearance.

'; echo 'Tips on using custom image for tiles'; echo '

Minimum image dimension is 107px width and height. The game tiles resizes to 58px on smaller screens. Recommended to use a perfect square image. The plugin will force your image to appear in perfect square anyway. Do not use transparent PNGs as you will see overlapping image tiles when merging tiles.

'; //$this->print_customize_preview(); } public function print_section_shortcode() { echo '

Custom Shortcode

  '; echo '
'; echo '

By using the shortcode [2048 custom=1] on any page or post, it will display the game based on the saved values on this page. But that only gives you two options, either the original 2048 design or the customized settings here. The generate button above provides you unlimited 2048 game designs by generating custom shortcodes.

'; echo '

'; echo '
    '; echo '
  1. Perform your changes as required in the above settings form
  2. '; echo '
  3. Check/uncheck the boxes of custom features as needed
  4. '; echo '
  5. Do not submit the changes on this page
  6. '; echo '
  7. Click the Generate button
  8. '; echo '
'; } /** * AJAX Function: Generates Custom Shortcodes in Settings Page */ public function shortcode_generator() { check_ajax_referer( 'wp2048_ajax', 'security' ); parse_str($_POST['postdata'], $postdata); $custom = $postdata['wp2048_custom']; $feature = isset($custom['feature']) ? array_keys($custom['feature']) : array(); $sc = "[2048 custom=1"; $sc .= !empty($custom['feature']) ? " feature='".implode(",",$feature)."'" : ''; $sc .= ( !empty($custom['color']['font']) && in_array('fontcolor',$feature) ) ? " fontcolor=".$custom['color']['font'] : ''; $sc .= ( !empty($custom['color']['bg']) && in_array('bgcolor',$feature) ) ? " bgcolor=".$custom['color']['bg'] : ''; $sc .= ( !empty($custom['color']['grid']) && in_array('gridcolor',$feature) ) ? " gridcolor=".$custom['color']['grid'] : ''; $attrs = array('text','color','size'); foreach($attrs as $attr) { if ( !empty($custom[$attr]) && !empty($custom['feature'][$attr]) ) { $output = array(); foreach($this->tiles as $key => $tile) { $default = ($attr == 'text') ? $tile : 0; $output[$tile] = empty($custom[$attr][$tile]) ? $default : $custom[$attr][$tile]; } $sc .= " ".$attr."='".implode(",", $output)."'"; } } if ( !empty($custom['image']) && !empty($custom['feature']['image']) ) { $images = array(); foreach($this->tiles as $key => $tile) { $images[$tile] = empty($custom['image'][$tile]) ? 0 : $custom['image'][$tile]; } $sc .= "]".implode(",", $images)."[/2048"; } $sc .= "]"; echo $sc; die(); } /** * Get the settings option array and print one of its values */ public function checkbox_callback($args) { $field = $args['field']; $label = $args['label']; $checked = isset($this->option[$field]) ? checked( 1, $this->option[$field], false ) : ''; printf( '', $field, $checked ); printf( '', $field, $label ); } public function number_callback() { printf( '', isset( $this->option['id_number'] ) ? esc_attr( $this->option['id_number']) : '' ); } public function text_callback($args) { $field = $args['field']; $desc = $args['desc']; printf( ' %3$s', $field, isset( $this->option[$field] ) ? esc_attr( $this->option[$field]) : '', $desc ); } public function textarea_callback($args) { $field = $args['field']; $desc = $args['desc']; printf( '
%3$s', $field, isset( $this->option[$field] ) ? esc_attr( $this->option[$field]) : '', $desc ); } public function notify_callback() { $notify = isset($this->option['notify']) ? $this->option['notify']: ''; $html = ''; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; $html .= '
'; $html .= ''; $html .= ''; echo $html; } public function email_template_callback($args) { $field = $args['field']; $desc = $args['desc']; printf( ' Email subject cannot be left blank', $field, isset( $this->option['email_template'][$field]['subject'] ) ? esc_attr( $this->option['email_template'][$field]['subject'] ) : '' ); printf( '
%3$s', $field, isset( $this->option['email_template'][$field]['message'] ) ? esc_attr( $this->option['email_template'][$field]['message'] ) : '', $desc ); } public function colorpicker_callback($args) { $colortype = $args['type']; $default = array('font' => '#776e65', 'bg' => '#eee4da', 'grid' => '#bbada0'); printf( '', $colortype, isset( $this->custom['color'][$colortype] ) ? esc_attr( $this->custom['color'][$colortype] ) : '' ); printf( '  

Default color is   %2$s  

', $default[$colortype], $default[$colortype] ); } public function features_callback() { printf( '', isset($this->custom['feature']['text']) ? checked( 1, $this->custom['feature']['text'], false ) : '' ); printf( '
', __('Custom Tile\'s Text','wp2048') ); printf( '', isset($this->custom['feature']['size']) ? checked( 1, $this->custom['feature']['size'], false ) : '' ); printf( '
', __('Custom Font Size','wp2048') ); printf( '', isset($this->custom['feature']['image']) ? checked( 1, $this->custom['feature']['image'], false ) : '' ); printf( '
', __('Custom Tile\'s Image','wp2048') ); printf( '', isset($this->custom['feature']['color']) ? checked( 1, $this->custom['feature']['color'], false ) : '' ); printf( '
', __('Custom Tile\'s Color','wp2048') ); printf( '', isset($this->custom['feature']['fontcolor']) ? checked( 1, $this->custom['feature']['fontcolor'], false ) : '' ); printf( '
', __('Custom Font Color','wp2048') ); printf( '', isset($this->custom['feature']['bgcolor']) ? checked( 1, $this->custom['feature']['bgcolor'], false ) : '' ); printf( '
', __('Custom Background Color','wp2048') ); printf( '', isset($this->custom['feature']['gridcolor']) ? checked( 1, $this->custom['feature']['gridcolor'], false ) : '' ); printf( '
', __('Custom Grid Color','wp2048') ); echo '

'.__('Disabled features will fall back to default values in the original 2048','wp2048').'

'; } public function customize_callback($args) { $tile = $args['tile']; // Custom Text printf( '', $tile, ( !empty($this->custom['text'][$tile]) && $this->custom['text'][$tile] != $tile ) ? esc_attr( $this->custom['text'][$tile] ) : '' ); // Font Size printf( '  px', $tile, !empty( $this->custom['size'][$tile] ) ? esc_attr( $this->custom['size'][$tile] ) : '' ); echo '
'; // Image Upload $default_img = 'http://placehold.it/107&text='.$tile; $img = !empty( $this->custom['image'][$tile] ) ? esc_attr( $this->custom['image'][$tile] ) : $default_img; printf( '
', $img, $default_img ); printf( '', $tile, $img ); echo '  '; echo '
'; // Color Picker $default = array('#eee4da','#ede0c8','#f2b179','#f59563','#f67c5f','#f65e3b','#edcf72','#edcc61','#edc850','#edc53f','#edc22e'); $ckey = log((int)$tile,2) - 1; printf( '
', $tile, !empty( $this->custom['color'][$tile] ) ? esc_attr( $this->custom['color'][$tile] ) : '' ); printf( '  

Default color is   %2$s  

', $default[$ckey], $default[$ckey] ); } /** * Displays the Preview of 2048 Game Board */ private function print_customize_preview() { print '
2
4
8
16
32
64
128
256
512
1024
2048
'; } }