Changeset 3258349
- Timestamp:
- 03/19/2025 09:23:26 AM (11 months ago)
- Location:
- shorthand-connect
- Files:
-
- 87 added
- 17 deleted
- 8 edited
- 12 copied
-
tags/1.3.32 (copied) (copied from shorthand-connect/trunk)
-
tags/1.3.32/README.md (added)
-
tags/1.3.32/README.txt (deleted)
-
tags/1.3.32/class-shorthand-admin.php (added)
-
tags/1.3.32/class-shorthand.php (added)
-
tags/1.3.32/composer.json (added)
-
tags/1.3.32/config-default.php (added)
-
tags/1.3.32/config.default.php (deleted)
-
tags/1.3.32/css (added)
-
tags/1.3.32/css/connect.css (added)
-
tags/1.3.32/css/options-default.css (added)
-
tags/1.3.32/css/options-start.css (added)
-
tags/1.3.32/css/options.css (added)
-
tags/1.3.32/images (added)
-
tags/1.3.32/images/search.svg (added)
-
tags/1.3.32/includes/api-v2.php (deleted)
-
tags/1.3.32/includes/api.php (copied) (copied from shorthand-connect/trunk/includes/api.php) (11 diffs)
-
tags/1.3.32/includes/mass-pull.php (copied) (copied from shorthand-connect/trunk/includes/mass-pull.php) (2 diffs)
-
tags/1.3.32/includes/mass_pull.php (deleted)
-
tags/1.3.32/includes/shorthand-options-init.php (added)
-
tags/1.3.32/includes/shorthand-options-variables.php (added)
-
tags/1.3.32/includes/shorthand-options.php (copied) (copied from shorthand-connect/trunk/includes/shorthand-options.php) (6 diffs)
-
tags/1.3.32/includes/shorthand_options.php (deleted)
-
tags/1.3.32/includes/wp-api.php (added)
-
tags/1.3.32/index.php (modified) (1 diff)
-
tags/1.3.32/js (added)
-
tags/1.3.32/js/connect-form.js (added)
-
tags/1.3.32/js/connect-stories-fetch.js (added)
-
tags/1.3.32/js/connect-stories-list-selected.js (added)
-
tags/1.3.32/js/connect-stories-list.js (added)
-
tags/1.3.32/js/list.js (added)
-
tags/1.3.32/js/list.js/v2.3.4 (added)
-
tags/1.3.32/js/list.js/v2.3.4/list.js (added)
-
tags/1.3.32/js/list.js/v2.3.4/list.js.map (added)
-
tags/1.3.32/js/list.js/v2.3.4/list.min.js (added)
-
tags/1.3.32/js/list.js/v2.3.4/list.min.js.map (added)
-
tags/1.3.32/shorthand-connect.php (copied) (copied from shorthand-connect/trunk/shorthand-connect.php) (17 diffs)
-
tags/1.3.32/shorthand_connect.php (deleted)
-
tags/1.3.32/templates/abstract.php (copied) (copied from shorthand-connect/trunk/templates/abstract.php) (1 diff)
-
tags/1.3.32/templates/single-shorthand-story.php (added)
-
tags/1.3.32/templates/single-shorthand_story.php (deleted)
-
tags/1.3.32/trunk (copied) (copied from shorthand-connect/trunk)
-
tags/1.3.32/trunk/README.md (added)
-
tags/1.3.32/trunk/README.txt (deleted)
-
tags/1.3.32/trunk/class-shorthand-admin.php (added)
-
tags/1.3.32/trunk/class-shorthand.php (added)
-
tags/1.3.32/trunk/composer.json (added)
-
tags/1.3.32/trunk/config-default.php (added)
-
tags/1.3.32/trunk/config.default.php (deleted)
-
tags/1.3.32/trunk/css (added)
-
tags/1.3.32/trunk/css/connect.css (added)
-
tags/1.3.32/trunk/css/options-default.css (added)
-
tags/1.3.32/trunk/css/options-start.css (added)
-
tags/1.3.32/trunk/css/options.css (added)
-
tags/1.3.32/trunk/images (added)
-
tags/1.3.32/trunk/images/search.svg (added)
-
tags/1.3.32/trunk/includes/api-v2.php (deleted)
-
tags/1.3.32/trunk/includes/api.php (copied) (copied from shorthand-connect/trunk/includes/api.php) (11 diffs)
-
tags/1.3.32/trunk/includes/mass-pull.php (copied) (copied from shorthand-connect/trunk/includes/mass-pull.php) (2 diffs)
-
tags/1.3.32/trunk/includes/mass_pull.php (deleted)
-
tags/1.3.32/trunk/includes/shorthand-options-init.php (added)
-
tags/1.3.32/trunk/includes/shorthand-options-variables.php (added)
-
tags/1.3.32/trunk/includes/shorthand-options.php (copied) (copied from shorthand-connect/trunk/includes/shorthand-options.php) (6 diffs)
-
tags/1.3.32/trunk/includes/shorthand_options.php (deleted)
-
tags/1.3.32/trunk/includes/wp-api.php (added)
-
tags/1.3.32/trunk/index.php (modified) (1 diff)
-
tags/1.3.32/trunk/js (added)
-
tags/1.3.32/trunk/js/connect-form.js (added)
-
tags/1.3.32/trunk/js/connect-stories-fetch.js (added)
-
tags/1.3.32/trunk/js/connect-stories-list-selected.js (added)
-
tags/1.3.32/trunk/js/connect-stories-list.js (added)
-
tags/1.3.32/trunk/js/list.js (added)
-
tags/1.3.32/trunk/js/list.js/v2.3.4 (added)
-
tags/1.3.32/trunk/js/list.js/v2.3.4/list.js (added)
-
tags/1.3.32/trunk/js/list.js/v2.3.4/list.js.map (added)
-
tags/1.3.32/trunk/js/list.js/v2.3.4/list.min.js (added)
-
tags/1.3.32/trunk/js/list.js/v2.3.4/list.min.js.map (added)
-
tags/1.3.32/trunk/shorthand-connect.php (copied) (copied from shorthand-connect/trunk/shorthand-connect.php) (17 diffs)
-
tags/1.3.32/trunk/shorthand_connect.php (deleted)
-
tags/1.3.32/trunk/templates/abstract.php (copied) (copied from shorthand-connect/trunk/templates/abstract.php) (1 diff)
-
tags/1.3.32/trunk/templates/single-shorthand-story.php (added)
-
tags/1.3.32/trunk/templates/single-shorthand_story.php (deleted)
-
tags/1.3.32/trunk/views (added)
-
tags/1.3.32/trunk/views/notice.php (added)
-
tags/1.3.32/views (added)
-
tags/1.3.32/views/notice.php (added)
-
trunk/README.md (added)
-
trunk/README.txt (deleted)
-
trunk/class-shorthand-admin.php (added)
-
trunk/class-shorthand.php (added)
-
trunk/composer.json (added)
-
trunk/config-default.php (added)
-
trunk/config.default.php (deleted)
-
trunk/css (added)
-
trunk/css/connect.css (added)
-
trunk/css/options-default.css (added)
-
trunk/css/options-start.css (added)
-
trunk/css/options.css (added)
-
trunk/images (added)
-
trunk/images/search.svg (added)
-
trunk/includes/api.php (modified) (11 diffs)
-
trunk/includes/mass-pull.php (modified) (2 diffs)
-
trunk/includes/shorthand-options-init.php (added)
-
trunk/includes/shorthand-options-variables.php (added)
-
trunk/includes/shorthand-options.php (modified) (6 diffs)
-
trunk/includes/wp-api.php (added)
-
trunk/index.php (modified) (1 diff)
-
trunk/js (added)
-
trunk/js/connect-form.js (added)
-
trunk/js/connect-stories-fetch.js (added)
-
trunk/js/connect-stories-list-selected.js (added)
-
trunk/js/connect-stories-list.js (added)
-
trunk/js/list.js (added)
-
trunk/js/list.js/v2.3.4 (added)
-
trunk/js/list.js/v2.3.4/list.js (added)
-
trunk/js/list.js/v2.3.4/list.js.map (added)
-
trunk/js/list.js/v2.3.4/list.min.js (added)
-
trunk/js/list.js/v2.3.4/list.min.js.map (added)
-
trunk/shorthand-connect.php (modified) (17 diffs)
-
trunk/templates/abstract.php (modified) (1 diff)
-
trunk/templates/single-shorthand-story.php (added)
-
trunk/templates/single-shorthand_story.php (deleted)
-
trunk/views (added)
-
trunk/views/notice.php (added)
Legend:
- Unmodified
- Added
- Removed
-
shorthand-connect/tags/1.3.32/includes/api.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Shorthand API functions. 4 * 5 * @package Shorthand Connect 6 */ 2 7 3 8 /* … … 11 16 * @param array $options An array of extra options args to pass to wp_remote_request 12 17 */ 13 function sh _v2_api_request( $url, $options ) {18 function shorthand_api_v2_request( $url, $options ) { 14 19 $token = get_option( 'sh_v2_token' ); 15 20 if ( ! $token ) { … … 44 49 } 45 50 46 function sh_v2_api_request_json( $url, $options ) { 47 $response = sh_v2_api_request( $url, $options ); 51 /** 52 * Makes a JSON API request to the shorthand API. 53 * 54 * @param string $url The URL of the API endpoint. 55 * @param array $options Optional arguments for the API request. 56 * @return mixed The decoded JSON response, or null if an error occurs. 57 */ 58 function shorthand_api_request_json( $url, $options ) { 59 $response = shorthand_api_v2_request( $url, $options ); 48 60 $body = wp_remote_retrieve_body( $response ); 49 61 return json_decode( $body ); 50 62 } 51 63 52 function sh_get_profile() { 64 /** 65 * Retrieves user profile information from the shorthand API. 66 * 67 * @return object User profile information, including username, gravatar, and other potential data. 68 */ 69 function shorthand_api_get_profile() { 53 70 $tokeninfo = array(); 54 71 55 $data = sh _v2_api_request_json( '/v2/token-info', array() );72 $data = shorthand_api_request_json( '/v2/token-info', array() ); 56 73 if ( $data && isset( $data->organisation_id ) ) { 57 74 $tokeninfo['username'] = $data->name . ' (' . $data->token_type . ' Token)'; … … 63 80 } 64 81 65 function sh_get_stories() { 82 /** 83 * Retrieves stories from the shorthand API. 84 * 85 * Fetches a list of stories from the shorthand API, optionally filtered by keyword. 86 * 87 * @param string $keyword Optional keyword to filter stories by. 88 * @return array|null An array of story data, or null if an error occurs or no stories are found. 89 */ 90 function shorthand_api_get_stories( string $keyword = '', string $cursor = '', string $limit = '50' ) { 66 91 $stories = null; 67 68 $data = sh_v2_api_request_json( '/v2/stories', array( 'timeout' => '240' ) ); 92 $url = '/v2/stories'; 93 $url .= '?limit='.$limit; 94 if ( $cursor && $cursor != '') { 95 $url .= '&cursor=' . $cursor; 96 } 97 if ( $keyword && $keyword != '' ) { 98 $url .= '&keyword=' . $keyword; 99 } 100 101 102 $data = shorthand_api_request_json( $url, array( 'timeout' => '240' ) ); 69 103 if ( $data ) { 70 104 $stories = array(); 71 // Something went wrong 105 // Something went wrong. 72 106 if ( isset( $data->status ) && $data->status ) { 73 107 return null; 74 108 } 109 75 110 foreach ( $data as $storydata ) { 76 $story = array( 77 'image' => $storydata->signedCover, 78 'id' => $storydata->id, 79 'metadata' => (object) array( 80 'description' => $storydata->description, 81 ), 82 'title' => $storydata->title, 83 'story_version' => '' . $storydata->version, 111 $updated_timestamp = strtotime( esc_html( $storydata->updatedAt ) ); 112 $updated_at = $storydata->updatedAt; 113 $published_timestamp = strtotime( esc_html( $storydata->lastPublishedAt ) ); 114 $updated = human_time_diff( $updated_timestamp, current_time( 'timestamp' ) ); 115 $published = human_time_diff( $published_timestamp, current_time( 'timestamp' ) ); 116 $stories[] = array( 117 'version_value' => '' . $storydata->version, 118 'title' => $storydata->title, 119 'description' => $storydata->description, 120 'imagealt' => $storydata->title, 121 'image' => $storydata->signedCover, 122 'updated_timestamp' => $updated_timestamp, 123 'updated_at' => $updated_at, 124 'updated_value' => $updated, 125 'published_timestamp' => $published_timestamp, 126 'published_value' => $published, 127 'story_id' => $storydata->id, 128 'class' => 'story', 84 129 ); 85 $stories[] = (object) $story;86 130 } 87 131 } … … 90 134 } 91 135 136 /** 137 * Gets the path to the story directory. 138 * 139 * Determines the path to the directory where story files for a specific post 140 * and story ID should be stored. 141 * 142 * @param int $post_id The ID of the post. 143 * @param string $story_id The ID of the story. 144 * @return string|null The path to the story directory, or null if the directory doesn't exist or an error occurs. 145 */ 92 146 function sh_get_story_path( $post_id, $story_id ) { 93 147 init_wp_filesystem(); … … 95 149 $destination_path = $destination['path'] . '/shorthand/' . $post_id . '/' . $story_id; 96 150 97 // on WP VIP, folders in the uploads dir always exist151 // On WP VIP, folders in the uploads dir always exist. 98 152 if ( ! file_exists( $destination_path ) ) { 99 153 $destination_path = null; … … 105 159 } 106 160 161 /** 162 * Gets the URL of the story directory. 163 * 164 * Determines the URL of the directory where story files for a specific post 165 * and story ID are located. 166 * 167 * @param int $post_id The ID of the post. 168 * @param string $story_id The ID of the story. 169 * @return string The URL of the story directory. 170 */ 107 171 function shorthand_get_story_url( $post_id, $story_id ) { 108 172 init_wp_filesystem(); … … 123 187 $story = array(); 124 188 125 // Attempt to connect to the server 126 $zip_file = wp_tempnam( 'sh_zip', $tmpdir );127 $response = sh_v2_api_request(189 // Attempt to connect to the server. 190 $zip_file = wp_tempnam( 'sh_zip', $tmpdir ); 191 $response = shorthand_api_v2_request( 128 192 '/v2/stories/' . $story_id . ( $without_assets ? '?without_assets=true' : '' ) . ( $assets_only ? '?assets_only=true' : '' ), 129 193 array( … … 145 209 ); 146 210 } else { 147 $story = extract StoryContent( $zip_file, $destination_path, $story_id );211 $story = extract_story_content( $zip_file, $destination_path, $story_id ); 148 212 } 149 213 … … 153 217 } 154 218 155 219 /** 220 * Initializes the WordPress filesystem. 221 * 222 * Ensures that the WordPress filesystem is available for file operations. 223 * If not, it requests filesystem credentials and re-initializes the filesystem. 224 */ 156 225 function init_wp_filesystem() { 157 226 WP_Filesystem(); … … 163 232 } 164 233 165 function extractStoryContent( $zip_file, $destination_path, $story_id ) { 234 /** 235 * Extracts story content from a ZIP file. 236 * 237 * Extracts the 'head.html' and 'article.html' files from a given ZIP file 238 * into a specified destination path. 239 * 240 * @param string $zip_file The path to the ZIP file. 241 * @param string $destination_path The path to the extraction destination. 242 * @param string $story_id The ID of the story. 243 * @return array An array containing extracted content, path, or error information. 244 */ 245 function extract_story_content( $zip_file, $destination_path, $story_id ) { 166 246 // WP VIP HOSTING COMPATIBILITY 167 247 $zip = new ZipArchive(); -
shorthand-connect/tags/1.3.32/includes/mass-pull.php
r3095659 r3258349 1 1 <?php 2 /* 3 * Sets each custom meta field, should be paired with sh_copy_story().2 /** 3 * Bulk story pull functions. 4 4 * 5 * @package Shorthand Connect 6 */ 7 8 /** 9 * Updates a story for a given post. 10 * 11 * Fetches story data from the shorthand API, copies story files, updates post 12 * metadata, and performs post-processing on the story content. 5 13 * Note: Unzipping a fresh story copy won't update the fields. 14 * 15 * @param int $post_id The ID of the post. 16 * @param string $story_id The ID of the story. 6 17 */ 7 18 function shand_update_story( $post_id, $story_id ) { … … 14 25 15 26 // Grab JSON for Story & Set into object $obj. 16 $obj = sh _v2_api_request_json( '/v2/stories/' . $story_id . '/settings', array( 'timeout' => '240' ) );27 $obj = shorthand_api_request_json( '/v2/stories/' . $story_id . '/settings', array( 'timeout' => '240' ) ); 17 28 18 29 $err = sh_copy_story( $post_id, $safe_story_id, $sh_media_cron_offload ); -
shorthand-connect/tags/1.3.32/includes/shorthand-options.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Admin settings for the first time dialog. 4 * 5 * @package Shorthand Connect 6 */ 7 2 8 /* Options */ 3 function shand_shorthand_menu() { 4 add_options_page( 'Shorthand Options', 'Shorthand', 'manage_options', 'shorthand-options', 'shand_shorthand_options' ); 5 } 6 $default_sh_site_css = ' 7 /* START CSS FOR DEFAULT WP THEMES */ 8 .site { 9 margin: 0; 10 max-width: none; 11 } 12 .site-content { 13 padding: 0 !important; 14 } 15 .site-inner { 16 max-width: none; 17 } 18 .site-header { 19 max-width: none; 20 z-index: 100; 21 } 22 .site:before { 23 width: 0; 24 } 25 /* END CSS FOR DEFAULT WP THEMES */ 26 '; 27 28 // JSON Checker 29 function validate_json( $json_string ) { 30 // Try to decode the JSON data. If it fails, the JSON is invalid. 31 $json_data = json_decode( $json_string, true ); 32 33 if ( json_last_error() !== JSON_ERROR_NONE ) { 34 // The JSON is invalid. 35 return false; 36 } 37 38 // Return the original JSON string if it's valid. 39 return $json_string; 40 } 41 42 function shand_shorthand_options() { 43 global $default_sh_site_css; 44 global $server_url; 45 46 // Rather than running a rewrite flush everytime a post is submitted, run it on plugin activate/deactivate 47 function shand_rewrite_flush() { 48 shand_create_post_type(); 49 flush_rewrite_rules(); 50 } 51 register_activation_hook( __FILE__, 'shand_rewrite_flush' ); 52 register_deactivation_hook( __FILE__, 'flush_rewrite_rules' ); 9 10 // Redirect to the first time setup. 11 function shorthand_redirect_admin_config() { 12 $profile = shorthand_api_get_profile(); 13 if ( isset( $_GET['page'] ) && ( 'shorthand-options' === $_GET['page'] ) && ( ! $profile ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 14 $admin_url = Shorthand_Admin::get_page_url( 'init' ); 15 wp_redirect( $admin_url ); 16 die(); 17 } 18 } 19 add_action( 'admin_menu', 'shorthand_redirect_admin_config' ); 20 21 function shorthand_shorthand_options() { 22 // Menu links. 23 $menu_links = array( 24 'token' => 'API Key', 25 'permalink' => 'Permalinks', 26 'css' => 'Custom CSS', 27 'processing' => 'Post-processing', 28 'experimental' => 'Experimental Features', 29 ); 30 31 // If current = all, then display all. 32 $current = isset( $_GET['navigation'] ) ? sanitize_key( $_GET['navigation'] ) : array_keys( $menu_links )[0]; 33 $profile = shorthand_api_get_profile(); 34 $messages = array(); 53 35 54 36 if ( ! current_user_can( 'manage_options' ) ) { 55 37 wp_die( esc_html( __( 'You do not have sufficient permissions to access this page.' ) ) ); 56 38 } 39 57 40 if ( isset( $_POST['sh_submit_hidden'] ) && 'Y' === $_POST['sh_submit_hidden'] && check_admin_referer( 'sh-update-configuration' ) ) { 58 41 // If there's a token set, use it, if not set it to an empty string 59 42 $sh_v2_token = isset( $_POST['sh_v2_token'] ) ? sanitize_text_field( $_POST['sh_v2_token'] ) : ''; 60 43 update_option( 'sh_v2_token', $sh_v2_token ); 44 45 $profile = shorthand_api_get_profile(); 46 if ( $profile ) { 47 $messages['updated'] = '<p>' . SHORTHAND_CONFIG_STEP1_SUCCESS . '</p><p><strong>Username</strong>: ' . esc_html( $profile->username ) . '</p>'; 48 } else { 49 $messages['notice-error'] = SHORTHAND_CONFIG_STEP1_ERROR; 50 } 61 51 } 62 52 … … 64 54 65 55 if ( isset( $_POST['sh_submit_hidden_two'] ) && 'Y' === $_POST['sh_submit_hidden_two'] && check_admin_referer( 'sh-update-configuration' ) ) { 66 // Check if there's custom CSS, if there is, use wp_kses_post() to sanitize otherwise set an empty string 56 // Check if there's custom CSS, if there is, use wp_kses_post() 57 // to sanitize otherwise set an empty string. 67 58 $sh_css = isset( $_POST['sh_css'] ) ? wp_kses_post( $_POST['sh_css'] ) : ''; 68 59 update_option( 'sh_css', $sh_css ); 60 $messages['updated'] = SHORTHAND_CONFIG_STEP3_SUCCESS; 69 61 } 70 62 71 63 if ( isset( $_POST['sh_submit_hidden_three'] ) && 'Y' === $_POST['sh_submit_hidden_three'] && check_admin_referer( 'sh-update-configuration' ) ) { 72 // Check if there's custom permalink, if there is, use sanitize_text_field() to sanitize potential HTML and then set an empty string 64 // Check if there's custom permalink, if there is, use sanitize_text_field() 65 // to sanitize potential HTML and then set an empty string. 73 66 $sh_permalink = isset( $_POST['sh_permalink'] ) ? sanitize_text_field( $_POST['sh_permalink'] ) : ''; 74 67 update_option( 'sh_permalink', $sh_permalink ); 75 shand_rewrite_flush(); 68 shorthand_rewrite_flush(); 69 $messages['updated'] = SHORTHAND_CONFIG_STEP2_SUCCESS; 76 70 } 77 71 $permalink_structure = esc_html( get_option( 'sh_permalink' ) ); … … 82 76 } 83 77 $sh_css = get_option( 'sh_css' ); 84 $no_css = false; 85 if ( '' === $sh_css ) { 86 $no_css = true; 87 if ( isset( $default_site_css ) ) { 88 update_option( 'sh_css', $default_site_css ); 89 } 90 $sh_css = $default_sh_site_css; 91 } 92 93 if ( isset( $_POST['sh_submit_hidden_four'] ) && 'Y' === $_POST['sh_submit_hidden_four'] && check_admin_referer( 'sh-update-configuration' ) ) { 94 $sh_regex_list = isset( $_POST['sh_regex_list'] ) ? wp_unslash( $_POST['sh_regex_list'] ) : ''; 95 78 79 if ( isset( $_POST['sh_submit_hidden_four'] ) && 80 ( 'Y' === $_POST['sh_submit_hidden_four'] ) && 81 check_admin_referer( 'sh-update-configuration' ) 82 ) { 83 // sh_regex_list may contain <tags> for lookup and processing on import and so may need to include <script> etc; however it is only ever displayed within a text-area value and manually processed. 84 $sh_regex_list = empty( $_POST['sh_regex_list'] ) ? '' : wp_unslash( $_POST['sh_regex_list'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 85 86 $messages['updated'] = SHORTHAND_CONFIG_STEP4_SUCCESS; 96 87 if ( empty( $sh_regex_list ) ) { 97 // Update the option with an empty value if the input is empty 88 // Update the option with an empty value if the input is empty. 98 89 update_option( 'sh_regex_list', '' ); 99 90 } else { 100 91 // Validate if it's a valid JSON without sanitizing 101 $sh_regex_list = validate_json( $sh_regex_list );92 $sh_regex_list = Shorthand_Admin::validate_json( $sh_regex_list ); 102 93 103 94 if ( false !== $sh_regex_list ) { … … 106 97 } else { 107 98 // Handle invalid JSON error here. 99 unset( $messages['updated'] ); 100 $messages['notice-error'] = SHORTHAND_CONFIG_STEP4_ERROR; 108 101 } 109 102 } … … 112 105 $sh_regex_list = base64_decode( get_option( 'sh_regex_list' ) ); 113 106 114 // Experimental Settings107 // Experimental settings. 115 108 if ( isset( $_POST['sh_submit_hidden_experimental'] ) && 'Y' === $_POST['sh_submit_hidden_experimental'] && check_admin_referer( 'sh-update-configuration' ) ) { 116 109 $sh_media_cron_offload = isset( $_POST['sh_media_cron_offload'] ) ? filter_var( $_POST['sh_media_cron_offload'], FILTER_VALIDATE_BOOLEAN ) : false; … … 118 111 update_option( 'sh_media_cron_offload', $sh_media_cron_offload ); 119 112 update_option( 'sh_disable_acf', $sh_disable_acf ); 113 $messages['updated'] = SHORTHAND_CONFIG_STEP5_SUCCESS; 120 114 } 121 115 $sh_media_cron_offload = filter_var( get_option( 'sh_media_cron_offload' ), FILTER_VALIDATE_BOOLEAN ); 122 116 $sh_disable_acf = filter_var( get_option( 'sh_disable_acf' ), FILTER_VALIDATE_BOOLEAN ); 123 117 124 $profile = sh_get_profile(); 125 ?> 126 <div class="container"> 127 <div class="py-1"> 128 <h1>Shorthand API Configuration</h1> 129 <h2>Shorthand Connect Status</h2> 130 <form name="formtoken" method="post"> 131 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 132 <input type="hidden" name="sh_submit_hidden" value="Y" /> 133 <table class="form-table"><tbody> 134 <tr class="v2row"> 135 <th scope="row"><label for="sh_v2_token"><?php esc_html_e( 'Shorthand Team Token', 'sh-v2-token' ); ?></label></th> 136 <td><input type="text" id="sh_v2_token" name="sh_v2_token" value="<?php echo esc_attr( $v2_token ); ?>" size="28"></td> 137 </tr> 138 </tbody></table> 139 <?php if ( $profile ) { ?> 140 <p class="status">Successfully connected</p> 141 <p><strong>Username</strong>: <?php echo esc_html( $profile->username ); ?></p> 142 <?php } else { ?> 143 <p class="status warn">Not Connected</p> 144 <?php } ?> 145 <div style='clear:both'></div> 146 <p class="submit"> 147 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 118 ?> 119 <div class="wrap shorthand-options-wrapper"> 120 <h1>Settings</h1> 121 122 <hr /> 123 <div class="shorthand-menu"> 124 <ol role="list"> 125 <?php foreach ( $menu_links as $menu_key => $menu_name ) { ?> 126 <li class="py-1"> 127 <form name="menu_settings_<?php echo esc_attr( $menu_key ); ?>" method="post" action="<?php echo esc_url( Shorthand_Admin::get_page_url( 'config', esc_attr( $menu_key ) ) ); ?>"> 128 <input type="submit" name="Submit" class="button<?php echo ( in_array( $current, array( $menu_key, 'all' ) ) ) ? ' button button-primary' : ''; ?>" value="<?php esc_attr_e( $menu_name ); ?>" /> 129 </form> 130 </li> 131 <?php } ?> 132 </ol> 133 </div> 134 135 <div class="shorthand-form-wrapper"> 136 <form name="form_settings" method="post" action="<?php echo esc_url( Shorthand_Admin::get_page_url( 'config', esc_attr( $current ) ) ); ?>"> 137 138 <?php if ( ! empty( $messages ) ) : ?> 139 <?php foreach ( $messages as $class => $message ) : ?> 140 <div class="notice <?php echo esc_html ( $class ); ?>"><?php echo wp_kses( $message, array( 141 'p' => array(), 142 'strong' => array(), 143 ) ); ?></div> 144 <?php endforeach; ?> 145 <?php endif; ?> 146 147 <?php if ( in_array( $current, array( array_keys( $menu_links )[0], 'all' ) ) ) : ?> 148 <div class="py-1"> 149 <h2>Shorthand API Key</h2> 150 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 151 <input type="hidden" name="sh_submit_hidden" value="Y"/> 152 <p><label for="sh_v2_token"><?php esc_html_e( 'Your API key provided by Shorthand', 'shorthand-connect' ); ?></label></p> 153 <input type="text" id="sh_v2_token" name="sh_v2_token" value="<?php echo esc_attr( $v2_token ); ?>"> 154 <p> 155 <?php esc_html_e( 'Do not have API key?', 'shorthand-connect' ); ?> <a target="_blank" alt="(<?php esc_html_e( 'opens Shorthand Connect plugin settings', 'shorthand-connect' ); ?>)" href="https://support.shorthand.com/en/articles/62-programmatic-publishing-with-the-shorthand-api"><?php esc_html_e( 'Get one here', 'shorthand-connect' ); ?></a> 148 156 </p> 149 </form> 150 </div> 151 152 153 <div class="py-1"> 154 <h2>Shorthand Permalink Structure</h2> 155 <p>Use this to set the permalink structure of Shorthand story URLs</p> 156 <form name="permalinks" method="post"> 157 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 158 <input type="hidden" name="sh_submit_hidden_three" value="Y" /> 159 <p> 160 <?php _e( 'Permalink structure:', 'sh-permalink-value' ); ?><br /><?php echo esc_url( get_site_url() ); ?>/<input type="text" name="sh_permalink" value="<?php echo esc_attr( $permalink_structure ); ?>" size="20">/{STORY_NAME} 161 </p> 162 <p class="submit"> 163 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 164 </p> 165 </form> 166 </div> 167 168 <div class="py-1"> 169 <h2>Shorthand Story Page CSS (theme wide CSS)</h2> 170 <p>Use this CSS to customise Shorthand Story pages to better suit your theme</p> 171 <?php if ( $no_css ) { ?> 172 <p class="status warn">No custom CSS found, using default theme CSS</p> 173 <?php } ?> 174 <form name="themecss" method="post"> 175 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 176 <input type="hidden" name="sh_submit_hidden_two" value="Y" /> 177 <textarea rows="10" cols="80" name="sh_css"><?php echo esc_textarea( $sh_css ); ?></textarea> 178 <p class="submit"> 179 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 180 </p> 181 </form> 182 </div> 183 184 <div class="py-1"> 185 <h2>Post-processing</h2> 186 <p>Use this to create a JSON object of regex queries and replacements.</p> 157 <div style='clear:both'></div> 158 </div> 159 <?php endif; ?> 160 161 <?php if ( in_array( $current, array( array_keys( $menu_links )[1], 'all' ) ) ) : ?> 162 <div class="py-1"> 163 <h2>Permalink Structure</h2> 164 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 165 <input type="hidden" name="sh_submit_hidden_three" value="Y"/> 166 <p> 167 <p><label for="sh_permalink"><?php esc_html_e( 'Set the permalink structure of Shorthand story URLs', 'shorthand-connect' ); ?></label></p> 168 <input type="text" name="sh_permalink" value="<?php echo esc_attr( $permalink_structure ); ?>" size="20"> 169 <p><?php echo esc_url( get_site_url() ); ?>/<strong><?php echo esc_html( $permalink_structure ); ?></strong>/{STORY_NAME}</p> 170 </div> 171 <?php endif; ?> 172 173 <?php if ( in_array( $current, array( array_keys( $menu_links )[2], 'all' ) ) ) : ?> 174 <div class="py-1"> 175 <h2>Custom CSS</h2> 176 <p>Use theme wide CSS to customise Shorthand Story pages to better suit your theme</p> 177 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 178 <input type="hidden" name="sh_submit_hidden_two" value="Y"/> 179 <textarea rows="10" cols="80" name="sh_css"><?php echo esc_textarea( $sh_css ); ?></textarea> 180 </div> 181 <?php endif; ?> 182 183 <?php if ( in_array( $current, array( array_keys( $menu_links )[3], 'all' ) ) ) : ?> 184 <div class="py-1"> 185 <h2>Post-processing</h2> 186 <p>Create a JSON object of regex queries and replacements.</p> 187 187 <p><em>This Example removes title tags from within the head tag by replacing it with nothing.</em></p> 188 <pre><code>188 <pre><code class="post-processing"> 189 189 { 190 190 "head": [ 191 191 { 192 "query": "/<title>(.*?)<\\/title>/",193 "replace": ""192 "query": "/<title>(.*?)<\\/title>/", 193 "replace": "" 194 194 } 195 195 ], 196 196 "body": [] 197 197 } 198 199 </code></pre> 200 <form name="postprocessing" method="post"> 201 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 202 <input type="hidden" name="sh_submit_hidden_four" value="Y" /> 203 <textarea rows="10" cols="80" id="sh_regex_list" name="sh_regex_list"><?php echo esc_textarea( $sh_regex_list ); ?></textarea> 204 <p class="submit"> 205 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 206 </p> 207 </form> 198 </code></pre> 199 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 200 <input type="hidden" name="sh_submit_hidden_four" value="Y"/> 201 <textarea rows="10" cols="80" id="sh_regex_list" 202 name="sh_regex_list"><?php echo esc_textarea( $sh_regex_list ); ?></textarea> 208 203 <script> 209 204 let textarea = document.querySelector("textarea#sh_regex_list"); 210 211 textarea.addEventListener("keyup", function(event) { 212 try { 213 JSON.parse(textarea.value); 205 206 textarea.addEventListener("keyup", function (event) { 207 try { 208 textarea.value = JSON.stringify(JSON.parse(textarea.value), undefined, 4); 209 textarea.setCustomValidity(""); 210 211 } catch (err) { 212 if (textarea.value != "") { 213 console.log("Invalid JSON"); 214 textarea.setCustomValidity("Invalid JSON in the Post-processing field"); 215 } else { 214 216 textarea.setCustomValidity(""); 215 216 } catch(err) {217 if(textarea.value != ""){218 console.log("Invalid JSON");219 textarea.setCustomValidity("Invalid JSON in the Post-processing field");220 } else {221 textarea.setCustomValidity("");222 }223 217 } 224 218 } 219 225 220 }); 226 221 </script> 227 </div> 228 229 <div class="py-1"> 230 <h2>Experimental Features</h2> 231 <p>Early access features that are still subject to change.</p> 232 <form name="form_experimental" method="post"> 233 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 222 </div> 223 <?php endif; ?> 224 225 <?php if ( in_array( $current, array( array_keys( $menu_links )[4], 'all' ) ) ) : ?> 226 <div class="py-1"> 227 <h2>Experimental Features <span class="badge badge-blue">Advanced</span></h2> 228 <p>Early access features that are still subject to change.</p> 229 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 234 230 <input type="hidden" name="sh_submit_hidden_experimental" value="Y"/> 235 <input type="checkbox" id="sh_media_cron_offload" name="sh_media_cron_offload" 236 value="true" <?php echo esc_attr( $sh_media_cron_offload ? 'checked' : '' ); ?> /> 237 <label for="sh_media_cron_offload">Import media assets via cron</label> 238 <p>Assets will be fetched after story save to prevent potential execution timeouts. Media won't be immediately 239 available on save but progress will be updated based on the `media_status` field.</p> 240 <p>It is advised that Shorthand Story Posts are saved as a draft first to trigger the cron job prior to public 241 publishing.</p> 231 232 <div class="checkbox-container"> 233 <input type="checkbox" id="sh_media_cron_offload" name="sh_media_cron_offload" <?php echo esc_attr( $sh_media_cron_offload ? 'checked' : '' ); ?> /> 234 <div class="bordered"> 235 <label for="sh_media_cron_offload"><strong>Import media assets via cron</strong> 236 <p>Assets will be fetched after story save to prevent potential execution timeouts. Media won't be immediately 237 available on save but progress will be updated based on the `media_status` field.</p> 238 <p>It is advised that Shorthand Story Posts are saved as a draft first to trigger the cron job prior to public 239 publishing.</p> 240 </label> 241 </div> 242 </div> 243 242 244 <br/> 245 <div class="checkbox-container"> 243 246 <input type="checkbox" id="sh_disable_acf" name="sh_disable_acf" 244 value="true" <?php echo esc_attr( $sh_disable_acf ? 'checked' : '' ); ?> />245 < label for="sh_disable_acf">Disable Advanced Custom Fields</label>246 <p>Used to prevent any potential issues that could cause the Shorthand Custom Fields to become hidden by Advanced247 Custom Fields.</p>247 value="true" <?php echo esc_attr( $sh_disable_acf ? 'checked' : '' ); ?> /> 248 <div class="bordered"><label for="sh_disable_acf"><strong>Disable Advanced Custom Fields</strong> 249 <p>Used to prevent any potential issues that could cause the Shorthand Custom Fields to become hidden by Advanced Custom Fields.</p></label></div> 250 </div> 248 251 </br> 252 </div> 253 <?php endif; ?> 254 255 <div class="py-1"> 256 <hr /> 249 257 <p class="submit"> 250 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>"/>258 <input type="submit" name="Submit" class="button button-primary" value="<?php esc_attr_e( 'Save changes' ); ?>"/> 251 259 </p> 260 </div> 252 261 </form> 253 </div> 254 </div> 255 </div> 256 <style> 257 .py-1 { 258 padding: 1em; 259 } 260 .bg-white { 261 background: white; 262 } 263 .container { 264 max-width: 980px; 265 } 266 img.grav { 267 float: left; 268 width:80px; 269 margin-right:10px; 270 } 271 p.status { 272 background:#dfd; 273 color:green; 274 font-weight:bold; 275 width:350px; 276 clear:left; 277 padding:5px; 278 } 279 p.status.warn { 280 background:#ffd; 281 color:orange; 282 } 283 .row-hidden { 284 display:none; 285 } 286 #wpfooter { 287 position: unset; 288 } 289 code { 290 font-family: monospace; 291 display: inherit; 292 } 293 </style> 294 262 263 </div> 264 </div> 265 </div> 295 266 296 267 <?php 297 268 } 298 269 299 add_action( 'admin_menu', 'shand_shorthand_menu' ); 300 301 ?> 270 function registerStyles() { 271 // Adding styles. 272 $css_path = '../css/options.css'; 273 wp_register_style( 'options_style', plugin_dir_url( __FILE__ ) . $css_path, array(), '1.3', 'all' ); 274 wp_enqueue_style( 'options_style' ); 275 } 276 277 add_action( 'init', 'registerStyles' ); 278 -
shorthand-connect/tags/1.3.32/index.php
r2898299 r3258349 1 <?php // Silence is golden 1 <?php 2 // Silence is golden. -
shorthand-connect/tags/1.3.32/shorthand-connect.php
r3095659 r3258349 1 1 <?php 2 2 /** 3 * Main plugin file. 4 * 3 5 * @package Shorthand Connect 4 * @version 1.3.315 6 */ 6 7 … … 10 11 Description: Import your Shorthand stories into your WordPress CMS as simply as possible - magic! 11 12 Author: Shorthand 12 Version: 1.3.3 113 Version: 1.3.32 13 14 Author URI: http://shorthand.com 14 15 */ 15 16 16 if ( file_exists( plugin_dir_path( __FILE__ ) . 'config.php' ) ) { 17 include_once plugin_dir_path( __FILE__ ) . 'config.php'; 17 // Make sure we don't expose any info if called directly. 18 if ( ! function_exists( 'add_action' ) ) { 19 echo 'Hi there! I\'m just a plugin, not much I can do when called directly.'; 20 exit; 21 } 22 23 define( 'SHORTHAND_VERSION', '1.3.32' ); 24 define( 'SHORTHAND__MINIMUM_WP_VERSION', '5.8' ); 25 define( 'SHORTHAND__PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 26 27 require_once SHORTHAND__PLUGIN_DIR . 'class-shorthand.php'; 28 29 // Add config. 30 if ( file_exists( SHORTHAND__PLUGIN_DIR . 'config.php' ) ) { 31 include_once SHORTHAND__PLUGIN_DIR . 'config.php'; 18 32 } else { 19 include_once plugin_dir_path( __FILE__ ) . 'config.default.php'; 20 } 21 require_once plugin_dir_path( __FILE__ ) . 'includes/api.php'; 22 require_once plugin_dir_path( __FILE__ ) . 'includes/mass-pull.php'; 23 24 require_once plugin_dir_path( __FILE__ ) . 'includes/shorthand-options.php'; 25 require_once plugin_dir_path( __FILE__ ) . 'templates/abstract.php'; 33 include_once SHORTHAND__PLUGIN_DIR . 'config-default.php'; 34 } 35 36 require_once SHORTHAND__PLUGIN_DIR . 'includes/api.php'; 37 require_once SHORTHAND__PLUGIN_DIR . 'includes/wp-api.php'; 38 require_once SHORTHAND__PLUGIN_DIR . 'includes/mass-pull.php'; 39 40 if ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) { 41 require_once SHORTHAND__PLUGIN_DIR . 'class-shorthand-admin.php'; 42 add_action( 'init', array( 'Shorthand_Admin', 'init' ) ); 43 } 44 45 // Loading initial setup or general configuration. 46 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options-variables.php'; 47 if ( isset( $_GET['view'] ) && ( $_GET['view'] === 'start' )) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 48 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options-init.php'; 49 } else { 50 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options.php'; 51 } 52 53 // Added admin menu. 54 function shorthand_shorthand_menu() { 55 add_options_page( 'Shorthand Options', 'Shorthand', 'manage_options', 'shorthand-options', 'shorthand_shorthand_options' ); 56 } 57 add_action( 'admin_menu', 'shorthand_shorthand_menu' ); 58 59 require_once SHORTHAND__PLUGIN_DIR . 'templates/abstract.php'; 26 60 27 61 if ( ! function_exists( 'WP_Filesystem' ) ) { … … 73 107 add_action( 'init', 'shand_create_post_type' ); 74 108 75 function sh and_wpt_shorthand_story() {109 function shorthand_wpt_shorthand_story() { 76 110 global $post; 77 global $server_url;78 111 global $show_archived_stories; 79 112 $baseurl = ''; 80 113 81 ?> 82 <style> 83 li.story { 84 float: left; 85 width: 160px; 86 margin: 5px; 87 } 88 89 li.story.selected label { 90 background: #5b9dd9; 91 color: #eee; 92 } 93 94 li.story input { 95 display: none !important; 96 } 97 98 li.story label { 99 display: block; 100 background: #fafafa; 101 text-align: center; 102 height: 160px; 103 padding-top: 5px; 104 border: 1px solid #eeeeee; 105 } 106 107 li.story label:hover { 108 border: 1px solid #5b9dd9; 109 } 110 111 li.story label span { 112 display: block; 113 font-weight: bold; 114 } 115 116 li.story label span.desc { 117 display: none; 118 } 119 120 div.clear { 121 clear: left; 122 } 123 124 div.publishing-actions { 125 padding: 10px; 126 clear: both; 127 border-top: 1px solid #dcdcde; 128 background: #f6f7f7; 129 margin: -12px; 130 margin-top: -12px; 131 margin-top: 10px; 132 display: flex; 133 justify-content: center; 134 } 135 136 .button-shorthand { 137 background-color: #000; 138 border: 1px solid #000; 139 transition: background-color .15s ease, color .15s ease; 140 color: #fff; 141 font-family: poppins, sans-serif; 142 font-size: 13px; 143 font-weight: 600; 144 letter-spacing: 0; 145 line-height: 1; 146 padding: 1em 2em; 147 text-decoration: none; 148 cursor: pointer; 149 border-radius: .9em; 150 } 151 152 .button-shorthand:hover { 153 background-color: #fff; 154 border-color: #000; 155 color: #000; 156 } 157 158 .button-shorthand:disabled { 159 pointer-events: none; 160 } 161 162 #codearea { 163 border: 1px solid #999999; 164 font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace; 165 width: 100%; 166 height: 300px; 167 } 168 169 #abstract { 170 border: 1px solid #999999; 171 width: 100%; 172 height: 200px; 173 } 174 175 ul.stories { 176 max-height: 400px; 177 overflow-y: scroll; 178 } 179 180 ul.stories img { 181 object-fit: cover; 182 height: 110px; 183 } 184 185 p.warning { 186 color: red; 187 font-weight: bold; 188 } 189 </style> 190 <?php 114 // Adding styles. 115 $css_path = 'css/connect.css'; 116 wp_register_style( 'connect_style', plugin_dir_url( __FILE__ ) . $css_path, array(), '1.3', 'all' ); 117 wp_enqueue_style( 'connect_style' ); 191 118 192 119 $selected_story = get_post_meta( $post->ID, 'story_id', true ); … … 195 122 return; 196 123 } 197 $stories = sh_get_stories(); 198 $profile = sh _get_profile();124 125 $profile = shorthand_api_get_profile(); 199 126 200 127 if ( ! ( $profile ) ) { 201 echo 'Could not connect to Shorthand, please check your API token in <a href="options-general.php?page=shorthand-options">Shorthand settings</a>.'; 202 } elseif ( $stories === null ) { 203 echo 'You currently have no stories ready for publishing on Shorthand. Please check that your story is set to be ready for publishing.'; 128 $uri = Shorthand_Admin::get_page_url(); 129 printf( wp_kses( __( 'Could not connect to Shorthand, please check your API token in <a alt="(opens Shorthand Connect plugin settings)" href="%s">Shorthand settings</a>.' ) ), esc_url( $uri ) ); 204 130 } else { 205 echo '<ul class="stories">'; 206 foreach ( $stories as $story ) { 207 $selected = ''; 208 $story_selected = ''; 209 if ( $selected_story === $story->id ) { 210 $selected = 'checked'; 211 $story_selected = 'selected'; 212 } 213 $archived = ''; 214 if ( isset( $story->story_version ) && '1' === $story->story_version ) { 215 if ( $show_archived_stories ) { 216 $archived = ' (archived)'; 217 } else { 218 continue; 219 } 220 } 221 echo '<li class="story ' . esc_attr( $story_selected ) . '"><label><input name="story_id" type="radio" value="' . esc_attr( $story->id ) . '" ' . esc_html( $selected ) . ' /><img width="150" src="' . esc_url( $baseurl . $story->image ) . '" /><span class="title">' . esc_html( $story->title . $archived ) . '</span><span class="desc">' . esc_html( $story->metadata->description ) . '</span></a></label></li>'; 222 } 223 echo '</ul><div class="clear"></div>'; 131 ?> 132 <div id="stories-list"> 133 <div class="filter-container wp-core-ui"> 134 <input class="search" placeholder="Search for a story" /> 135 <span class="sort button-secondary desc" data-sort="updated_value"> 136 Edited<span class="sort-icon"></span> 137 </span> 138 </div> 139 <!-- List to populate the stories. --> 140 <ul class="list stories"> 141 142 </ul> 143 </div> 144 <?php 145 wp_register_script( 146 'list-js', 147 plugin_dir_url( __FILE__ ) . 'js/list.js/v2.3.4/list.min.js', 148 array(), 149 '2.3.4', 150 array() 151 ); 152 wp_enqueue_script( 'list-js' ); 153 154 wp_register_script( 155 'list-js-stories', 156 plugin_dir_url( __FILE__ ) . 'js/connect-stories-list.js', 157 array(), 158 '1.0.0', 159 array( 160 'strategy' => 'defer', 161 ) 162 ); 163 wp_enqueue_script( 'list-js-stories' ); 164 165 wp_register_script( 166 'list-js-stories-selected', 167 plugin_dir_url( __FILE__ ) . 'js/connect-stories-list-selected.js', 168 array(), 169 '1.0.0', 170 array( 171 'strategy' => 'defer', 172 ) 173 ); 174 wp_enqueue_script( 'list-js-stories-selected' ); 175 wp_register_script( 176 'fetch-stories', 177 plugin_dir_url( __FILE__ ) . 'js/connect-stories-fetch.js', 178 array(), 179 '1.0.0', 180 array( 181 'strategy' => 'defer', 182 ) 183 ); 184 wp_localize_script('fetch-stories', 'wp_server', array( 185 'url' => ( get_option('permalink_structure') ) ? "/wp-json/shorthand_connect/v1/stories/" : "/?rest_route=/shorthand_connect/v1/stories/", 186 'nonce' => wp_create_nonce('wp_rest'), 187 'selected_story' => $selected_story 188 )); 189 wp_enqueue_script( 'fetch-stories' ); 190 echo '<div class="clear"></div>'; 224 191 } 225 192 226 193 // Noncename needed to verify where the data originated 227 echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' . 228 esc_attr( wp_create_nonce( plugin_basename( __FILE__ ) ) ) . '" />'; 229 194 echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' . esc_attr( wp_create_nonce( plugin_basename( __FILE__ ) ) ) . '" />'; 195 } 196 197 function shorthand_wpt_shorthand_story_advanced() { 230 198 ?> 199 <div class="form-check form-switch text-light"> 200 <input class="form-check-input" type="checkbox" id="show-advanced"> 201 <label class="form-check-label" for="show-advanced">Show advanced options</label> 202 </div> 231 203 <script> 232 jQuery('li.story input:radio').click(function () { 233 jQuery('li.story').removeClass('selected'); 234 jQuery(this).parent().parent().addClass('selected'); 235 jQuery('label#title-prompt-text').text(''); 236 jQuery('input#title').val(jQuery(this).parent().find('span.title').text()); 237 if (jQuery('textarea#abstract').val() === '') { 238 jQuery('textarea#abstract').val(jQuery(this).parent().find('span.desc').text()); 239 } 240 }); 204 //var elements = document.querySelectorAll( 'body *' ); 205 //document.getElementById("postcustom").style.visibility = 0; 206 console.log(document.getElementById("postcustom")); 241 207 </script> 242 208 <?php … … 259 225 formaction="?shand_update" 260 226 /> 261 262 <script>263 jQuery('#post').submit(function () {264 jQuery('#shorthand_update').prop('disabled', true);265 });266 </script>267 268 227 </div> 269 228 270 229 <?php 230 231 wp_register_script( 232 'connect-form', 233 plugin_dir_url( __FILE__ ) . 'js/connect-form.js', 234 array(), 235 '1.0.0', 236 array( 237 'strategy' => 'defer', 238 ) 239 ); 240 wp_enqueue_script( 'connect-form' ); 271 241 } 272 242 … … 275 245 global $noabstract; 276 246 $selected_story = get_post_meta( $post->ID, 'story_id', true ); 247 277 248 if ( $selected_story ) { 278 249 add_meta_box( 279 'sh and_wpt_shorthand_story_update',250 'shorthand_wpt_shorthand_story_update', 280 251 'Update Shorthand Story', 281 'sh and_wpt_shorthand_story',252 'shorthand_wpt_shorthand_story', 282 253 'shorthand_story', 283 254 'side', … … 286 257 } else { 287 258 add_meta_box( 288 'sh and_wpt_shorthand_story',259 'shorthand_wpt_shorthand_story', 289 260 'Select Shorthand Story', 290 'sh and_wpt_shorthand_story',261 'shorthand_wpt_shorthand_story', 291 262 'shorthand_story', 292 263 'normal', 293 'default' 294 ); 295 } 264 'high' 265 ); 266 } 267 296 268 if ( ! $noabstract ) { 297 269 add_meta_box( … … 300 272 'shand_wpt_shorthand_abstract', 301 273 'shorthand_story', 302 'normal', 303 'default' 304 ); 305 } 306 add_meta_box( 'shand_wpt_shorthand_extra_html', 'Add additional HTML', 'shand_wpt_shorthand_extra_html', 'shorthand_story', 'normal', 'default' ); 274 'advanced' 275 ); 276 } 277 278 add_meta_box( 279 'shand_wpt_shorthand_extra_html', 280 'Add additional HTML', 281 'shand_wpt_shorthand_extra_html', 282 'shorthand_story', 283 'advanced' 284 ); 307 285 } 308 286 … … 323 301 324 302 /* Save the shorthand story */ 325 function shand_save_shorthand_story( $post_id, $post ) { 303 function shorthand_save_shorthand_story( $post_id, $post ) { 304 $profile = shorthand_api_get_profile(); 305 if ( ( get_post_type( $post ) === 'shorthand_story' ) && ! ( $profile ) ) { 306 $uri = Shorthand_Admin::get_page_url(); 307 wp_die( message: sprintf( wp_kses_post ( __( 'Could not connect to Shorthand, please check your API token in <a alt="(opens Shorthand Connect plugin settings)" href="%s">Shorthand settings</a>.', 'shorthand-connect' ) ), esc_url( $uri ) ), title: wp_kses_post( __( 'Shorthand is not connected' ) ) ); 308 } 309 326 310 WP_Filesystem(); 327 311 global $wp_filesystem; … … 363 347 // Sanitize but also check if the query is GET or POST. 364 348 if ( isset( $_REQUEST['story_id'] ) ) { 365 $story_id = filter_input( INPUT_GET, 'story_id', FILTER_SANITIZE_STRING ); 366 // If the variable is not present in the $_GET array. 367 if ( null === $story_id ) { 368 $story_id = filter_input( INPUT_POST, 'story_id', FILTER_SANITIZE_STRING ); 369 } 349 $story_id = sanitize_text_field( $_REQUEST['story_id'] ); 370 350 $safe_story_id = preg_replace( '/\W|_/', '', $story_id ); 371 351 } … … 429 409 if ( ! $noabstract ) { 430 410 $abstract = $body; 431 remove_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );411 remove_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 432 412 $post = array( 433 413 'ID' => $post_id, 434 'post_content' => sh and_abstract_template( $post_id, wp_kses_post( $_REQUEST['abstract'] ), $abstract ),414 'post_content' => shorthand_abstract_template( $post_id, wp_kses_post( $_REQUEST['abstract'] ), $abstract ), 435 415 ); 436 416 wp_update_post( $post ); 437 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );417 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 438 418 } else { 439 remove_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );419 remove_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 440 420 $post = array( 441 421 'ID' => $post_id, … … 443 423 ); 444 424 wp_update_post( $post ); 445 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );425 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 446 426 } 447 427 … … 461 441 } 462 442 463 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );443 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 464 444 465 445 /* Load Shorthand Template Hook */ … … 467 447 global $post; 468 448 if ( 'shorthand_story' === $post->post_type ) { 469 $path = locate_template( array( 'single-shorthand_story.php', 'templates/single-shorthand_story.php', 'template-parts/single-shorthand_story.php' ) ); 449 $path = locate_template( 450 array( 451 'single-shorthand_story.php', 452 'templates/single-shorthand_story.php', 453 'template-parts/single-shorthand_story.php', 454 'single-shorthand-story.php', 455 'templates/single-shorthand-story.php', 456 'template-parts/single-shorthand-story.php', 457 ) 458 ); 470 459 if ( $path ) { 471 460 return $path; 472 461 } 473 462 $plugin_path = plugin_dir_path( __FILE__ ); 474 $template_name = 'templates/single-shorthand _story.php';463 $template_name = 'templates/single-shorthand-story.php'; 475 464 if ( ( get_stylesheet_directory() . '/' . $template_name === $template ) 476 465 || ! file_exists( $plugin_path . $template_name ) … … 491 480 if ( is_single() && 'shorthand_story' === get_post_type() ) { 492 481 $meta = get_post_meta( get_post()->ID ); 493 echo get_shorthandinfo( $meta, 'story_head' );482 echo ( get_shorthandinfo( $meta, 'story_head' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 494 483 } 495 484 } … … 506 495 if ( $query->is_main_query() && ! is_admin() ) { 507 496 $queried_object = get_queried_object(); 508 $shorthand_templates = array( 'single-shorthand_story.php', 'templates/single-shorthand_story.php', 'template-parts/single-shorthand_story.php' ); 497 $shorthand_templates = array( 498 'single-shorthand_story.php', 499 'templates/single-shorthand_story.php', 500 'template-parts/single-shorthand_story.php', 501 'single-shorthand-story.php', 502 'templates/single-shorthand-story.php', 503 'template-parts/single-shorthand-story.php', 504 ); 509 505 510 506 // Check if the queried object uses a Shorthand Post template from the array. … … 555 551 * Activates plugin by creating post type. 556 552 */ 557 function shand_shorthand_activate() { 553 function shorthand_shorthand_activate() { 554 558 555 shand_create_post_type(); 559 flush_rewrite_rules(); 560 } 561 562 register_activation_hook( __FILE__, 'shand_shorthand_activate' ); 556 flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules 557 558 // Set config values. 559 update_option( 'sh_v2_token', '' ); 560 update_option( 'sh_permalink', 'shorthand_story' ); 561 $css_path = '/css/options-default.css'; 562 $sh_css = file_get_contents( __DIR__. $css_path ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown 563 update_option( 'sh_css', $sh_css ); 564 update_option( 'sh_regex_list', '' ); 565 update_option( 'sh_media_cron_offload', true ); 566 update_option( 'sh_disable_acf', false ); 567 } 568 569 register_activation_hook( __FILE__, 'shorthand_shorthand_activate' ); 563 570 register_deactivation_hook( __FILE__, 'flush_rewrite_rules' ); 564 571 -
shorthand-connect/tags/1.3.32/templates/abstract.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Shorthand abstract template. 4 * 5 * @package Shorthand Connect 6 */ 2 7 3 function shand_abstract_template( $post_id, $abstract_html, $data ) { 4 $abstract_html = '<p>' . $abstract_html . '</p>'; 5 6 $abstract_html .= '<a href="' . get_permalink( $post_id ) . '">View the story</a>'; 7 8 $abstract_html .= '<div style="display:none;">' . $data . '</div>'; 9 return $abstract_html; 8 /** 9 * Generates a shorthand abstract template for a post. 10 * 11 * Creates a basic abstract template containing the provided abstract HTML, 12 a link to the post, and hidden data. 13 * 14 * @param int $post_id The ID of the post. 15 * @param string $abstract_html The HTML content for the abstract. 16 * @param string $data Additional data to be included in a hidden div. 17 * @return string The generated abstract HTML. 18 */ 19 function shorthand_abstract_template( $post_id, $abstract_html, $data ) { 20 $title = __( 'View the story' ); 21 $abstract = array( 22 '<p>' . $abstract_html . '</p>', 23 '<a href="' . get_permalink( $post_id ) . '">' . $title . '</a>', 24 '<div style="display:none;">' . $data . '</div>', 25 ); 26 return implode( $abstract ); 10 27 } -
shorthand-connect/tags/1.3.32/trunk/includes/api.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Shorthand API functions. 4 * 5 * @package Shorthand Connect 6 */ 2 7 3 8 /* … … 11 16 * @param array $options An array of extra options args to pass to wp_remote_request 12 17 */ 13 function sh _v2_api_request( $url, $options ) {18 function shorthand_api_v2_request( $url, $options ) { 14 19 $token = get_option( 'sh_v2_token' ); 15 20 if ( ! $token ) { … … 44 49 } 45 50 46 function sh_v2_api_request_json( $url, $options ) { 47 $response = sh_v2_api_request( $url, $options ); 51 /** 52 * Makes a JSON API request to the shorthand API. 53 * 54 * @param string $url The URL of the API endpoint. 55 * @param array $options Optional arguments for the API request. 56 * @return mixed The decoded JSON response, or null if an error occurs. 57 */ 58 function shorthand_api_request_json( $url, $options ) { 59 $response = shorthand_api_v2_request( $url, $options ); 48 60 $body = wp_remote_retrieve_body( $response ); 49 61 return json_decode( $body ); 50 62 } 51 63 52 function sh_get_profile() { 64 /** 65 * Retrieves user profile information from the shorthand API. 66 * 67 * @return object User profile information, including username, gravatar, and other potential data. 68 */ 69 function shorthand_api_get_profile() { 53 70 $tokeninfo = array(); 54 71 55 $data = sh _v2_api_request_json( '/v2/token-info', array() );72 $data = shorthand_api_request_json( '/v2/token-info', array() ); 56 73 if ( $data && isset( $data->organisation_id ) ) { 57 74 $tokeninfo['username'] = $data->name . ' (' . $data->token_type . ' Token)'; … … 63 80 } 64 81 65 function sh_get_stories() { 82 /** 83 * Retrieves stories from the shorthand API. 84 * 85 * Fetches a list of stories from the shorthand API, optionally filtered by keyword. 86 * 87 * @param string $keyword Optional keyword to filter stories by. 88 * @return array|null An array of story data, or null if an error occurs or no stories are found. 89 */ 90 function shorthand_api_get_stories( string $keyword = '', string $cursor = '', string $limit = '50' ) { 66 91 $stories = null; 67 68 $data = sh_v2_api_request_json( '/v2/stories', array( 'timeout' => '240' ) ); 92 $url = '/v2/stories'; 93 $url .= '?limit='.$limit; 94 if ( $cursor && $cursor != '') { 95 $url .= '&cursor=' . $cursor; 96 } 97 if ( $keyword && $keyword != '' ) { 98 $url .= '&keyword=' . $keyword; 99 } 100 101 102 $data = shorthand_api_request_json( $url, array( 'timeout' => '240' ) ); 69 103 if ( $data ) { 70 104 $stories = array(); 71 // Something went wrong 105 // Something went wrong. 72 106 if ( isset( $data->status ) && $data->status ) { 73 107 return null; 74 108 } 109 75 110 foreach ( $data as $storydata ) { 76 $story = array( 77 'image' => $storydata->signedCover, 78 'id' => $storydata->id, 79 'metadata' => (object) array( 80 'description' => $storydata->description, 81 ), 82 'title' => $storydata->title, 83 'story_version' => '' . $storydata->version, 111 $updated_timestamp = strtotime( esc_html( $storydata->updatedAt ) ); 112 $updated_at = $storydata->updatedAt; 113 $published_timestamp = strtotime( esc_html( $storydata->lastPublishedAt ) ); 114 $updated = human_time_diff( $updated_timestamp, current_time( 'timestamp' ) ); 115 $published = human_time_diff( $published_timestamp, current_time( 'timestamp' ) ); 116 $stories[] = array( 117 'version_value' => '' . $storydata->version, 118 'title' => $storydata->title, 119 'description' => $storydata->description, 120 'imagealt' => $storydata->title, 121 'image' => $storydata->signedCover, 122 'updated_timestamp' => $updated_timestamp, 123 'updated_at' => $updated_at, 124 'updated_value' => $updated, 125 'published_timestamp' => $published_timestamp, 126 'published_value' => $published, 127 'story_id' => $storydata->id, 128 'class' => 'story', 84 129 ); 85 $stories[] = (object) $story;86 130 } 87 131 } … … 90 134 } 91 135 136 /** 137 * Gets the path to the story directory. 138 * 139 * Determines the path to the directory where story files for a specific post 140 * and story ID should be stored. 141 * 142 * @param int $post_id The ID of the post. 143 * @param string $story_id The ID of the story. 144 * @return string|null The path to the story directory, or null if the directory doesn't exist or an error occurs. 145 */ 92 146 function sh_get_story_path( $post_id, $story_id ) { 93 147 init_wp_filesystem(); … … 95 149 $destination_path = $destination['path'] . '/shorthand/' . $post_id . '/' . $story_id; 96 150 97 // on WP VIP, folders in the uploads dir always exist151 // On WP VIP, folders in the uploads dir always exist. 98 152 if ( ! file_exists( $destination_path ) ) { 99 153 $destination_path = null; … … 105 159 } 106 160 161 /** 162 * Gets the URL of the story directory. 163 * 164 * Determines the URL of the directory where story files for a specific post 165 * and story ID are located. 166 * 167 * @param int $post_id The ID of the post. 168 * @param string $story_id The ID of the story. 169 * @return string The URL of the story directory. 170 */ 107 171 function shorthand_get_story_url( $post_id, $story_id ) { 108 172 init_wp_filesystem(); … … 123 187 $story = array(); 124 188 125 // Attempt to connect to the server 126 $zip_file = wp_tempnam( 'sh_zip', $tmpdir );127 $response = sh_v2_api_request(189 // Attempt to connect to the server. 190 $zip_file = wp_tempnam( 'sh_zip', $tmpdir ); 191 $response = shorthand_api_v2_request( 128 192 '/v2/stories/' . $story_id . ( $without_assets ? '?without_assets=true' : '' ) . ( $assets_only ? '?assets_only=true' : '' ), 129 193 array( … … 145 209 ); 146 210 } else { 147 $story = extract StoryContent( $zip_file, $destination_path, $story_id );211 $story = extract_story_content( $zip_file, $destination_path, $story_id ); 148 212 } 149 213 … … 153 217 } 154 218 155 219 /** 220 * Initializes the WordPress filesystem. 221 * 222 * Ensures that the WordPress filesystem is available for file operations. 223 * If not, it requests filesystem credentials and re-initializes the filesystem. 224 */ 156 225 function init_wp_filesystem() { 157 226 WP_Filesystem(); … … 163 232 } 164 233 165 function extractStoryContent( $zip_file, $destination_path, $story_id ) { 234 /** 235 * Extracts story content from a ZIP file. 236 * 237 * Extracts the 'head.html' and 'article.html' files from a given ZIP file 238 * into a specified destination path. 239 * 240 * @param string $zip_file The path to the ZIP file. 241 * @param string $destination_path The path to the extraction destination. 242 * @param string $story_id The ID of the story. 243 * @return array An array containing extracted content, path, or error information. 244 */ 245 function extract_story_content( $zip_file, $destination_path, $story_id ) { 166 246 // WP VIP HOSTING COMPATIBILITY 167 247 $zip = new ZipArchive(); -
shorthand-connect/tags/1.3.32/trunk/includes/mass-pull.php
r3095659 r3258349 1 1 <?php 2 /* 3 * Sets each custom meta field, should be paired with sh_copy_story().2 /** 3 * Bulk story pull functions. 4 4 * 5 * @package Shorthand Connect 6 */ 7 8 /** 9 * Updates a story for a given post. 10 * 11 * Fetches story data from the shorthand API, copies story files, updates post 12 * metadata, and performs post-processing on the story content. 5 13 * Note: Unzipping a fresh story copy won't update the fields. 14 * 15 * @param int $post_id The ID of the post. 16 * @param string $story_id The ID of the story. 6 17 */ 7 18 function shand_update_story( $post_id, $story_id ) { … … 14 25 15 26 // Grab JSON for Story & Set into object $obj. 16 $obj = sh _v2_api_request_json( '/v2/stories/' . $story_id . '/settings', array( 'timeout' => '240' ) );27 $obj = shorthand_api_request_json( '/v2/stories/' . $story_id . '/settings', array( 'timeout' => '240' ) ); 17 28 18 29 $err = sh_copy_story( $post_id, $safe_story_id, $sh_media_cron_offload ); -
shorthand-connect/tags/1.3.32/trunk/includes/shorthand-options.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Admin settings for the first time dialog. 4 * 5 * @package Shorthand Connect 6 */ 7 2 8 /* Options */ 3 function shand_shorthand_menu() { 4 add_options_page( 'Shorthand Options', 'Shorthand', 'manage_options', 'shorthand-options', 'shand_shorthand_options' ); 5 } 6 $default_sh_site_css = ' 7 /* START CSS FOR DEFAULT WP THEMES */ 8 .site { 9 margin: 0; 10 max-width: none; 11 } 12 .site-content { 13 padding: 0 !important; 14 } 15 .site-inner { 16 max-width: none; 17 } 18 .site-header { 19 max-width: none; 20 z-index: 100; 21 } 22 .site:before { 23 width: 0; 24 } 25 /* END CSS FOR DEFAULT WP THEMES */ 26 '; 27 28 // JSON Checker 29 function validate_json( $json_string ) { 30 // Try to decode the JSON data. If it fails, the JSON is invalid. 31 $json_data = json_decode( $json_string, true ); 32 33 if ( json_last_error() !== JSON_ERROR_NONE ) { 34 // The JSON is invalid. 35 return false; 36 } 37 38 // Return the original JSON string if it's valid. 39 return $json_string; 40 } 41 42 function shand_shorthand_options() { 43 global $default_sh_site_css; 44 global $server_url; 45 46 // Rather than running a rewrite flush everytime a post is submitted, run it on plugin activate/deactivate 47 function shand_rewrite_flush() { 48 shand_create_post_type(); 49 flush_rewrite_rules(); 50 } 51 register_activation_hook( __FILE__, 'shand_rewrite_flush' ); 52 register_deactivation_hook( __FILE__, 'flush_rewrite_rules' ); 9 10 // Redirect to the first time setup. 11 function shorthand_redirect_admin_config() { 12 $profile = shorthand_api_get_profile(); 13 if ( isset( $_GET['page'] ) && ( 'shorthand-options' === $_GET['page'] ) && ( ! $profile ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 14 $admin_url = Shorthand_Admin::get_page_url( 'init' ); 15 wp_redirect( $admin_url ); 16 die(); 17 } 18 } 19 add_action( 'admin_menu', 'shorthand_redirect_admin_config' ); 20 21 function shorthand_shorthand_options() { 22 // Menu links. 23 $menu_links = array( 24 'token' => 'API Key', 25 'permalink' => 'Permalinks', 26 'css' => 'Custom CSS', 27 'processing' => 'Post-processing', 28 'experimental' => 'Experimental Features', 29 ); 30 31 // If current = all, then display all. 32 $current = isset( $_GET['navigation'] ) ? sanitize_key( $_GET['navigation'] ) : array_keys( $menu_links )[0]; 33 $profile = shorthand_api_get_profile(); 34 $messages = array(); 53 35 54 36 if ( ! current_user_can( 'manage_options' ) ) { 55 37 wp_die( esc_html( __( 'You do not have sufficient permissions to access this page.' ) ) ); 56 38 } 39 57 40 if ( isset( $_POST['sh_submit_hidden'] ) && 'Y' === $_POST['sh_submit_hidden'] && check_admin_referer( 'sh-update-configuration' ) ) { 58 41 // If there's a token set, use it, if not set it to an empty string 59 42 $sh_v2_token = isset( $_POST['sh_v2_token'] ) ? sanitize_text_field( $_POST['sh_v2_token'] ) : ''; 60 43 update_option( 'sh_v2_token', $sh_v2_token ); 44 45 $profile = shorthand_api_get_profile(); 46 if ( $profile ) { 47 $messages['updated'] = '<p>' . SHORTHAND_CONFIG_STEP1_SUCCESS . '</p><p><strong>Username</strong>: ' . esc_html( $profile->username ) . '</p>'; 48 } else { 49 $messages['notice-error'] = SHORTHAND_CONFIG_STEP1_ERROR; 50 } 61 51 } 62 52 … … 64 54 65 55 if ( isset( $_POST['sh_submit_hidden_two'] ) && 'Y' === $_POST['sh_submit_hidden_two'] && check_admin_referer( 'sh-update-configuration' ) ) { 66 // Check if there's custom CSS, if there is, use wp_kses_post() to sanitize otherwise set an empty string 56 // Check if there's custom CSS, if there is, use wp_kses_post() 57 // to sanitize otherwise set an empty string. 67 58 $sh_css = isset( $_POST['sh_css'] ) ? wp_kses_post( $_POST['sh_css'] ) : ''; 68 59 update_option( 'sh_css', $sh_css ); 60 $messages['updated'] = SHORTHAND_CONFIG_STEP3_SUCCESS; 69 61 } 70 62 71 63 if ( isset( $_POST['sh_submit_hidden_three'] ) && 'Y' === $_POST['sh_submit_hidden_three'] && check_admin_referer( 'sh-update-configuration' ) ) { 72 // Check if there's custom permalink, if there is, use sanitize_text_field() to sanitize potential HTML and then set an empty string 64 // Check if there's custom permalink, if there is, use sanitize_text_field() 65 // to sanitize potential HTML and then set an empty string. 73 66 $sh_permalink = isset( $_POST['sh_permalink'] ) ? sanitize_text_field( $_POST['sh_permalink'] ) : ''; 74 67 update_option( 'sh_permalink', $sh_permalink ); 75 shand_rewrite_flush(); 68 shorthand_rewrite_flush(); 69 $messages['updated'] = SHORTHAND_CONFIG_STEP2_SUCCESS; 76 70 } 77 71 $permalink_structure = esc_html( get_option( 'sh_permalink' ) ); … … 82 76 } 83 77 $sh_css = get_option( 'sh_css' ); 84 $no_css = false; 85 if ( '' === $sh_css ) { 86 $no_css = true; 87 if ( isset( $default_site_css ) ) { 88 update_option( 'sh_css', $default_site_css ); 89 } 90 $sh_css = $default_sh_site_css; 91 } 92 93 if ( isset( $_POST['sh_submit_hidden_four'] ) && 'Y' === $_POST['sh_submit_hidden_four'] && check_admin_referer( 'sh-update-configuration' ) ) { 94 $sh_regex_list = isset( $_POST['sh_regex_list'] ) ? wp_unslash( $_POST['sh_regex_list'] ) : ''; 95 78 79 if ( isset( $_POST['sh_submit_hidden_four'] ) && 80 ( 'Y' === $_POST['sh_submit_hidden_four'] ) && 81 check_admin_referer( 'sh-update-configuration' ) 82 ) { 83 // sh_regex_list may contain <tags> for lookup and processing on import and so may need to include <script> etc; however it is only ever displayed within a text-area value and manually processed. 84 $sh_regex_list = empty( $_POST['sh_regex_list'] ) ? '' : wp_unslash( $_POST['sh_regex_list'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 85 86 $messages['updated'] = SHORTHAND_CONFIG_STEP4_SUCCESS; 96 87 if ( empty( $sh_regex_list ) ) { 97 // Update the option with an empty value if the input is empty 88 // Update the option with an empty value if the input is empty. 98 89 update_option( 'sh_regex_list', '' ); 99 90 } else { 100 91 // Validate if it's a valid JSON without sanitizing 101 $sh_regex_list = validate_json( $sh_regex_list );92 $sh_regex_list = Shorthand_Admin::validate_json( $sh_regex_list ); 102 93 103 94 if ( false !== $sh_regex_list ) { … … 106 97 } else { 107 98 // Handle invalid JSON error here. 99 unset( $messages['updated'] ); 100 $messages['notice-error'] = SHORTHAND_CONFIG_STEP4_ERROR; 108 101 } 109 102 } … … 112 105 $sh_regex_list = base64_decode( get_option( 'sh_regex_list' ) ); 113 106 114 // Experimental Settings107 // Experimental settings. 115 108 if ( isset( $_POST['sh_submit_hidden_experimental'] ) && 'Y' === $_POST['sh_submit_hidden_experimental'] && check_admin_referer( 'sh-update-configuration' ) ) { 116 109 $sh_media_cron_offload = isset( $_POST['sh_media_cron_offload'] ) ? filter_var( $_POST['sh_media_cron_offload'], FILTER_VALIDATE_BOOLEAN ) : false; … … 118 111 update_option( 'sh_media_cron_offload', $sh_media_cron_offload ); 119 112 update_option( 'sh_disable_acf', $sh_disable_acf ); 113 $messages['updated'] = SHORTHAND_CONFIG_STEP5_SUCCESS; 120 114 } 121 115 $sh_media_cron_offload = filter_var( get_option( 'sh_media_cron_offload' ), FILTER_VALIDATE_BOOLEAN ); 122 116 $sh_disable_acf = filter_var( get_option( 'sh_disable_acf' ), FILTER_VALIDATE_BOOLEAN ); 123 117 124 $profile = sh_get_profile(); 125 ?> 126 <div class="container"> 127 <div class="py-1"> 128 <h1>Shorthand API Configuration</h1> 129 <h2>Shorthand Connect Status</h2> 130 <form name="formtoken" method="post"> 131 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 132 <input type="hidden" name="sh_submit_hidden" value="Y" /> 133 <table class="form-table"><tbody> 134 <tr class="v2row"> 135 <th scope="row"><label for="sh_v2_token"><?php esc_html_e( 'Shorthand Team Token', 'sh-v2-token' ); ?></label></th> 136 <td><input type="text" id="sh_v2_token" name="sh_v2_token" value="<?php echo esc_attr( $v2_token ); ?>" size="28"></td> 137 </tr> 138 </tbody></table> 139 <?php if ( $profile ) { ?> 140 <p class="status">Successfully connected</p> 141 <p><strong>Username</strong>: <?php echo esc_html( $profile->username ); ?></p> 142 <?php } else { ?> 143 <p class="status warn">Not Connected</p> 144 <?php } ?> 145 <div style='clear:both'></div> 146 <p class="submit"> 147 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 118 ?> 119 <div class="wrap shorthand-options-wrapper"> 120 <h1>Settings</h1> 121 122 <hr /> 123 <div class="shorthand-menu"> 124 <ol role="list"> 125 <?php foreach ( $menu_links as $menu_key => $menu_name ) { ?> 126 <li class="py-1"> 127 <form name="menu_settings_<?php echo esc_attr( $menu_key ); ?>" method="post" action="<?php echo esc_url( Shorthand_Admin::get_page_url( 'config', esc_attr( $menu_key ) ) ); ?>"> 128 <input type="submit" name="Submit" class="button<?php echo ( in_array( $current, array( $menu_key, 'all' ) ) ) ? ' button button-primary' : ''; ?>" value="<?php esc_attr_e( $menu_name ); ?>" /> 129 </form> 130 </li> 131 <?php } ?> 132 </ol> 133 </div> 134 135 <div class="shorthand-form-wrapper"> 136 <form name="form_settings" method="post" action="<?php echo esc_url( Shorthand_Admin::get_page_url( 'config', esc_attr( $current ) ) ); ?>"> 137 138 <?php if ( ! empty( $messages ) ) : ?> 139 <?php foreach ( $messages as $class => $message ) : ?> 140 <div class="notice <?php echo esc_html ( $class ); ?>"><?php echo wp_kses( $message, array( 141 'p' => array(), 142 'strong' => array(), 143 ) ); ?></div> 144 <?php endforeach; ?> 145 <?php endif; ?> 146 147 <?php if ( in_array( $current, array( array_keys( $menu_links )[0], 'all' ) ) ) : ?> 148 <div class="py-1"> 149 <h2>Shorthand API Key</h2> 150 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 151 <input type="hidden" name="sh_submit_hidden" value="Y"/> 152 <p><label for="sh_v2_token"><?php esc_html_e( 'Your API key provided by Shorthand', 'shorthand-connect' ); ?></label></p> 153 <input type="text" id="sh_v2_token" name="sh_v2_token" value="<?php echo esc_attr( $v2_token ); ?>"> 154 <p> 155 <?php esc_html_e( 'Do not have API key?', 'shorthand-connect' ); ?> <a target="_blank" alt="(<?php esc_html_e( 'opens Shorthand Connect plugin settings', 'shorthand-connect' ); ?>)" href="https://support.shorthand.com/en/articles/62-programmatic-publishing-with-the-shorthand-api"><?php esc_html_e( 'Get one here', 'shorthand-connect' ); ?></a> 148 156 </p> 149 </form> 150 </div> 151 152 153 <div class="py-1"> 154 <h2>Shorthand Permalink Structure</h2> 155 <p>Use this to set the permalink structure of Shorthand story URLs</p> 156 <form name="permalinks" method="post"> 157 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 158 <input type="hidden" name="sh_submit_hidden_three" value="Y" /> 159 <p> 160 <?php _e( 'Permalink structure:', 'sh-permalink-value' ); ?><br /><?php echo esc_url( get_site_url() ); ?>/<input type="text" name="sh_permalink" value="<?php echo esc_attr( $permalink_structure ); ?>" size="20">/{STORY_NAME} 161 </p> 162 <p class="submit"> 163 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 164 </p> 165 </form> 166 </div> 167 168 <div class="py-1"> 169 <h2>Shorthand Story Page CSS (theme wide CSS)</h2> 170 <p>Use this CSS to customise Shorthand Story pages to better suit your theme</p> 171 <?php if ( $no_css ) { ?> 172 <p class="status warn">No custom CSS found, using default theme CSS</p> 173 <?php } ?> 174 <form name="themecss" method="post"> 175 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 176 <input type="hidden" name="sh_submit_hidden_two" value="Y" /> 177 <textarea rows="10" cols="80" name="sh_css"><?php echo esc_textarea( $sh_css ); ?></textarea> 178 <p class="submit"> 179 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 180 </p> 181 </form> 182 </div> 183 184 <div class="py-1"> 185 <h2>Post-processing</h2> 186 <p>Use this to create a JSON object of regex queries and replacements.</p> 157 <div style='clear:both'></div> 158 </div> 159 <?php endif; ?> 160 161 <?php if ( in_array( $current, array( array_keys( $menu_links )[1], 'all' ) ) ) : ?> 162 <div class="py-1"> 163 <h2>Permalink Structure</h2> 164 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 165 <input type="hidden" name="sh_submit_hidden_three" value="Y"/> 166 <p> 167 <p><label for="sh_permalink"><?php esc_html_e( 'Set the permalink structure of Shorthand story URLs', 'shorthand-connect' ); ?></label></p> 168 <input type="text" name="sh_permalink" value="<?php echo esc_attr( $permalink_structure ); ?>" size="20"> 169 <p><?php echo esc_url( get_site_url() ); ?>/<strong><?php echo esc_html( $permalink_structure ); ?></strong>/{STORY_NAME}</p> 170 </div> 171 <?php endif; ?> 172 173 <?php if ( in_array( $current, array( array_keys( $menu_links )[2], 'all' ) ) ) : ?> 174 <div class="py-1"> 175 <h2>Custom CSS</h2> 176 <p>Use theme wide CSS to customise Shorthand Story pages to better suit your theme</p> 177 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 178 <input type="hidden" name="sh_submit_hidden_two" value="Y"/> 179 <textarea rows="10" cols="80" name="sh_css"><?php echo esc_textarea( $sh_css ); ?></textarea> 180 </div> 181 <?php endif; ?> 182 183 <?php if ( in_array( $current, array( array_keys( $menu_links )[3], 'all' ) ) ) : ?> 184 <div class="py-1"> 185 <h2>Post-processing</h2> 186 <p>Create a JSON object of regex queries and replacements.</p> 187 187 <p><em>This Example removes title tags from within the head tag by replacing it with nothing.</em></p> 188 <pre><code>188 <pre><code class="post-processing"> 189 189 { 190 190 "head": [ 191 191 { 192 "query": "/<title>(.*?)<\\/title>/",193 "replace": ""192 "query": "/<title>(.*?)<\\/title>/", 193 "replace": "" 194 194 } 195 195 ], 196 196 "body": [] 197 197 } 198 199 </code></pre> 200 <form name="postprocessing" method="post"> 201 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 202 <input type="hidden" name="sh_submit_hidden_four" value="Y" /> 203 <textarea rows="10" cols="80" id="sh_regex_list" name="sh_regex_list"><?php echo esc_textarea( $sh_regex_list ); ?></textarea> 204 <p class="submit"> 205 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 206 </p> 207 </form> 198 </code></pre> 199 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 200 <input type="hidden" name="sh_submit_hidden_four" value="Y"/> 201 <textarea rows="10" cols="80" id="sh_regex_list" 202 name="sh_regex_list"><?php echo esc_textarea( $sh_regex_list ); ?></textarea> 208 203 <script> 209 204 let textarea = document.querySelector("textarea#sh_regex_list"); 210 211 textarea.addEventListener("keyup", function(event) { 212 try { 213 JSON.parse(textarea.value); 205 206 textarea.addEventListener("keyup", function (event) { 207 try { 208 textarea.value = JSON.stringify(JSON.parse(textarea.value), undefined, 4); 209 textarea.setCustomValidity(""); 210 211 } catch (err) { 212 if (textarea.value != "") { 213 console.log("Invalid JSON"); 214 textarea.setCustomValidity("Invalid JSON in the Post-processing field"); 215 } else { 214 216 textarea.setCustomValidity(""); 215 216 } catch(err) {217 if(textarea.value != ""){218 console.log("Invalid JSON");219 textarea.setCustomValidity("Invalid JSON in the Post-processing field");220 } else {221 textarea.setCustomValidity("");222 }223 217 } 224 218 } 219 225 220 }); 226 221 </script> 227 </div> 228 229 <div class="py-1"> 230 <h2>Experimental Features</h2> 231 <p>Early access features that are still subject to change.</p> 232 <form name="form_experimental" method="post"> 233 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 222 </div> 223 <?php endif; ?> 224 225 <?php if ( in_array( $current, array( array_keys( $menu_links )[4], 'all' ) ) ) : ?> 226 <div class="py-1"> 227 <h2>Experimental Features <span class="badge badge-blue">Advanced</span></h2> 228 <p>Early access features that are still subject to change.</p> 229 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 234 230 <input type="hidden" name="sh_submit_hidden_experimental" value="Y"/> 235 <input type="checkbox" id="sh_media_cron_offload" name="sh_media_cron_offload" 236 value="true" <?php echo esc_attr( $sh_media_cron_offload ? 'checked' : '' ); ?> /> 237 <label for="sh_media_cron_offload">Import media assets via cron</label> 238 <p>Assets will be fetched after story save to prevent potential execution timeouts. Media won't be immediately 239 available on save but progress will be updated based on the `media_status` field.</p> 240 <p>It is advised that Shorthand Story Posts are saved as a draft first to trigger the cron job prior to public 241 publishing.</p> 231 232 <div class="checkbox-container"> 233 <input type="checkbox" id="sh_media_cron_offload" name="sh_media_cron_offload" <?php echo esc_attr( $sh_media_cron_offload ? 'checked' : '' ); ?> /> 234 <div class="bordered"> 235 <label for="sh_media_cron_offload"><strong>Import media assets via cron</strong> 236 <p>Assets will be fetched after story save to prevent potential execution timeouts. Media won't be immediately 237 available on save but progress will be updated based on the `media_status` field.</p> 238 <p>It is advised that Shorthand Story Posts are saved as a draft first to trigger the cron job prior to public 239 publishing.</p> 240 </label> 241 </div> 242 </div> 243 242 244 <br/> 245 <div class="checkbox-container"> 243 246 <input type="checkbox" id="sh_disable_acf" name="sh_disable_acf" 244 value="true" <?php echo esc_attr( $sh_disable_acf ? 'checked' : '' ); ?> />245 < label for="sh_disable_acf">Disable Advanced Custom Fields</label>246 <p>Used to prevent any potential issues that could cause the Shorthand Custom Fields to become hidden by Advanced247 Custom Fields.</p>247 value="true" <?php echo esc_attr( $sh_disable_acf ? 'checked' : '' ); ?> /> 248 <div class="bordered"><label for="sh_disable_acf"><strong>Disable Advanced Custom Fields</strong> 249 <p>Used to prevent any potential issues that could cause the Shorthand Custom Fields to become hidden by Advanced Custom Fields.</p></label></div> 250 </div> 248 251 </br> 252 </div> 253 <?php endif; ?> 254 255 <div class="py-1"> 256 <hr /> 249 257 <p class="submit"> 250 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>"/>258 <input type="submit" name="Submit" class="button button-primary" value="<?php esc_attr_e( 'Save changes' ); ?>"/> 251 259 </p> 260 </div> 252 261 </form> 253 </div> 254 </div> 255 </div> 256 <style> 257 .py-1 { 258 padding: 1em; 259 } 260 .bg-white { 261 background: white; 262 } 263 .container { 264 max-width: 980px; 265 } 266 img.grav { 267 float: left; 268 width:80px; 269 margin-right:10px; 270 } 271 p.status { 272 background:#dfd; 273 color:green; 274 font-weight:bold; 275 width:350px; 276 clear:left; 277 padding:5px; 278 } 279 p.status.warn { 280 background:#ffd; 281 color:orange; 282 } 283 .row-hidden { 284 display:none; 285 } 286 #wpfooter { 287 position: unset; 288 } 289 code { 290 font-family: monospace; 291 display: inherit; 292 } 293 </style> 294 262 263 </div> 264 </div> 265 </div> 295 266 296 267 <?php 297 268 } 298 269 299 add_action( 'admin_menu', 'shand_shorthand_menu' ); 300 301 ?> 270 function registerStyles() { 271 // Adding styles. 272 $css_path = '../css/options.css'; 273 wp_register_style( 'options_style', plugin_dir_url( __FILE__ ) . $css_path, array(), '1.3', 'all' ); 274 wp_enqueue_style( 'options_style' ); 275 } 276 277 add_action( 'init', 'registerStyles' ); 278 -
shorthand-connect/tags/1.3.32/trunk/index.php
r2898299 r3258349 1 <?php // Silence is golden 1 <?php 2 // Silence is golden. -
shorthand-connect/tags/1.3.32/trunk/shorthand-connect.php
r3095659 r3258349 1 1 <?php 2 2 /** 3 * Main plugin file. 4 * 3 5 * @package Shorthand Connect 4 * @version 1.3.315 6 */ 6 7 … … 10 11 Description: Import your Shorthand stories into your WordPress CMS as simply as possible - magic! 11 12 Author: Shorthand 12 Version: 1.3.3 113 Version: 1.3.32 13 14 Author URI: http://shorthand.com 14 15 */ 15 16 16 if ( file_exists( plugin_dir_path( __FILE__ ) . 'config.php' ) ) { 17 include_once plugin_dir_path( __FILE__ ) . 'config.php'; 17 // Make sure we don't expose any info if called directly. 18 if ( ! function_exists( 'add_action' ) ) { 19 echo 'Hi there! I\'m just a plugin, not much I can do when called directly.'; 20 exit; 21 } 22 23 define( 'SHORTHAND_VERSION', '1.3.32' ); 24 define( 'SHORTHAND__MINIMUM_WP_VERSION', '5.8' ); 25 define( 'SHORTHAND__PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 26 27 require_once SHORTHAND__PLUGIN_DIR . 'class-shorthand.php'; 28 29 // Add config. 30 if ( file_exists( SHORTHAND__PLUGIN_DIR . 'config.php' ) ) { 31 include_once SHORTHAND__PLUGIN_DIR . 'config.php'; 18 32 } else { 19 include_once plugin_dir_path( __FILE__ ) . 'config.default.php'; 20 } 21 require_once plugin_dir_path( __FILE__ ) . 'includes/api.php'; 22 require_once plugin_dir_path( __FILE__ ) . 'includes/mass-pull.php'; 23 24 require_once plugin_dir_path( __FILE__ ) . 'includes/shorthand-options.php'; 25 require_once plugin_dir_path( __FILE__ ) . 'templates/abstract.php'; 33 include_once SHORTHAND__PLUGIN_DIR . 'config-default.php'; 34 } 35 36 require_once SHORTHAND__PLUGIN_DIR . 'includes/api.php'; 37 require_once SHORTHAND__PLUGIN_DIR . 'includes/wp-api.php'; 38 require_once SHORTHAND__PLUGIN_DIR . 'includes/mass-pull.php'; 39 40 if ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) { 41 require_once SHORTHAND__PLUGIN_DIR . 'class-shorthand-admin.php'; 42 add_action( 'init', array( 'Shorthand_Admin', 'init' ) ); 43 } 44 45 // Loading initial setup or general configuration. 46 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options-variables.php'; 47 if ( isset( $_GET['view'] ) && ( $_GET['view'] === 'start' )) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 48 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options-init.php'; 49 } else { 50 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options.php'; 51 } 52 53 // Added admin menu. 54 function shorthand_shorthand_menu() { 55 add_options_page( 'Shorthand Options', 'Shorthand', 'manage_options', 'shorthand-options', 'shorthand_shorthand_options' ); 56 } 57 add_action( 'admin_menu', 'shorthand_shorthand_menu' ); 58 59 require_once SHORTHAND__PLUGIN_DIR . 'templates/abstract.php'; 26 60 27 61 if ( ! function_exists( 'WP_Filesystem' ) ) { … … 73 107 add_action( 'init', 'shand_create_post_type' ); 74 108 75 function sh and_wpt_shorthand_story() {109 function shorthand_wpt_shorthand_story() { 76 110 global $post; 77 global $server_url;78 111 global $show_archived_stories; 79 112 $baseurl = ''; 80 113 81 ?> 82 <style> 83 li.story { 84 float: left; 85 width: 160px; 86 margin: 5px; 87 } 88 89 li.story.selected label { 90 background: #5b9dd9; 91 color: #eee; 92 } 93 94 li.story input { 95 display: none !important; 96 } 97 98 li.story label { 99 display: block; 100 background: #fafafa; 101 text-align: center; 102 height: 160px; 103 padding-top: 5px; 104 border: 1px solid #eeeeee; 105 } 106 107 li.story label:hover { 108 border: 1px solid #5b9dd9; 109 } 110 111 li.story label span { 112 display: block; 113 font-weight: bold; 114 } 115 116 li.story label span.desc { 117 display: none; 118 } 119 120 div.clear { 121 clear: left; 122 } 123 124 div.publishing-actions { 125 padding: 10px; 126 clear: both; 127 border-top: 1px solid #dcdcde; 128 background: #f6f7f7; 129 margin: -12px; 130 margin-top: -12px; 131 margin-top: 10px; 132 display: flex; 133 justify-content: center; 134 } 135 136 .button-shorthand { 137 background-color: #000; 138 border: 1px solid #000; 139 transition: background-color .15s ease, color .15s ease; 140 color: #fff; 141 font-family: poppins, sans-serif; 142 font-size: 13px; 143 font-weight: 600; 144 letter-spacing: 0; 145 line-height: 1; 146 padding: 1em 2em; 147 text-decoration: none; 148 cursor: pointer; 149 border-radius: .9em; 150 } 151 152 .button-shorthand:hover { 153 background-color: #fff; 154 border-color: #000; 155 color: #000; 156 } 157 158 .button-shorthand:disabled { 159 pointer-events: none; 160 } 161 162 #codearea { 163 border: 1px solid #999999; 164 font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace; 165 width: 100%; 166 height: 300px; 167 } 168 169 #abstract { 170 border: 1px solid #999999; 171 width: 100%; 172 height: 200px; 173 } 174 175 ul.stories { 176 max-height: 400px; 177 overflow-y: scroll; 178 } 179 180 ul.stories img { 181 object-fit: cover; 182 height: 110px; 183 } 184 185 p.warning { 186 color: red; 187 font-weight: bold; 188 } 189 </style> 190 <?php 114 // Adding styles. 115 $css_path = 'css/connect.css'; 116 wp_register_style( 'connect_style', plugin_dir_url( __FILE__ ) . $css_path, array(), '1.3', 'all' ); 117 wp_enqueue_style( 'connect_style' ); 191 118 192 119 $selected_story = get_post_meta( $post->ID, 'story_id', true ); … … 195 122 return; 196 123 } 197 $stories = sh_get_stories(); 198 $profile = sh _get_profile();124 125 $profile = shorthand_api_get_profile(); 199 126 200 127 if ( ! ( $profile ) ) { 201 echo 'Could not connect to Shorthand, please check your API token in <a href="options-general.php?page=shorthand-options">Shorthand settings</a>.'; 202 } elseif ( $stories === null ) { 203 echo 'You currently have no stories ready for publishing on Shorthand. Please check that your story is set to be ready for publishing.'; 128 $uri = Shorthand_Admin::get_page_url(); 129 printf( wp_kses( __( 'Could not connect to Shorthand, please check your API token in <a alt="(opens Shorthand Connect plugin settings)" href="%s">Shorthand settings</a>.' ) ), esc_url( $uri ) ); 204 130 } else { 205 echo '<ul class="stories">'; 206 foreach ( $stories as $story ) { 207 $selected = ''; 208 $story_selected = ''; 209 if ( $selected_story === $story->id ) { 210 $selected = 'checked'; 211 $story_selected = 'selected'; 212 } 213 $archived = ''; 214 if ( isset( $story->story_version ) && '1' === $story->story_version ) { 215 if ( $show_archived_stories ) { 216 $archived = ' (archived)'; 217 } else { 218 continue; 219 } 220 } 221 echo '<li class="story ' . esc_attr( $story_selected ) . '"><label><input name="story_id" type="radio" value="' . esc_attr( $story->id ) . '" ' . esc_html( $selected ) . ' /><img width="150" src="' . esc_url( $baseurl . $story->image ) . '" /><span class="title">' . esc_html( $story->title . $archived ) . '</span><span class="desc">' . esc_html( $story->metadata->description ) . '</span></a></label></li>'; 222 } 223 echo '</ul><div class="clear"></div>'; 131 ?> 132 <div id="stories-list"> 133 <div class="filter-container wp-core-ui"> 134 <input class="search" placeholder="Search for a story" /> 135 <span class="sort button-secondary desc" data-sort="updated_value"> 136 Edited<span class="sort-icon"></span> 137 </span> 138 </div> 139 <!-- List to populate the stories. --> 140 <ul class="list stories"> 141 142 </ul> 143 </div> 144 <?php 145 wp_register_script( 146 'list-js', 147 plugin_dir_url( __FILE__ ) . 'js/list.js/v2.3.4/list.min.js', 148 array(), 149 '2.3.4', 150 array() 151 ); 152 wp_enqueue_script( 'list-js' ); 153 154 wp_register_script( 155 'list-js-stories', 156 plugin_dir_url( __FILE__ ) . 'js/connect-stories-list.js', 157 array(), 158 '1.0.0', 159 array( 160 'strategy' => 'defer', 161 ) 162 ); 163 wp_enqueue_script( 'list-js-stories' ); 164 165 wp_register_script( 166 'list-js-stories-selected', 167 plugin_dir_url( __FILE__ ) . 'js/connect-stories-list-selected.js', 168 array(), 169 '1.0.0', 170 array( 171 'strategy' => 'defer', 172 ) 173 ); 174 wp_enqueue_script( 'list-js-stories-selected' ); 175 wp_register_script( 176 'fetch-stories', 177 plugin_dir_url( __FILE__ ) . 'js/connect-stories-fetch.js', 178 array(), 179 '1.0.0', 180 array( 181 'strategy' => 'defer', 182 ) 183 ); 184 wp_localize_script('fetch-stories', 'wp_server', array( 185 'url' => ( get_option('permalink_structure') ) ? "/wp-json/shorthand_connect/v1/stories/" : "/?rest_route=/shorthand_connect/v1/stories/", 186 'nonce' => wp_create_nonce('wp_rest'), 187 'selected_story' => $selected_story 188 )); 189 wp_enqueue_script( 'fetch-stories' ); 190 echo '<div class="clear"></div>'; 224 191 } 225 192 226 193 // Noncename needed to verify where the data originated 227 echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' . 228 esc_attr( wp_create_nonce( plugin_basename( __FILE__ ) ) ) . '" />'; 229 194 echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' . esc_attr( wp_create_nonce( plugin_basename( __FILE__ ) ) ) . '" />'; 195 } 196 197 function shorthand_wpt_shorthand_story_advanced() { 230 198 ?> 199 <div class="form-check form-switch text-light"> 200 <input class="form-check-input" type="checkbox" id="show-advanced"> 201 <label class="form-check-label" for="show-advanced">Show advanced options</label> 202 </div> 231 203 <script> 232 jQuery('li.story input:radio').click(function () { 233 jQuery('li.story').removeClass('selected'); 234 jQuery(this).parent().parent().addClass('selected'); 235 jQuery('label#title-prompt-text').text(''); 236 jQuery('input#title').val(jQuery(this).parent().find('span.title').text()); 237 if (jQuery('textarea#abstract').val() === '') { 238 jQuery('textarea#abstract').val(jQuery(this).parent().find('span.desc').text()); 239 } 240 }); 204 //var elements = document.querySelectorAll( 'body *' ); 205 //document.getElementById("postcustom").style.visibility = 0; 206 console.log(document.getElementById("postcustom")); 241 207 </script> 242 208 <?php … … 259 225 formaction="?shand_update" 260 226 /> 261 262 <script>263 jQuery('#post').submit(function () {264 jQuery('#shorthand_update').prop('disabled', true);265 });266 </script>267 268 227 </div> 269 228 270 229 <?php 230 231 wp_register_script( 232 'connect-form', 233 plugin_dir_url( __FILE__ ) . 'js/connect-form.js', 234 array(), 235 '1.0.0', 236 array( 237 'strategy' => 'defer', 238 ) 239 ); 240 wp_enqueue_script( 'connect-form' ); 271 241 } 272 242 … … 275 245 global $noabstract; 276 246 $selected_story = get_post_meta( $post->ID, 'story_id', true ); 247 277 248 if ( $selected_story ) { 278 249 add_meta_box( 279 'sh and_wpt_shorthand_story_update',250 'shorthand_wpt_shorthand_story_update', 280 251 'Update Shorthand Story', 281 'sh and_wpt_shorthand_story',252 'shorthand_wpt_shorthand_story', 282 253 'shorthand_story', 283 254 'side', … … 286 257 } else { 287 258 add_meta_box( 288 'sh and_wpt_shorthand_story',259 'shorthand_wpt_shorthand_story', 289 260 'Select Shorthand Story', 290 'sh and_wpt_shorthand_story',261 'shorthand_wpt_shorthand_story', 291 262 'shorthand_story', 292 263 'normal', 293 'default' 294 ); 295 } 264 'high' 265 ); 266 } 267 296 268 if ( ! $noabstract ) { 297 269 add_meta_box( … … 300 272 'shand_wpt_shorthand_abstract', 301 273 'shorthand_story', 302 'normal', 303 'default' 304 ); 305 } 306 add_meta_box( 'shand_wpt_shorthand_extra_html', 'Add additional HTML', 'shand_wpt_shorthand_extra_html', 'shorthand_story', 'normal', 'default' ); 274 'advanced' 275 ); 276 } 277 278 add_meta_box( 279 'shand_wpt_shorthand_extra_html', 280 'Add additional HTML', 281 'shand_wpt_shorthand_extra_html', 282 'shorthand_story', 283 'advanced' 284 ); 307 285 } 308 286 … … 323 301 324 302 /* Save the shorthand story */ 325 function shand_save_shorthand_story( $post_id, $post ) { 303 function shorthand_save_shorthand_story( $post_id, $post ) { 304 $profile = shorthand_api_get_profile(); 305 if ( ( get_post_type( $post ) === 'shorthand_story' ) && ! ( $profile ) ) { 306 $uri = Shorthand_Admin::get_page_url(); 307 wp_die( message: sprintf( wp_kses_post ( __( 'Could not connect to Shorthand, please check your API token in <a alt="(opens Shorthand Connect plugin settings)" href="%s">Shorthand settings</a>.', 'shorthand-connect' ) ), esc_url( $uri ) ), title: wp_kses_post( __( 'Shorthand is not connected' ) ) ); 308 } 309 326 310 WP_Filesystem(); 327 311 global $wp_filesystem; … … 363 347 // Sanitize but also check if the query is GET or POST. 364 348 if ( isset( $_REQUEST['story_id'] ) ) { 365 $story_id = filter_input( INPUT_GET, 'story_id', FILTER_SANITIZE_STRING ); 366 // If the variable is not present in the $_GET array. 367 if ( null === $story_id ) { 368 $story_id = filter_input( INPUT_POST, 'story_id', FILTER_SANITIZE_STRING ); 369 } 349 $story_id = sanitize_text_field( $_REQUEST['story_id'] ); 370 350 $safe_story_id = preg_replace( '/\W|_/', '', $story_id ); 371 351 } … … 429 409 if ( ! $noabstract ) { 430 410 $abstract = $body; 431 remove_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );411 remove_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 432 412 $post = array( 433 413 'ID' => $post_id, 434 'post_content' => sh and_abstract_template( $post_id, wp_kses_post( $_REQUEST['abstract'] ), $abstract ),414 'post_content' => shorthand_abstract_template( $post_id, wp_kses_post( $_REQUEST['abstract'] ), $abstract ), 435 415 ); 436 416 wp_update_post( $post ); 437 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );417 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 438 418 } else { 439 remove_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );419 remove_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 440 420 $post = array( 441 421 'ID' => $post_id, … … 443 423 ); 444 424 wp_update_post( $post ); 445 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );425 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 446 426 } 447 427 … … 461 441 } 462 442 463 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );443 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 464 444 465 445 /* Load Shorthand Template Hook */ … … 467 447 global $post; 468 448 if ( 'shorthand_story' === $post->post_type ) { 469 $path = locate_template( array( 'single-shorthand_story.php', 'templates/single-shorthand_story.php', 'template-parts/single-shorthand_story.php' ) ); 449 $path = locate_template( 450 array( 451 'single-shorthand_story.php', 452 'templates/single-shorthand_story.php', 453 'template-parts/single-shorthand_story.php', 454 'single-shorthand-story.php', 455 'templates/single-shorthand-story.php', 456 'template-parts/single-shorthand-story.php', 457 ) 458 ); 470 459 if ( $path ) { 471 460 return $path; 472 461 } 473 462 $plugin_path = plugin_dir_path( __FILE__ ); 474 $template_name = 'templates/single-shorthand _story.php';463 $template_name = 'templates/single-shorthand-story.php'; 475 464 if ( ( get_stylesheet_directory() . '/' . $template_name === $template ) 476 465 || ! file_exists( $plugin_path . $template_name ) … … 491 480 if ( is_single() && 'shorthand_story' === get_post_type() ) { 492 481 $meta = get_post_meta( get_post()->ID ); 493 echo get_shorthandinfo( $meta, 'story_head' );482 echo ( get_shorthandinfo( $meta, 'story_head' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 494 483 } 495 484 } … … 506 495 if ( $query->is_main_query() && ! is_admin() ) { 507 496 $queried_object = get_queried_object(); 508 $shorthand_templates = array( 'single-shorthand_story.php', 'templates/single-shorthand_story.php', 'template-parts/single-shorthand_story.php' ); 497 $shorthand_templates = array( 498 'single-shorthand_story.php', 499 'templates/single-shorthand_story.php', 500 'template-parts/single-shorthand_story.php', 501 'single-shorthand-story.php', 502 'templates/single-shorthand-story.php', 503 'template-parts/single-shorthand-story.php', 504 ); 509 505 510 506 // Check if the queried object uses a Shorthand Post template from the array. … … 555 551 * Activates plugin by creating post type. 556 552 */ 557 function shand_shorthand_activate() { 553 function shorthand_shorthand_activate() { 554 558 555 shand_create_post_type(); 559 flush_rewrite_rules(); 560 } 561 562 register_activation_hook( __FILE__, 'shand_shorthand_activate' ); 556 flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules 557 558 // Set config values. 559 update_option( 'sh_v2_token', '' ); 560 update_option( 'sh_permalink', 'shorthand_story' ); 561 $css_path = '/css/options-default.css'; 562 $sh_css = file_get_contents( __DIR__. $css_path ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown 563 update_option( 'sh_css', $sh_css ); 564 update_option( 'sh_regex_list', '' ); 565 update_option( 'sh_media_cron_offload', true ); 566 update_option( 'sh_disable_acf', false ); 567 } 568 569 register_activation_hook( __FILE__, 'shorthand_shorthand_activate' ); 563 570 register_deactivation_hook( __FILE__, 'flush_rewrite_rules' ); 564 571 -
shorthand-connect/tags/1.3.32/trunk/templates/abstract.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Shorthand abstract template. 4 * 5 * @package Shorthand Connect 6 */ 2 7 3 function shand_abstract_template( $post_id, $abstract_html, $data ) { 4 $abstract_html = '<p>' . $abstract_html . '</p>'; 5 6 $abstract_html .= '<a href="' . get_permalink( $post_id ) . '">View the story</a>'; 7 8 $abstract_html .= '<div style="display:none;">' . $data . '</div>'; 9 return $abstract_html; 8 /** 9 * Generates a shorthand abstract template for a post. 10 * 11 * Creates a basic abstract template containing the provided abstract HTML, 12 a link to the post, and hidden data. 13 * 14 * @param int $post_id The ID of the post. 15 * @param string $abstract_html The HTML content for the abstract. 16 * @param string $data Additional data to be included in a hidden div. 17 * @return string The generated abstract HTML. 18 */ 19 function shorthand_abstract_template( $post_id, $abstract_html, $data ) { 20 $title = __( 'View the story' ); 21 $abstract = array( 22 '<p>' . $abstract_html . '</p>', 23 '<a href="' . get_permalink( $post_id ) . '">' . $title . '</a>', 24 '<div style="display:none;">' . $data . '</div>', 25 ); 26 return implode( $abstract ); 10 27 } -
shorthand-connect/trunk/includes/api.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Shorthand API functions. 4 * 5 * @package Shorthand Connect 6 */ 2 7 3 8 /* … … 11 16 * @param array $options An array of extra options args to pass to wp_remote_request 12 17 */ 13 function sh _v2_api_request( $url, $options ) {18 function shorthand_api_v2_request( $url, $options ) { 14 19 $token = get_option( 'sh_v2_token' ); 15 20 if ( ! $token ) { … … 44 49 } 45 50 46 function sh_v2_api_request_json( $url, $options ) { 47 $response = sh_v2_api_request( $url, $options ); 51 /** 52 * Makes a JSON API request to the shorthand API. 53 * 54 * @param string $url The URL of the API endpoint. 55 * @param array $options Optional arguments for the API request. 56 * @return mixed The decoded JSON response, or null if an error occurs. 57 */ 58 function shorthand_api_request_json( $url, $options ) { 59 $response = shorthand_api_v2_request( $url, $options ); 48 60 $body = wp_remote_retrieve_body( $response ); 49 61 return json_decode( $body ); 50 62 } 51 63 52 function sh_get_profile() { 64 /** 65 * Retrieves user profile information from the shorthand API. 66 * 67 * @return object User profile information, including username, gravatar, and other potential data. 68 */ 69 function shorthand_api_get_profile() { 53 70 $tokeninfo = array(); 54 71 55 $data = sh _v2_api_request_json( '/v2/token-info', array() );72 $data = shorthand_api_request_json( '/v2/token-info', array() ); 56 73 if ( $data && isset( $data->organisation_id ) ) { 57 74 $tokeninfo['username'] = $data->name . ' (' . $data->token_type . ' Token)'; … … 63 80 } 64 81 65 function sh_get_stories() { 82 /** 83 * Retrieves stories from the shorthand API. 84 * 85 * Fetches a list of stories from the shorthand API, optionally filtered by keyword. 86 * 87 * @param string $keyword Optional keyword to filter stories by. 88 * @return array|null An array of story data, or null if an error occurs or no stories are found. 89 */ 90 function shorthand_api_get_stories( string $keyword = '', string $cursor = '', string $limit = '50' ) { 66 91 $stories = null; 67 68 $data = sh_v2_api_request_json( '/v2/stories', array( 'timeout' => '240' ) ); 92 $url = '/v2/stories'; 93 $url .= '?limit='.$limit; 94 if ( $cursor && $cursor != '') { 95 $url .= '&cursor=' . $cursor; 96 } 97 if ( $keyword && $keyword != '' ) { 98 $url .= '&keyword=' . $keyword; 99 } 100 101 102 $data = shorthand_api_request_json( $url, array( 'timeout' => '240' ) ); 69 103 if ( $data ) { 70 104 $stories = array(); 71 // Something went wrong 105 // Something went wrong. 72 106 if ( isset( $data->status ) && $data->status ) { 73 107 return null; 74 108 } 109 75 110 foreach ( $data as $storydata ) { 76 $story = array( 77 'image' => $storydata->signedCover, 78 'id' => $storydata->id, 79 'metadata' => (object) array( 80 'description' => $storydata->description, 81 ), 82 'title' => $storydata->title, 83 'story_version' => '' . $storydata->version, 111 $updated_timestamp = strtotime( esc_html( $storydata->updatedAt ) ); 112 $updated_at = $storydata->updatedAt; 113 $published_timestamp = strtotime( esc_html( $storydata->lastPublishedAt ) ); 114 $updated = human_time_diff( $updated_timestamp, current_time( 'timestamp' ) ); 115 $published = human_time_diff( $published_timestamp, current_time( 'timestamp' ) ); 116 $stories[] = array( 117 'version_value' => '' . $storydata->version, 118 'title' => $storydata->title, 119 'description' => $storydata->description, 120 'imagealt' => $storydata->title, 121 'image' => $storydata->signedCover, 122 'updated_timestamp' => $updated_timestamp, 123 'updated_at' => $updated_at, 124 'updated_value' => $updated, 125 'published_timestamp' => $published_timestamp, 126 'published_value' => $published, 127 'story_id' => $storydata->id, 128 'class' => 'story', 84 129 ); 85 $stories[] = (object) $story;86 130 } 87 131 } … … 90 134 } 91 135 136 /** 137 * Gets the path to the story directory. 138 * 139 * Determines the path to the directory where story files for a specific post 140 * and story ID should be stored. 141 * 142 * @param int $post_id The ID of the post. 143 * @param string $story_id The ID of the story. 144 * @return string|null The path to the story directory, or null if the directory doesn't exist or an error occurs. 145 */ 92 146 function sh_get_story_path( $post_id, $story_id ) { 93 147 init_wp_filesystem(); … … 95 149 $destination_path = $destination['path'] . '/shorthand/' . $post_id . '/' . $story_id; 96 150 97 // on WP VIP, folders in the uploads dir always exist151 // On WP VIP, folders in the uploads dir always exist. 98 152 if ( ! file_exists( $destination_path ) ) { 99 153 $destination_path = null; … … 105 159 } 106 160 161 /** 162 * Gets the URL of the story directory. 163 * 164 * Determines the URL of the directory where story files for a specific post 165 * and story ID are located. 166 * 167 * @param int $post_id The ID of the post. 168 * @param string $story_id The ID of the story. 169 * @return string The URL of the story directory. 170 */ 107 171 function shorthand_get_story_url( $post_id, $story_id ) { 108 172 init_wp_filesystem(); … … 123 187 $story = array(); 124 188 125 // Attempt to connect to the server 126 $zip_file = wp_tempnam( 'sh_zip', $tmpdir );127 $response = sh_v2_api_request(189 // Attempt to connect to the server. 190 $zip_file = wp_tempnam( 'sh_zip', $tmpdir ); 191 $response = shorthand_api_v2_request( 128 192 '/v2/stories/' . $story_id . ( $without_assets ? '?without_assets=true' : '' ) . ( $assets_only ? '?assets_only=true' : '' ), 129 193 array( … … 145 209 ); 146 210 } else { 147 $story = extract StoryContent( $zip_file, $destination_path, $story_id );211 $story = extract_story_content( $zip_file, $destination_path, $story_id ); 148 212 } 149 213 … … 153 217 } 154 218 155 219 /** 220 * Initializes the WordPress filesystem. 221 * 222 * Ensures that the WordPress filesystem is available for file operations. 223 * If not, it requests filesystem credentials and re-initializes the filesystem. 224 */ 156 225 function init_wp_filesystem() { 157 226 WP_Filesystem(); … … 163 232 } 164 233 165 function extractStoryContent( $zip_file, $destination_path, $story_id ) { 234 /** 235 * Extracts story content from a ZIP file. 236 * 237 * Extracts the 'head.html' and 'article.html' files from a given ZIP file 238 * into a specified destination path. 239 * 240 * @param string $zip_file The path to the ZIP file. 241 * @param string $destination_path The path to the extraction destination. 242 * @param string $story_id The ID of the story. 243 * @return array An array containing extracted content, path, or error information. 244 */ 245 function extract_story_content( $zip_file, $destination_path, $story_id ) { 166 246 // WP VIP HOSTING COMPATIBILITY 167 247 $zip = new ZipArchive(); -
shorthand-connect/trunk/includes/mass-pull.php
r3095659 r3258349 1 1 <?php 2 /* 3 * Sets each custom meta field, should be paired with sh_copy_story().2 /** 3 * Bulk story pull functions. 4 4 * 5 * @package Shorthand Connect 6 */ 7 8 /** 9 * Updates a story for a given post. 10 * 11 * Fetches story data from the shorthand API, copies story files, updates post 12 * metadata, and performs post-processing on the story content. 5 13 * Note: Unzipping a fresh story copy won't update the fields. 14 * 15 * @param int $post_id The ID of the post. 16 * @param string $story_id The ID of the story. 6 17 */ 7 18 function shand_update_story( $post_id, $story_id ) { … … 14 25 15 26 // Grab JSON for Story & Set into object $obj. 16 $obj = sh _v2_api_request_json( '/v2/stories/' . $story_id . '/settings', array( 'timeout' => '240' ) );27 $obj = shorthand_api_request_json( '/v2/stories/' . $story_id . '/settings', array( 'timeout' => '240' ) ); 17 28 18 29 $err = sh_copy_story( $post_id, $safe_story_id, $sh_media_cron_offload ); -
shorthand-connect/trunk/includes/shorthand-options.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Admin settings for the first time dialog. 4 * 5 * @package Shorthand Connect 6 */ 7 2 8 /* Options */ 3 function shand_shorthand_menu() { 4 add_options_page( 'Shorthand Options', 'Shorthand', 'manage_options', 'shorthand-options', 'shand_shorthand_options' ); 5 } 6 $default_sh_site_css = ' 7 /* START CSS FOR DEFAULT WP THEMES */ 8 .site { 9 margin: 0; 10 max-width: none; 11 } 12 .site-content { 13 padding: 0 !important; 14 } 15 .site-inner { 16 max-width: none; 17 } 18 .site-header { 19 max-width: none; 20 z-index: 100; 21 } 22 .site:before { 23 width: 0; 24 } 25 /* END CSS FOR DEFAULT WP THEMES */ 26 '; 27 28 // JSON Checker 29 function validate_json( $json_string ) { 30 // Try to decode the JSON data. If it fails, the JSON is invalid. 31 $json_data = json_decode( $json_string, true ); 32 33 if ( json_last_error() !== JSON_ERROR_NONE ) { 34 // The JSON is invalid. 35 return false; 36 } 37 38 // Return the original JSON string if it's valid. 39 return $json_string; 40 } 41 42 function shand_shorthand_options() { 43 global $default_sh_site_css; 44 global $server_url; 45 46 // Rather than running a rewrite flush everytime a post is submitted, run it on plugin activate/deactivate 47 function shand_rewrite_flush() { 48 shand_create_post_type(); 49 flush_rewrite_rules(); 50 } 51 register_activation_hook( __FILE__, 'shand_rewrite_flush' ); 52 register_deactivation_hook( __FILE__, 'flush_rewrite_rules' ); 9 10 // Redirect to the first time setup. 11 function shorthand_redirect_admin_config() { 12 $profile = shorthand_api_get_profile(); 13 if ( isset( $_GET['page'] ) && ( 'shorthand-options' === $_GET['page'] ) && ( ! $profile ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 14 $admin_url = Shorthand_Admin::get_page_url( 'init' ); 15 wp_redirect( $admin_url ); 16 die(); 17 } 18 } 19 add_action( 'admin_menu', 'shorthand_redirect_admin_config' ); 20 21 function shorthand_shorthand_options() { 22 // Menu links. 23 $menu_links = array( 24 'token' => 'API Key', 25 'permalink' => 'Permalinks', 26 'css' => 'Custom CSS', 27 'processing' => 'Post-processing', 28 'experimental' => 'Experimental Features', 29 ); 30 31 // If current = all, then display all. 32 $current = isset( $_GET['navigation'] ) ? sanitize_key( $_GET['navigation'] ) : array_keys( $menu_links )[0]; 33 $profile = shorthand_api_get_profile(); 34 $messages = array(); 53 35 54 36 if ( ! current_user_can( 'manage_options' ) ) { 55 37 wp_die( esc_html( __( 'You do not have sufficient permissions to access this page.' ) ) ); 56 38 } 39 57 40 if ( isset( $_POST['sh_submit_hidden'] ) && 'Y' === $_POST['sh_submit_hidden'] && check_admin_referer( 'sh-update-configuration' ) ) { 58 41 // If there's a token set, use it, if not set it to an empty string 59 42 $sh_v2_token = isset( $_POST['sh_v2_token'] ) ? sanitize_text_field( $_POST['sh_v2_token'] ) : ''; 60 43 update_option( 'sh_v2_token', $sh_v2_token ); 44 45 $profile = shorthand_api_get_profile(); 46 if ( $profile ) { 47 $messages['updated'] = '<p>' . SHORTHAND_CONFIG_STEP1_SUCCESS . '</p><p><strong>Username</strong>: ' . esc_html( $profile->username ) . '</p>'; 48 } else { 49 $messages['notice-error'] = SHORTHAND_CONFIG_STEP1_ERROR; 50 } 61 51 } 62 52 … … 64 54 65 55 if ( isset( $_POST['sh_submit_hidden_two'] ) && 'Y' === $_POST['sh_submit_hidden_two'] && check_admin_referer( 'sh-update-configuration' ) ) { 66 // Check if there's custom CSS, if there is, use wp_kses_post() to sanitize otherwise set an empty string 56 // Check if there's custom CSS, if there is, use wp_kses_post() 57 // to sanitize otherwise set an empty string. 67 58 $sh_css = isset( $_POST['sh_css'] ) ? wp_kses_post( $_POST['sh_css'] ) : ''; 68 59 update_option( 'sh_css', $sh_css ); 60 $messages['updated'] = SHORTHAND_CONFIG_STEP3_SUCCESS; 69 61 } 70 62 71 63 if ( isset( $_POST['sh_submit_hidden_three'] ) && 'Y' === $_POST['sh_submit_hidden_three'] && check_admin_referer( 'sh-update-configuration' ) ) { 72 // Check if there's custom permalink, if there is, use sanitize_text_field() to sanitize potential HTML and then set an empty string 64 // Check if there's custom permalink, if there is, use sanitize_text_field() 65 // to sanitize potential HTML and then set an empty string. 73 66 $sh_permalink = isset( $_POST['sh_permalink'] ) ? sanitize_text_field( $_POST['sh_permalink'] ) : ''; 74 67 update_option( 'sh_permalink', $sh_permalink ); 75 shand_rewrite_flush(); 68 shorthand_rewrite_flush(); 69 $messages['updated'] = SHORTHAND_CONFIG_STEP2_SUCCESS; 76 70 } 77 71 $permalink_structure = esc_html( get_option( 'sh_permalink' ) ); … … 82 76 } 83 77 $sh_css = get_option( 'sh_css' ); 84 $no_css = false; 85 if ( '' === $sh_css ) { 86 $no_css = true; 87 if ( isset( $default_site_css ) ) { 88 update_option( 'sh_css', $default_site_css ); 89 } 90 $sh_css = $default_sh_site_css; 91 } 92 93 if ( isset( $_POST['sh_submit_hidden_four'] ) && 'Y' === $_POST['sh_submit_hidden_four'] && check_admin_referer( 'sh-update-configuration' ) ) { 94 $sh_regex_list = isset( $_POST['sh_regex_list'] ) ? wp_unslash( $_POST['sh_regex_list'] ) : ''; 95 78 79 if ( isset( $_POST['sh_submit_hidden_four'] ) && 80 ( 'Y' === $_POST['sh_submit_hidden_four'] ) && 81 check_admin_referer( 'sh-update-configuration' ) 82 ) { 83 // sh_regex_list may contain <tags> for lookup and processing on import and so may need to include <script> etc; however it is only ever displayed within a text-area value and manually processed. 84 $sh_regex_list = empty( $_POST['sh_regex_list'] ) ? '' : wp_unslash( $_POST['sh_regex_list'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized 85 86 $messages['updated'] = SHORTHAND_CONFIG_STEP4_SUCCESS; 96 87 if ( empty( $sh_regex_list ) ) { 97 // Update the option with an empty value if the input is empty 88 // Update the option with an empty value if the input is empty. 98 89 update_option( 'sh_regex_list', '' ); 99 90 } else { 100 91 // Validate if it's a valid JSON without sanitizing 101 $sh_regex_list = validate_json( $sh_regex_list );92 $sh_regex_list = Shorthand_Admin::validate_json( $sh_regex_list ); 102 93 103 94 if ( false !== $sh_regex_list ) { … … 106 97 } else { 107 98 // Handle invalid JSON error here. 99 unset( $messages['updated'] ); 100 $messages['notice-error'] = SHORTHAND_CONFIG_STEP4_ERROR; 108 101 } 109 102 } … … 112 105 $sh_regex_list = base64_decode( get_option( 'sh_regex_list' ) ); 113 106 114 // Experimental Settings107 // Experimental settings. 115 108 if ( isset( $_POST['sh_submit_hidden_experimental'] ) && 'Y' === $_POST['sh_submit_hidden_experimental'] && check_admin_referer( 'sh-update-configuration' ) ) { 116 109 $sh_media_cron_offload = isset( $_POST['sh_media_cron_offload'] ) ? filter_var( $_POST['sh_media_cron_offload'], FILTER_VALIDATE_BOOLEAN ) : false; … … 118 111 update_option( 'sh_media_cron_offload', $sh_media_cron_offload ); 119 112 update_option( 'sh_disable_acf', $sh_disable_acf ); 113 $messages['updated'] = SHORTHAND_CONFIG_STEP5_SUCCESS; 120 114 } 121 115 $sh_media_cron_offload = filter_var( get_option( 'sh_media_cron_offload' ), FILTER_VALIDATE_BOOLEAN ); 122 116 $sh_disable_acf = filter_var( get_option( 'sh_disable_acf' ), FILTER_VALIDATE_BOOLEAN ); 123 117 124 $profile = sh_get_profile(); 125 ?> 126 <div class="container"> 127 <div class="py-1"> 128 <h1>Shorthand API Configuration</h1> 129 <h2>Shorthand Connect Status</h2> 130 <form name="formtoken" method="post"> 131 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 132 <input type="hidden" name="sh_submit_hidden" value="Y" /> 133 <table class="form-table"><tbody> 134 <tr class="v2row"> 135 <th scope="row"><label for="sh_v2_token"><?php esc_html_e( 'Shorthand Team Token', 'sh-v2-token' ); ?></label></th> 136 <td><input type="text" id="sh_v2_token" name="sh_v2_token" value="<?php echo esc_attr( $v2_token ); ?>" size="28"></td> 137 </tr> 138 </tbody></table> 139 <?php if ( $profile ) { ?> 140 <p class="status">Successfully connected</p> 141 <p><strong>Username</strong>: <?php echo esc_html( $profile->username ); ?></p> 142 <?php } else { ?> 143 <p class="status warn">Not Connected</p> 144 <?php } ?> 145 <div style='clear:both'></div> 146 <p class="submit"> 147 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 118 ?> 119 <div class="wrap shorthand-options-wrapper"> 120 <h1>Settings</h1> 121 122 <hr /> 123 <div class="shorthand-menu"> 124 <ol role="list"> 125 <?php foreach ( $menu_links as $menu_key => $menu_name ) { ?> 126 <li class="py-1"> 127 <form name="menu_settings_<?php echo esc_attr( $menu_key ); ?>" method="post" action="<?php echo esc_url( Shorthand_Admin::get_page_url( 'config', esc_attr( $menu_key ) ) ); ?>"> 128 <input type="submit" name="Submit" class="button<?php echo ( in_array( $current, array( $menu_key, 'all' ) ) ) ? ' button button-primary' : ''; ?>" value="<?php esc_attr_e( $menu_name ); ?>" /> 129 </form> 130 </li> 131 <?php } ?> 132 </ol> 133 </div> 134 135 <div class="shorthand-form-wrapper"> 136 <form name="form_settings" method="post" action="<?php echo esc_url( Shorthand_Admin::get_page_url( 'config', esc_attr( $current ) ) ); ?>"> 137 138 <?php if ( ! empty( $messages ) ) : ?> 139 <?php foreach ( $messages as $class => $message ) : ?> 140 <div class="notice <?php echo esc_html ( $class ); ?>"><?php echo wp_kses( $message, array( 141 'p' => array(), 142 'strong' => array(), 143 ) ); ?></div> 144 <?php endforeach; ?> 145 <?php endif; ?> 146 147 <?php if ( in_array( $current, array( array_keys( $menu_links )[0], 'all' ) ) ) : ?> 148 <div class="py-1"> 149 <h2>Shorthand API Key</h2> 150 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 151 <input type="hidden" name="sh_submit_hidden" value="Y"/> 152 <p><label for="sh_v2_token"><?php esc_html_e( 'Your API key provided by Shorthand', 'shorthand-connect' ); ?></label></p> 153 <input type="text" id="sh_v2_token" name="sh_v2_token" value="<?php echo esc_attr( $v2_token ); ?>"> 154 <p> 155 <?php esc_html_e( 'Do not have API key?', 'shorthand-connect' ); ?> <a target="_blank" alt="(<?php esc_html_e( 'opens Shorthand Connect plugin settings', 'shorthand-connect' ); ?>)" href="https://support.shorthand.com/en/articles/62-programmatic-publishing-with-the-shorthand-api"><?php esc_html_e( 'Get one here', 'shorthand-connect' ); ?></a> 148 156 </p> 149 </form> 150 </div> 151 152 153 <div class="py-1"> 154 <h2>Shorthand Permalink Structure</h2> 155 <p>Use this to set the permalink structure of Shorthand story URLs</p> 156 <form name="permalinks" method="post"> 157 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 158 <input type="hidden" name="sh_submit_hidden_three" value="Y" /> 159 <p> 160 <?php _e( 'Permalink structure:', 'sh-permalink-value' ); ?><br /><?php echo esc_url( get_site_url() ); ?>/<input type="text" name="sh_permalink" value="<?php echo esc_attr( $permalink_structure ); ?>" size="20">/{STORY_NAME} 161 </p> 162 <p class="submit"> 163 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 164 </p> 165 </form> 166 </div> 167 168 <div class="py-1"> 169 <h2>Shorthand Story Page CSS (theme wide CSS)</h2> 170 <p>Use this CSS to customise Shorthand Story pages to better suit your theme</p> 171 <?php if ( $no_css ) { ?> 172 <p class="status warn">No custom CSS found, using default theme CSS</p> 173 <?php } ?> 174 <form name="themecss" method="post"> 175 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 176 <input type="hidden" name="sh_submit_hidden_two" value="Y" /> 177 <textarea rows="10" cols="80" name="sh_css"><?php echo esc_textarea( $sh_css ); ?></textarea> 178 <p class="submit"> 179 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 180 </p> 181 </form> 182 </div> 183 184 <div class="py-1"> 185 <h2>Post-processing</h2> 186 <p>Use this to create a JSON object of regex queries and replacements.</p> 157 <div style='clear:both'></div> 158 </div> 159 <?php endif; ?> 160 161 <?php if ( in_array( $current, array( array_keys( $menu_links )[1], 'all' ) ) ) : ?> 162 <div class="py-1"> 163 <h2>Permalink Structure</h2> 164 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 165 <input type="hidden" name="sh_submit_hidden_three" value="Y"/> 166 <p> 167 <p><label for="sh_permalink"><?php esc_html_e( 'Set the permalink structure of Shorthand story URLs', 'shorthand-connect' ); ?></label></p> 168 <input type="text" name="sh_permalink" value="<?php echo esc_attr( $permalink_structure ); ?>" size="20"> 169 <p><?php echo esc_url( get_site_url() ); ?>/<strong><?php echo esc_html( $permalink_structure ); ?></strong>/{STORY_NAME}</p> 170 </div> 171 <?php endif; ?> 172 173 <?php if ( in_array( $current, array( array_keys( $menu_links )[2], 'all' ) ) ) : ?> 174 <div class="py-1"> 175 <h2>Custom CSS</h2> 176 <p>Use theme wide CSS to customise Shorthand Story pages to better suit your theme</p> 177 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 178 <input type="hidden" name="sh_submit_hidden_two" value="Y"/> 179 <textarea rows="10" cols="80" name="sh_css"><?php echo esc_textarea( $sh_css ); ?></textarea> 180 </div> 181 <?php endif; ?> 182 183 <?php if ( in_array( $current, array( array_keys( $menu_links )[3], 'all' ) ) ) : ?> 184 <div class="py-1"> 185 <h2>Post-processing</h2> 186 <p>Create a JSON object of regex queries and replacements.</p> 187 187 <p><em>This Example removes title tags from within the head tag by replacing it with nothing.</em></p> 188 <pre><code>188 <pre><code class="post-processing"> 189 189 { 190 190 "head": [ 191 191 { 192 "query": "/<title>(.*?)<\\/title>/",193 "replace": ""192 "query": "/<title>(.*?)<\\/title>/", 193 "replace": "" 194 194 } 195 195 ], 196 196 "body": [] 197 197 } 198 199 </code></pre> 200 <form name="postprocessing" method="post"> 201 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 202 <input type="hidden" name="sh_submit_hidden_four" value="Y" /> 203 <textarea rows="10" cols="80" id="sh_regex_list" name="sh_regex_list"><?php echo esc_textarea( $sh_regex_list ); ?></textarea> 204 <p class="submit"> 205 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>" /> 206 </p> 207 </form> 198 </code></pre> 199 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 200 <input type="hidden" name="sh_submit_hidden_four" value="Y"/> 201 <textarea rows="10" cols="80" id="sh_regex_list" 202 name="sh_regex_list"><?php echo esc_textarea( $sh_regex_list ); ?></textarea> 208 203 <script> 209 204 let textarea = document.querySelector("textarea#sh_regex_list"); 210 211 textarea.addEventListener("keyup", function(event) { 212 try { 213 JSON.parse(textarea.value); 205 206 textarea.addEventListener("keyup", function (event) { 207 try { 208 textarea.value = JSON.stringify(JSON.parse(textarea.value), undefined, 4); 209 textarea.setCustomValidity(""); 210 211 } catch (err) { 212 if (textarea.value != "") { 213 console.log("Invalid JSON"); 214 textarea.setCustomValidity("Invalid JSON in the Post-processing field"); 215 } else { 214 216 textarea.setCustomValidity(""); 215 216 } catch(err) {217 if(textarea.value != ""){218 console.log("Invalid JSON");219 textarea.setCustomValidity("Invalid JSON in the Post-processing field");220 } else {221 textarea.setCustomValidity("");222 }223 217 } 224 218 } 219 225 220 }); 226 221 </script> 227 </div> 228 229 <div class="py-1"> 230 <h2>Experimental Features</h2> 231 <p>Early access features that are still subject to change.</p> 232 <form name="form_experimental" method="post"> 233 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 222 </div> 223 <?php endif; ?> 224 225 <?php if ( in_array( $current, array( array_keys( $menu_links )[4], 'all' ) ) ) : ?> 226 <div class="py-1"> 227 <h2>Experimental Features <span class="badge badge-blue">Advanced</span></h2> 228 <p>Early access features that are still subject to change.</p> 229 <?php wp_nonce_field( 'sh-update-configuration' ); ?> 234 230 <input type="hidden" name="sh_submit_hidden_experimental" value="Y"/> 235 <input type="checkbox" id="sh_media_cron_offload" name="sh_media_cron_offload" 236 value="true" <?php echo esc_attr( $sh_media_cron_offload ? 'checked' : '' ); ?> /> 237 <label for="sh_media_cron_offload">Import media assets via cron</label> 238 <p>Assets will be fetched after story save to prevent potential execution timeouts. Media won't be immediately 239 available on save but progress will be updated based on the `media_status` field.</p> 240 <p>It is advised that Shorthand Story Posts are saved as a draft first to trigger the cron job prior to public 241 publishing.</p> 231 232 <div class="checkbox-container"> 233 <input type="checkbox" id="sh_media_cron_offload" name="sh_media_cron_offload" <?php echo esc_attr( $sh_media_cron_offload ? 'checked' : '' ); ?> /> 234 <div class="bordered"> 235 <label for="sh_media_cron_offload"><strong>Import media assets via cron</strong> 236 <p>Assets will be fetched after story save to prevent potential execution timeouts. Media won't be immediately 237 available on save but progress will be updated based on the `media_status` field.</p> 238 <p>It is advised that Shorthand Story Posts are saved as a draft first to trigger the cron job prior to public 239 publishing.</p> 240 </label> 241 </div> 242 </div> 243 242 244 <br/> 245 <div class="checkbox-container"> 243 246 <input type="checkbox" id="sh_disable_acf" name="sh_disable_acf" 244 value="true" <?php echo esc_attr( $sh_disable_acf ? 'checked' : '' ); ?> />245 < label for="sh_disable_acf">Disable Advanced Custom Fields</label>246 <p>Used to prevent any potential issues that could cause the Shorthand Custom Fields to become hidden by Advanced247 Custom Fields.</p>247 value="true" <?php echo esc_attr( $sh_disable_acf ? 'checked' : '' ); ?> /> 248 <div class="bordered"><label for="sh_disable_acf"><strong>Disable Advanced Custom Fields</strong> 249 <p>Used to prevent any potential issues that could cause the Shorthand Custom Fields to become hidden by Advanced Custom Fields.</p></label></div> 250 </div> 248 251 </br> 252 </div> 253 <?php endif; ?> 254 255 <div class="py-1"> 256 <hr /> 249 257 <p class="submit"> 250 <input type="submit" name="Submit" class="button-primary" value="<?php esc_attr_e( 'Save Changes' ); ?>"/>258 <input type="submit" name="Submit" class="button button-primary" value="<?php esc_attr_e( 'Save changes' ); ?>"/> 251 259 </p> 260 </div> 252 261 </form> 253 </div> 254 </div> 255 </div> 256 <style> 257 .py-1 { 258 padding: 1em; 259 } 260 .bg-white { 261 background: white; 262 } 263 .container { 264 max-width: 980px; 265 } 266 img.grav { 267 float: left; 268 width:80px; 269 margin-right:10px; 270 } 271 p.status { 272 background:#dfd; 273 color:green; 274 font-weight:bold; 275 width:350px; 276 clear:left; 277 padding:5px; 278 } 279 p.status.warn { 280 background:#ffd; 281 color:orange; 282 } 283 .row-hidden { 284 display:none; 285 } 286 #wpfooter { 287 position: unset; 288 } 289 code { 290 font-family: monospace; 291 display: inherit; 292 } 293 </style> 294 262 263 </div> 264 </div> 265 </div> 295 266 296 267 <?php 297 268 } 298 269 299 add_action( 'admin_menu', 'shand_shorthand_menu' ); 300 301 ?> 270 function registerStyles() { 271 // Adding styles. 272 $css_path = '../css/options.css'; 273 wp_register_style( 'options_style', plugin_dir_url( __FILE__ ) . $css_path, array(), '1.3', 'all' ); 274 wp_enqueue_style( 'options_style' ); 275 } 276 277 add_action( 'init', 'registerStyles' ); 278 -
shorthand-connect/trunk/index.php
r2898299 r3258349 1 <?php // Silence is golden 1 <?php 2 // Silence is golden. -
shorthand-connect/trunk/shorthand-connect.php
r3095659 r3258349 1 1 <?php 2 2 /** 3 * Main plugin file. 4 * 3 5 * @package Shorthand Connect 4 * @version 1.3.315 6 */ 6 7 … … 10 11 Description: Import your Shorthand stories into your WordPress CMS as simply as possible - magic! 11 12 Author: Shorthand 12 Version: 1.3.3 113 Version: 1.3.32 13 14 Author URI: http://shorthand.com 14 15 */ 15 16 16 if ( file_exists( plugin_dir_path( __FILE__ ) . 'config.php' ) ) { 17 include_once plugin_dir_path( __FILE__ ) . 'config.php'; 17 // Make sure we don't expose any info if called directly. 18 if ( ! function_exists( 'add_action' ) ) { 19 echo 'Hi there! I\'m just a plugin, not much I can do when called directly.'; 20 exit; 21 } 22 23 define( 'SHORTHAND_VERSION', '1.3.32' ); 24 define( 'SHORTHAND__MINIMUM_WP_VERSION', '5.8' ); 25 define( 'SHORTHAND__PLUGIN_DIR', plugin_dir_path( __FILE__ ) ); 26 27 require_once SHORTHAND__PLUGIN_DIR . 'class-shorthand.php'; 28 29 // Add config. 30 if ( file_exists( SHORTHAND__PLUGIN_DIR . 'config.php' ) ) { 31 include_once SHORTHAND__PLUGIN_DIR . 'config.php'; 18 32 } else { 19 include_once plugin_dir_path( __FILE__ ) . 'config.default.php'; 20 } 21 require_once plugin_dir_path( __FILE__ ) . 'includes/api.php'; 22 require_once plugin_dir_path( __FILE__ ) . 'includes/mass-pull.php'; 23 24 require_once plugin_dir_path( __FILE__ ) . 'includes/shorthand-options.php'; 25 require_once plugin_dir_path( __FILE__ ) . 'templates/abstract.php'; 33 include_once SHORTHAND__PLUGIN_DIR . 'config-default.php'; 34 } 35 36 require_once SHORTHAND__PLUGIN_DIR . 'includes/api.php'; 37 require_once SHORTHAND__PLUGIN_DIR . 'includes/wp-api.php'; 38 require_once SHORTHAND__PLUGIN_DIR . 'includes/mass-pull.php'; 39 40 if ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) { 41 require_once SHORTHAND__PLUGIN_DIR . 'class-shorthand-admin.php'; 42 add_action( 'init', array( 'Shorthand_Admin', 'init' ) ); 43 } 44 45 // Loading initial setup or general configuration. 46 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options-variables.php'; 47 if ( isset( $_GET['view'] ) && ( $_GET['view'] === 'start' )) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended 48 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options-init.php'; 49 } else { 50 require_once SHORTHAND__PLUGIN_DIR . 'includes/shorthand-options.php'; 51 } 52 53 // Added admin menu. 54 function shorthand_shorthand_menu() { 55 add_options_page( 'Shorthand Options', 'Shorthand', 'manage_options', 'shorthand-options', 'shorthand_shorthand_options' ); 56 } 57 add_action( 'admin_menu', 'shorthand_shorthand_menu' ); 58 59 require_once SHORTHAND__PLUGIN_DIR . 'templates/abstract.php'; 26 60 27 61 if ( ! function_exists( 'WP_Filesystem' ) ) { … … 73 107 add_action( 'init', 'shand_create_post_type' ); 74 108 75 function sh and_wpt_shorthand_story() {109 function shorthand_wpt_shorthand_story() { 76 110 global $post; 77 global $server_url;78 111 global $show_archived_stories; 79 112 $baseurl = ''; 80 113 81 ?> 82 <style> 83 li.story { 84 float: left; 85 width: 160px; 86 margin: 5px; 87 } 88 89 li.story.selected label { 90 background: #5b9dd9; 91 color: #eee; 92 } 93 94 li.story input { 95 display: none !important; 96 } 97 98 li.story label { 99 display: block; 100 background: #fafafa; 101 text-align: center; 102 height: 160px; 103 padding-top: 5px; 104 border: 1px solid #eeeeee; 105 } 106 107 li.story label:hover { 108 border: 1px solid #5b9dd9; 109 } 110 111 li.story label span { 112 display: block; 113 font-weight: bold; 114 } 115 116 li.story label span.desc { 117 display: none; 118 } 119 120 div.clear { 121 clear: left; 122 } 123 124 div.publishing-actions { 125 padding: 10px; 126 clear: both; 127 border-top: 1px solid #dcdcde; 128 background: #f6f7f7; 129 margin: -12px; 130 margin-top: -12px; 131 margin-top: 10px; 132 display: flex; 133 justify-content: center; 134 } 135 136 .button-shorthand { 137 background-color: #000; 138 border: 1px solid #000; 139 transition: background-color .15s ease, color .15s ease; 140 color: #fff; 141 font-family: poppins, sans-serif; 142 font-size: 13px; 143 font-weight: 600; 144 letter-spacing: 0; 145 line-height: 1; 146 padding: 1em 2em; 147 text-decoration: none; 148 cursor: pointer; 149 border-radius: .9em; 150 } 151 152 .button-shorthand:hover { 153 background-color: #fff; 154 border-color: #000; 155 color: #000; 156 } 157 158 .button-shorthand:disabled { 159 pointer-events: none; 160 } 161 162 #codearea { 163 border: 1px solid #999999; 164 font-family: Consolas, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace; 165 width: 100%; 166 height: 300px; 167 } 168 169 #abstract { 170 border: 1px solid #999999; 171 width: 100%; 172 height: 200px; 173 } 174 175 ul.stories { 176 max-height: 400px; 177 overflow-y: scroll; 178 } 179 180 ul.stories img { 181 object-fit: cover; 182 height: 110px; 183 } 184 185 p.warning { 186 color: red; 187 font-weight: bold; 188 } 189 </style> 190 <?php 114 // Adding styles. 115 $css_path = 'css/connect.css'; 116 wp_register_style( 'connect_style', plugin_dir_url( __FILE__ ) . $css_path, array(), '1.3', 'all' ); 117 wp_enqueue_style( 'connect_style' ); 191 118 192 119 $selected_story = get_post_meta( $post->ID, 'story_id', true ); … … 195 122 return; 196 123 } 197 $stories = sh_get_stories(); 198 $profile = sh _get_profile();124 125 $profile = shorthand_api_get_profile(); 199 126 200 127 if ( ! ( $profile ) ) { 201 echo 'Could not connect to Shorthand, please check your API token in <a href="options-general.php?page=shorthand-options">Shorthand settings</a>.'; 202 } elseif ( $stories === null ) { 203 echo 'You currently have no stories ready for publishing on Shorthand. Please check that your story is set to be ready for publishing.'; 128 $uri = Shorthand_Admin::get_page_url(); 129 printf( wp_kses( __( 'Could not connect to Shorthand, please check your API token in <a alt="(opens Shorthand Connect plugin settings)" href="%s">Shorthand settings</a>.' ) ), esc_url( $uri ) ); 204 130 } else { 205 echo '<ul class="stories">'; 206 foreach ( $stories as $story ) { 207 $selected = ''; 208 $story_selected = ''; 209 if ( $selected_story === $story->id ) { 210 $selected = 'checked'; 211 $story_selected = 'selected'; 212 } 213 $archived = ''; 214 if ( isset( $story->story_version ) && '1' === $story->story_version ) { 215 if ( $show_archived_stories ) { 216 $archived = ' (archived)'; 217 } else { 218 continue; 219 } 220 } 221 echo '<li class="story ' . esc_attr( $story_selected ) . '"><label><input name="story_id" type="radio" value="' . esc_attr( $story->id ) . '" ' . esc_html( $selected ) . ' /><img width="150" src="' . esc_url( $baseurl . $story->image ) . '" /><span class="title">' . esc_html( $story->title . $archived ) . '</span><span class="desc">' . esc_html( $story->metadata->description ) . '</span></a></label></li>'; 222 } 223 echo '</ul><div class="clear"></div>'; 131 ?> 132 <div id="stories-list"> 133 <div class="filter-container wp-core-ui"> 134 <input class="search" placeholder="Search for a story" /> 135 <span class="sort button-secondary desc" data-sort="updated_value"> 136 Edited<span class="sort-icon"></span> 137 </span> 138 </div> 139 <!-- List to populate the stories. --> 140 <ul class="list stories"> 141 142 </ul> 143 </div> 144 <?php 145 wp_register_script( 146 'list-js', 147 plugin_dir_url( __FILE__ ) . 'js/list.js/v2.3.4/list.min.js', 148 array(), 149 '2.3.4', 150 array() 151 ); 152 wp_enqueue_script( 'list-js' ); 153 154 wp_register_script( 155 'list-js-stories', 156 plugin_dir_url( __FILE__ ) . 'js/connect-stories-list.js', 157 array(), 158 '1.0.0', 159 array( 160 'strategy' => 'defer', 161 ) 162 ); 163 wp_enqueue_script( 'list-js-stories' ); 164 165 wp_register_script( 166 'list-js-stories-selected', 167 plugin_dir_url( __FILE__ ) . 'js/connect-stories-list-selected.js', 168 array(), 169 '1.0.0', 170 array( 171 'strategy' => 'defer', 172 ) 173 ); 174 wp_enqueue_script( 'list-js-stories-selected' ); 175 wp_register_script( 176 'fetch-stories', 177 plugin_dir_url( __FILE__ ) . 'js/connect-stories-fetch.js', 178 array(), 179 '1.0.0', 180 array( 181 'strategy' => 'defer', 182 ) 183 ); 184 wp_localize_script('fetch-stories', 'wp_server', array( 185 'url' => ( get_option('permalink_structure') ) ? "/wp-json/shorthand_connect/v1/stories/" : "/?rest_route=/shorthand_connect/v1/stories/", 186 'nonce' => wp_create_nonce('wp_rest'), 187 'selected_story' => $selected_story 188 )); 189 wp_enqueue_script( 'fetch-stories' ); 190 echo '<div class="clear"></div>'; 224 191 } 225 192 226 193 // Noncename needed to verify where the data originated 227 echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' . 228 esc_attr( wp_create_nonce( plugin_basename( __FILE__ ) ) ) . '" />'; 229 194 echo '<input type="hidden" name="eventmeta_noncename" id="eventmeta_noncename" value="' . esc_attr( wp_create_nonce( plugin_basename( __FILE__ ) ) ) . '" />'; 195 } 196 197 function shorthand_wpt_shorthand_story_advanced() { 230 198 ?> 199 <div class="form-check form-switch text-light"> 200 <input class="form-check-input" type="checkbox" id="show-advanced"> 201 <label class="form-check-label" for="show-advanced">Show advanced options</label> 202 </div> 231 203 <script> 232 jQuery('li.story input:radio').click(function () { 233 jQuery('li.story').removeClass('selected'); 234 jQuery(this).parent().parent().addClass('selected'); 235 jQuery('label#title-prompt-text').text(''); 236 jQuery('input#title').val(jQuery(this).parent().find('span.title').text()); 237 if (jQuery('textarea#abstract').val() === '') { 238 jQuery('textarea#abstract').val(jQuery(this).parent().find('span.desc').text()); 239 } 240 }); 204 //var elements = document.querySelectorAll( 'body *' ); 205 //document.getElementById("postcustom").style.visibility = 0; 206 console.log(document.getElementById("postcustom")); 241 207 </script> 242 208 <?php … … 259 225 formaction="?shand_update" 260 226 /> 261 262 <script>263 jQuery('#post').submit(function () {264 jQuery('#shorthand_update').prop('disabled', true);265 });266 </script>267 268 227 </div> 269 228 270 229 <?php 230 231 wp_register_script( 232 'connect-form', 233 plugin_dir_url( __FILE__ ) . 'js/connect-form.js', 234 array(), 235 '1.0.0', 236 array( 237 'strategy' => 'defer', 238 ) 239 ); 240 wp_enqueue_script( 'connect-form' ); 271 241 } 272 242 … … 275 245 global $noabstract; 276 246 $selected_story = get_post_meta( $post->ID, 'story_id', true ); 247 277 248 if ( $selected_story ) { 278 249 add_meta_box( 279 'sh and_wpt_shorthand_story_update',250 'shorthand_wpt_shorthand_story_update', 280 251 'Update Shorthand Story', 281 'sh and_wpt_shorthand_story',252 'shorthand_wpt_shorthand_story', 282 253 'shorthand_story', 283 254 'side', … … 286 257 } else { 287 258 add_meta_box( 288 'sh and_wpt_shorthand_story',259 'shorthand_wpt_shorthand_story', 289 260 'Select Shorthand Story', 290 'sh and_wpt_shorthand_story',261 'shorthand_wpt_shorthand_story', 291 262 'shorthand_story', 292 263 'normal', 293 'default' 294 ); 295 } 264 'high' 265 ); 266 } 267 296 268 if ( ! $noabstract ) { 297 269 add_meta_box( … … 300 272 'shand_wpt_shorthand_abstract', 301 273 'shorthand_story', 302 'normal', 303 'default' 304 ); 305 } 306 add_meta_box( 'shand_wpt_shorthand_extra_html', 'Add additional HTML', 'shand_wpt_shorthand_extra_html', 'shorthand_story', 'normal', 'default' ); 274 'advanced' 275 ); 276 } 277 278 add_meta_box( 279 'shand_wpt_shorthand_extra_html', 280 'Add additional HTML', 281 'shand_wpt_shorthand_extra_html', 282 'shorthand_story', 283 'advanced' 284 ); 307 285 } 308 286 … … 323 301 324 302 /* Save the shorthand story */ 325 function shand_save_shorthand_story( $post_id, $post ) { 303 function shorthand_save_shorthand_story( $post_id, $post ) { 304 $profile = shorthand_api_get_profile(); 305 if ( ( get_post_type( $post ) === 'shorthand_story' ) && ! ( $profile ) ) { 306 $uri = Shorthand_Admin::get_page_url(); 307 wp_die( message: sprintf( wp_kses_post ( __( 'Could not connect to Shorthand, please check your API token in <a alt="(opens Shorthand Connect plugin settings)" href="%s">Shorthand settings</a>.', 'shorthand-connect' ) ), esc_url( $uri ) ), title: wp_kses_post( __( 'Shorthand is not connected' ) ) ); 308 } 309 326 310 WP_Filesystem(); 327 311 global $wp_filesystem; … … 363 347 // Sanitize but also check if the query is GET or POST. 364 348 if ( isset( $_REQUEST['story_id'] ) ) { 365 $story_id = filter_input( INPUT_GET, 'story_id', FILTER_SANITIZE_STRING ); 366 // If the variable is not present in the $_GET array. 367 if ( null === $story_id ) { 368 $story_id = filter_input( INPUT_POST, 'story_id', FILTER_SANITIZE_STRING ); 369 } 349 $story_id = sanitize_text_field( $_REQUEST['story_id'] ); 370 350 $safe_story_id = preg_replace( '/\W|_/', '', $story_id ); 371 351 } … … 429 409 if ( ! $noabstract ) { 430 410 $abstract = $body; 431 remove_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );411 remove_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 432 412 $post = array( 433 413 'ID' => $post_id, 434 'post_content' => sh and_abstract_template( $post_id, wp_kses_post( $_REQUEST['abstract'] ), $abstract ),414 'post_content' => shorthand_abstract_template( $post_id, wp_kses_post( $_REQUEST['abstract'] ), $abstract ), 435 415 ); 436 416 wp_update_post( $post ); 437 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );417 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 438 418 } else { 439 remove_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );419 remove_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 440 420 $post = array( 441 421 'ID' => $post_id, … … 443 423 ); 444 424 wp_update_post( $post ); 445 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );425 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 446 426 } 447 427 … … 461 441 } 462 442 463 add_action( 'save_post', 'sh and_save_shorthand_story', 10, 3 );443 add_action( 'save_post', 'shorthand_save_shorthand_story', 10, 3 ); 464 444 465 445 /* Load Shorthand Template Hook */ … … 467 447 global $post; 468 448 if ( 'shorthand_story' === $post->post_type ) { 469 $path = locate_template( array( 'single-shorthand_story.php', 'templates/single-shorthand_story.php', 'template-parts/single-shorthand_story.php' ) ); 449 $path = locate_template( 450 array( 451 'single-shorthand_story.php', 452 'templates/single-shorthand_story.php', 453 'template-parts/single-shorthand_story.php', 454 'single-shorthand-story.php', 455 'templates/single-shorthand-story.php', 456 'template-parts/single-shorthand-story.php', 457 ) 458 ); 470 459 if ( $path ) { 471 460 return $path; 472 461 } 473 462 $plugin_path = plugin_dir_path( __FILE__ ); 474 $template_name = 'templates/single-shorthand _story.php';463 $template_name = 'templates/single-shorthand-story.php'; 475 464 if ( ( get_stylesheet_directory() . '/' . $template_name === $template ) 476 465 || ! file_exists( $plugin_path . $template_name ) … … 491 480 if ( is_single() && 'shorthand_story' === get_post_type() ) { 492 481 $meta = get_post_meta( get_post()->ID ); 493 echo get_shorthandinfo( $meta, 'story_head' );482 echo ( get_shorthandinfo( $meta, 'story_head' ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 494 483 } 495 484 } … … 506 495 if ( $query->is_main_query() && ! is_admin() ) { 507 496 $queried_object = get_queried_object(); 508 $shorthand_templates = array( 'single-shorthand_story.php', 'templates/single-shorthand_story.php', 'template-parts/single-shorthand_story.php' ); 497 $shorthand_templates = array( 498 'single-shorthand_story.php', 499 'templates/single-shorthand_story.php', 500 'template-parts/single-shorthand_story.php', 501 'single-shorthand-story.php', 502 'templates/single-shorthand-story.php', 503 'template-parts/single-shorthand-story.php', 504 ); 509 505 510 506 // Check if the queried object uses a Shorthand Post template from the array. … … 555 551 * Activates plugin by creating post type. 556 552 */ 557 function shand_shorthand_activate() { 553 function shorthand_shorthand_activate() { 554 558 555 shand_create_post_type(); 559 flush_rewrite_rules(); 560 } 561 562 register_activation_hook( __FILE__, 'shand_shorthand_activate' ); 556 flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules 557 558 // Set config values. 559 update_option( 'sh_v2_token', '' ); 560 update_option( 'sh_permalink', 'shorthand_story' ); 561 $css_path = '/css/options-default.css'; 562 $sh_css = file_get_contents( __DIR__. $css_path ); // phpcs:ignore WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown 563 update_option( 'sh_css', $sh_css ); 564 update_option( 'sh_regex_list', '' ); 565 update_option( 'sh_media_cron_offload', true ); 566 update_option( 'sh_disable_acf', false ); 567 } 568 569 register_activation_hook( __FILE__, 'shorthand_shorthand_activate' ); 563 570 register_deactivation_hook( __FILE__, 'flush_rewrite_rules' ); 564 571 -
shorthand-connect/trunk/templates/abstract.php
r3095659 r3258349 1 1 <?php 2 /** 3 * Shorthand abstract template. 4 * 5 * @package Shorthand Connect 6 */ 2 7 3 function shand_abstract_template( $post_id, $abstract_html, $data ) { 4 $abstract_html = '<p>' . $abstract_html . '</p>'; 5 6 $abstract_html .= '<a href="' . get_permalink( $post_id ) . '">View the story</a>'; 7 8 $abstract_html .= '<div style="display:none;">' . $data . '</div>'; 9 return $abstract_html; 8 /** 9 * Generates a shorthand abstract template for a post. 10 * 11 * Creates a basic abstract template containing the provided abstract HTML, 12 a link to the post, and hidden data. 13 * 14 * @param int $post_id The ID of the post. 15 * @param string $abstract_html The HTML content for the abstract. 16 * @param string $data Additional data to be included in a hidden div. 17 * @return string The generated abstract HTML. 18 */ 19 function shorthand_abstract_template( $post_id, $abstract_html, $data ) { 20 $title = __( 'View the story' ); 21 $abstract = array( 22 '<p>' . $abstract_html . '</p>', 23 '<a href="' . get_permalink( $post_id ) . '">' . $title . '</a>', 24 '<div style="display:none;">' . $data . '</div>', 25 ); 26 return implode( $abstract ); 10 27 }
Note: See TracChangeset
for help on using the changeset viewer.