PK! f block-styles.phpnu[ 'twentytwentyone-columns-overlap', 'label' => esc_html__( 'Overlap', 'twentytwentyone' ), ) ); // Cover: Borders. register_block_style( 'core/cover', array( 'name' => 'twentytwentyone-border', 'label' => esc_html__( 'Borders', 'twentytwentyone' ), ) ); // Group: Borders. register_block_style( 'core/group', array( 'name' => 'twentytwentyone-border', 'label' => esc_html__( 'Borders', 'twentytwentyone' ), ) ); // Image: Borders. register_block_style( 'core/image', array( 'name' => 'twentytwentyone-border', 'label' => esc_html__( 'Borders', 'twentytwentyone' ), ) ); // Image: Frame. register_block_style( 'core/image', array( 'name' => 'twentytwentyone-image-frame', 'label' => esc_html__( 'Frame', 'twentytwentyone' ), ) ); // Latest Posts: Dividers. register_block_style( 'core/latest-posts', array( 'name' => 'twentytwentyone-latest-posts-dividers', 'label' => esc_html__( 'Dividers', 'twentytwentyone' ), ) ); // Latest Posts: Borders. register_block_style( 'core/latest-posts', array( 'name' => 'twentytwentyone-latest-posts-borders', 'label' => esc_html__( 'Borders', 'twentytwentyone' ), ) ); // Media & Text: Borders. register_block_style( 'core/media-text', array( 'name' => 'twentytwentyone-border', 'label' => esc_html__( 'Borders', 'twentytwentyone' ), ) ); // Separator: Thick. register_block_style( 'core/separator', array( 'name' => 'twentytwentyone-separator-thick', 'label' => esc_html__( 'Thick', 'twentytwentyone' ), ) ); // Social icons: Dark gray color. register_block_style( 'core/social-links', array( 'name' => 'twentytwentyone-social-icons-color', 'label' => esc_html__( 'Dark gray', 'twentytwentyone' ), ) ); } add_action( 'init', 'twenty_twenty_one_register_block_styles' ); } PK!zsddtemplate-tags.phpnu[%2$s'; $time_string = sprintf( $time_string, esc_attr( get_the_date( DATE_W3C ) ), esc_html( get_the_date() ) ); echo ''; printf( /* translators: %s: Publish date. */ esc_html__( 'Published %s', 'twentytwentyone' ), $time_string // phpcs:ignore WordPress.Security.EscapeOutput ); echo ''; } } if ( ! function_exists( 'twenty_twenty_one_posted_by' ) ) { /** * Prints HTML with meta information about theme author. * * @since Twenty Twenty-One 1.0 * * @return void */ function twenty_twenty_one_posted_by() { if ( ! get_the_author_meta( 'description' ) && post_type_supports( get_post_type(), 'author' ) ) { echo ''; printf( /* translators: %s: Author name. */ esc_html__( 'By %s', 'twentytwentyone' ), '' ); echo ''; } } } if ( ! function_exists( 'twenty_twenty_one_entry_meta_footer' ) ) { /** * Prints HTML with meta information for the categories, tags and comments. * Footer entry meta is displayed differently in archives and single posts. * * @since Twenty Twenty-One 1.0 * * @return void */ function twenty_twenty_one_entry_meta_footer() { // Early exit if not a post. if ( 'post' !== get_post_type() ) { return; } // Hide meta information on pages. if ( ! is_single() ) { if ( is_sticky() ) { echo '

' . esc_html_x( 'Featured post', 'Label for sticky posts', 'twentytwentyone' ) . '

'; } $post_format = get_post_format(); if ( 'aside' === $post_format || 'status' === $post_format ) { echo '

' . twenty_twenty_one_continue_reading_text() . '

'; // phpcs:ignore WordPress.Security.EscapeOutput } // Posted on. twenty_twenty_one_posted_on(); // Edit post link. edit_post_link( sprintf( /* translators: %s: Post title. Only visible to screen readers. */ esc_html__( 'Edit %s', 'twentytwentyone' ), '' . get_the_title() . '' ), '', '
' ); if ( has_category() || has_tag() ) { echo '
'; $categories_list = get_the_category_list( wp_get_list_item_separator() ); if ( $categories_list ) { printf( /* translators: %s: List of categories. */ '' . esc_html__( 'Categorized as %s', 'twentytwentyone' ) . ' ', $categories_list // phpcs:ignore WordPress.Security.EscapeOutput ); } $tags_list = get_the_tag_list( '', wp_get_list_item_separator() ); if ( $tags_list && ! is_wp_error( $tags_list ) ) { printf( /* translators: %s: List of tags. */ '' . esc_html__( 'Tagged %s', 'twentytwentyone' ) . '', $tags_list // phpcs:ignore WordPress.Security.EscapeOutput ); } echo '
'; } } else { echo '
'; // Posted on. twenty_twenty_one_posted_on(); // Posted by. twenty_twenty_one_posted_by(); // Edit post link. edit_post_link( sprintf( /* translators: %s: Post title. Only visible to screen readers. */ esc_html__( 'Edit %s', 'twentytwentyone' ), '' . get_the_title() . '' ), '', '' ); echo '
'; if ( has_category() || has_tag() ) { echo '
'; $categories_list = get_the_category_list( wp_get_list_item_separator() ); if ( $categories_list ) { printf( /* translators: %s: List of categories. */ '' . esc_html__( 'Categorized as %s', 'twentytwentyone' ) . ' ', $categories_list // phpcs:ignore WordPress.Security.EscapeOutput ); } $tags_list = get_the_tag_list( '', wp_get_list_item_separator() ); if ( $tags_list && ! is_wp_error( $tags_list ) ) { printf( /* translators: %s: List of tags. */ '' . esc_html__( 'Tagged %s', 'twentytwentyone' ) . '', $tags_list // phpcs:ignore WordPress.Security.EscapeOutput ); } echo '
'; } } } } if ( ! function_exists( 'twenty_twenty_one_post_thumbnail' ) ) { /** * Displays an optional post thumbnail. * * Wraps the post thumbnail in an anchor element on index views, or a div * element when on single views. * * @since Twenty Twenty-One 1.0 * * @return void */ function twenty_twenty_one_post_thumbnail() { if ( ! twenty_twenty_one_can_show_post_thumbnail() ) { return; } ?>
false ) ); ?>
esc_html__( 'Page', 'twentytwentyone' ) . ' ', 'mid_size' => 0, 'prev_text' => sprintf( '%s %s', is_rtl() ? twenty_twenty_one_get_icon_svg( 'ui', 'arrow_right' ) : twenty_twenty_one_get_icon_svg( 'ui', 'arrow_left' ), wp_kses( __( 'Newer posts', 'twentytwentyone' ), array( 'span' => array( 'class' => array(), ), ) ) ), 'next_text' => sprintf( '%s %s', wp_kses( __( 'Older posts', 'twentytwentyone' ), array( 'span' => array( 'class' => array(), ), ) ), is_rtl() ? twenty_twenty_one_get_icon_svg( 'ui', 'arrow_left' ) : twenty_twenty_one_get_icon_svg( 'ui', 'arrow_right' ) ), ) ); } } PK!#;EEtemplate-functions.phpnu['; } } add_action( 'wp_head', 'twenty_twenty_one_pingback_header' ); /** * Remove the `no-js` class from body if JS is supported. * * @since Twenty Twenty-One 1.0 * * @return void */ function twenty_twenty_one_supports_js() { echo ''; } add_action( 'wp_footer', 'twenty_twenty_one_supports_js' ); /** * Changes comment form default fields. * * @since Twenty Twenty-One 1.0 * * @param array $defaults The form defaults. * @return array */ function twenty_twenty_one_comment_form_defaults( $defaults ) { // Adjust height of comment form. $defaults['comment_field'] = preg_replace( '/rows="\d+"/', 'rows="5"', $defaults['comment_field'] ); return $defaults; } add_filter( 'comment_form_defaults', 'twenty_twenty_one_comment_form_defaults' ); /** * Determines if post thumbnail can be displayed. * * @since Twenty Twenty-One 1.0 * * @return bool */ function twenty_twenty_one_can_show_post_thumbnail() { /** * Filters whether post thumbnail can be displayed. * * @since Twenty Twenty-One 1.0 * * @param bool $show_post_thumbnail Whether to show post thumbnail. */ return apply_filters( 'twenty_twenty_one_can_show_post_thumbnail', ! post_password_required() && ! is_attachment() && has_post_thumbnail() ); } /** * Returns the size for avatars used in the theme. * * @since Twenty Twenty-One 1.0 * * @return int */ function twenty_twenty_one_get_avatar_size() { return 60; } /** * Creates continue reading text. * * @since Twenty Twenty-One 1.0 */ function twenty_twenty_one_continue_reading_text() { $continue_reading = sprintf( /* translators: %s: Post title. Only visible to screen readers. */ esc_html__( 'Continue reading %s', 'twentytwentyone' ), the_title( '', '', false ) ); return $continue_reading; } /** * Creates the continue reading link for excerpt. * * @since Twenty Twenty-One 1.0 */ function twenty_twenty_one_continue_reading_link_excerpt() { if ( ! is_admin() ) { return '… ' . twenty_twenty_one_continue_reading_text() . ''; } } // Filter the excerpt more link. add_filter( 'excerpt_more', 'twenty_twenty_one_continue_reading_link_excerpt' ); /** * Creates the continue reading link. * * @since Twenty Twenty-One 1.0 */ function twenty_twenty_one_continue_reading_link() { if ( ! is_admin() ) { return ''; } } // Filter the content more link. add_filter( 'the_content_more_link', 'twenty_twenty_one_continue_reading_link' ); if ( ! function_exists( 'twenty_twenty_one_post_title' ) ) { /** * Adds a title to posts and pages that are missing titles. * * @since Twenty Twenty-One 1.0 * * @param string $title The title. * @return string */ function twenty_twenty_one_post_title( $title ) { return '' === $title ? esc_html_x( 'Untitled', 'Added to posts and pages that are missing titles', 'twentytwentyone' ) : $title; } } add_filter( 'the_title', 'twenty_twenty_one_post_title' ); /** * Gets the SVG code for a given icon. * * @since Twenty Twenty-One 1.0 * * @param string $group The icon group. * @param string $icon The icon. * @param int $size The icon size in pixels. * @return string */ function twenty_twenty_one_get_icon_svg( $group, $icon, $size = 24 ) { return Twenty_Twenty_One_SVG_Icons::get_svg( $group, $icon, $size ); } /** * Changes the default navigation arrows to svg icons * * @since Twenty Twenty-One 1.0 * * @param string $calendar_output The generated HTML of the calendar. * @return string */ function twenty_twenty_one_change_calendar_nav_arrows( $calendar_output ) { $calendar_output = str_replace( '« ', is_rtl() ? twenty_twenty_one_get_icon_svg( 'ui', 'arrow_right' ) : twenty_twenty_one_get_icon_svg( 'ui', 'arrow_left' ), $calendar_output ); $calendar_output = str_replace( ' »', is_rtl() ? twenty_twenty_one_get_icon_svg( 'ui', 'arrow_left' ) : twenty_twenty_one_get_icon_svg( 'ui', 'arrow_right' ), $calendar_output ); return $calendar_output; } add_filter( 'get_calendar', 'twenty_twenty_one_change_calendar_nav_arrows' ); /** * Get custom CSS. * * Return CSS for non-latin language, if available, or null * * @since Twenty Twenty-One 1.0 * * @param string $type Whether to return CSS for the "front-end", "block-editor", or "classic-editor". * @return string */ function twenty_twenty_one_get_non_latin_css( $type = 'front-end' ) { // Fetch site locale. $locale = get_bloginfo( 'language' ); /** * Filters the fallback fonts for non-latin languages. * * @since Twenty Twenty-One 1.0 * * @param array $font_family An array of locales and font families. */ $font_family = apply_filters( 'twenty_twenty_one_get_localized_font_family_types', array( // Arabic. 'ar' => array( 'Tahoma', 'Arial', 'sans-serif' ), 'ary' => array( 'Tahoma', 'Arial', 'sans-serif' ), 'azb' => array( 'Tahoma', 'Arial', 'sans-serif' ), 'ckb' => array( 'Tahoma', 'Arial', 'sans-serif' ), 'fa-IR' => array( 'Tahoma', 'Arial', 'sans-serif' ), 'haz' => array( 'Tahoma', 'Arial', 'sans-serif' ), 'ps' => array( 'Tahoma', 'Arial', 'sans-serif' ), // Chinese Simplified (China) - Noto Sans SC. 'zh-CN' => array( '\'PingFang SC\'', '\'Helvetica Neue\'', '\'Microsoft YaHei New\'', '\'STHeiti Light\'', 'sans-serif' ), // Chinese Traditional (Taiwan) - Noto Sans TC. 'zh-TW' => array( '\'PingFang TC\'', '\'Helvetica Neue\'', '\'Microsoft YaHei New\'', '\'STHeiti Light\'', 'sans-serif' ), // Chinese (Hong Kong) - Noto Sans HK. 'zh-HK' => array( '\'PingFang HK\'', '\'Helvetica Neue\'', '\'Microsoft YaHei New\'', '\'STHeiti Light\'', 'sans-serif' ), // Cyrillic. 'bel' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'bg-BG' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'kk' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'mk-MK' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'mn' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'ru-RU' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'sah' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'sr-RS' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'tt-RU' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), 'uk' => array( '\'Helvetica Neue\'', 'Helvetica', '\'Segoe UI\'', 'Arial', 'sans-serif' ), // Devanagari. 'bn-BD' => array( 'Arial', 'sans-serif' ), 'hi-IN' => array( 'Arial', 'sans-serif' ), 'mr' => array( 'Arial', 'sans-serif' ), 'ne-NP' => array( 'Arial', 'sans-serif' ), // Greek. 'el' => array( '\'Helvetica Neue\', Helvetica, Arial, sans-serif' ), // Gujarati. 'gu' => array( 'Arial', 'sans-serif' ), // Hebrew. 'he-IL' => array( '\'Arial Hebrew\'', 'Arial', 'sans-serif' ), // Japanese. 'ja' => array( 'sans-serif' ), // Korean. 'ko-KR' => array( '\'Apple SD Gothic Neo\'', '\'Malgun Gothic\'', '\'Nanum Gothic\'', 'Dotum', 'sans-serif' ), // Thai. 'th' => array( '\'Sukhumvit Set\'', '\'Helvetica Neue\'', 'Helvetica', 'Arial', 'sans-serif' ), // Vietnamese. 'vi' => array( '\'Libre Franklin\'', 'sans-serif' ), ) ); // Return if the selected language has no fallback fonts. if ( empty( $font_family[ $locale ] ) ) { return ''; } /** * Filters the elements to apply fallback fonts to. * * @since Twenty Twenty-One 1.0 * * @param array $elements An array of elements for "front-end", "block-editor", or "classic-editor". */ $elements = apply_filters( 'twenty_twenty_one_get_localized_font_family_elements', array( 'front-end' => array( 'body', 'input', 'textarea', 'button', '.button', '.faux-button', '.wp-block-button__link', '.wp-block-file__button', '.has-drop-cap:not(:focus)::first-letter', '.entry-content .wp-block-archives', '.entry-content .wp-block-categories', '.entry-content .wp-block-cover-image', '.entry-content .wp-block-latest-comments', '.entry-content .wp-block-latest-posts', '.entry-content .wp-block-pullquote', '.entry-content .wp-block-quote.is-large', '.entry-content .wp-block-quote.is-style-large', '.entry-content .wp-block-archives *', '.entry-content .wp-block-categories *', '.entry-content .wp-block-latest-posts *', '.entry-content .wp-block-latest-comments *', '.entry-content p', '.entry-content ol', '.entry-content ul', '.entry-content dl', '.entry-content dt', '.entry-content cite', '.entry-content figcaption', '.entry-content .wp-caption-text', '.comment-content p', '.comment-content ol', '.comment-content ul', '.comment-content dl', '.comment-content dt', '.comment-content cite', '.comment-content figcaption', '.comment-content .wp-caption-text', '.widget_text p', '.widget_text ol', '.widget_text ul', '.widget_text dl', '.widget_text dt', '.widget-content .rssSummary', '.widget-content cite', '.widget-content figcaption', '.widget-content .wp-caption-text' ), 'block-editor' => array( '.editor-styles-wrapper > *', '.editor-styles-wrapper p', '.editor-styles-wrapper ol', '.editor-styles-wrapper ul', '.editor-styles-wrapper dl', '.editor-styles-wrapper dt', '.editor-post-title__block .editor-post-title__input', '.editor-styles-wrapper .wp-block h1', '.editor-styles-wrapper .wp-block h2', '.editor-styles-wrapper .wp-block h3', '.editor-styles-wrapper .wp-block h4', '.editor-styles-wrapper .wp-block h5', '.editor-styles-wrapper .wp-block h6', '.editor-styles-wrapper .has-drop-cap:not(:focus)::first-letter', '.editor-styles-wrapper cite', '.editor-styles-wrapper figcaption', '.editor-styles-wrapper .wp-caption-text' ), 'classic-editor' => array( 'body#tinymce.wp-editor', 'body#tinymce.wp-editor p', 'body#tinymce.wp-editor ol', 'body#tinymce.wp-editor ul', 'body#tinymce.wp-editor dl', 'body#tinymce.wp-editor dt', 'body#tinymce.wp-editor figcaption', 'body#tinymce.wp-editor .wp-caption-text', 'body#tinymce.wp-editor .wp-caption-dd', 'body#tinymce.wp-editor cite', 'body#tinymce.wp-editor table' ), ) ); // Return if the specified type doesn't exist. if ( empty( $elements[ $type ] ) ) { return ''; } // Include file if function doesn't exist. if ( ! function_exists( 'twenty_twenty_one_generate_css' ) ) { require_once get_theme_file_path( 'inc/custom-css.php' ); // phpcs:ignore WPThemeReview.CoreFunctionality.FileInclude.FileIncludeFound } // Return the specified styles. return twenty_twenty_one_generate_css( // @phpstan-ignore-line. implode( ',', $elements[ $type ] ), 'font-family', implode( ',', $font_family[ $locale ] ), null, null, false ); } /** * Print the first instance of a block in the content, and then break away. * * @since Twenty Twenty-One 1.0 * * @param string $block_name The full block type name, or a partial match. * Example: `core/image`, `core-embed/*`. * @param string|null $content The content to search in. Use null for get_the_content(). * @param int $instances How many instances of the block will be printed (max). Default 1. * @return bool Returns true if a block was located & printed, otherwise false. */ function twenty_twenty_one_print_first_instance_of_block( $block_name, $content = null, $instances = 1 ) { $instances_count = 0; $blocks_content = ''; if ( ! $content ) { $content = get_the_content(); } // Parse blocks in the content. $blocks = parse_blocks( $content ); // Loop blocks. foreach ( $blocks as $block ) { // Confidence check. if ( ! isset( $block['blockName'] ) ) { continue; } // Check if this the block matches the $block_name. $is_matching_block = false; // If the block ends with *, try to match the first portion. if ( '*' === $block_name[-1] ) { $is_matching_block = 0 === strpos( $block['blockName'], rtrim( $block_name, '*' ) ); } else { $is_matching_block = $block_name === $block['blockName']; } if ( $is_matching_block ) { // Increment count. ++$instances_count; // Add the block HTML. $blocks_content .= render_block( $block ); // Break the loop if the $instances count was reached. if ( $instances_count >= $instances ) { break; } } } if ( $blocks_content ) { /** This filter is documented in wp-includes/post-template.php */ echo apply_filters( 'the_content', $blocks_content ); // phpcs:ignore WordPress.Security.EscapeOutput return true; } return false; } /** * Retrieve protected post password form content. * * @since Twenty Twenty-One 1.0 * @since Twenty Twenty-One 1.4 Corrected parameter name for `$output`, * added the `$post` parameter. * * @param string $output The password form HTML output. * @param int|WP_Post $post Optional. Post ID or WP_Post object. Default is global $post. * @return string HTML content for password form for password protected post. */ function twenty_twenty_one_password_form( $output, $post = 0 ) { $post = get_post( $post ); $label = 'pwbox-' . ( empty( $post->ID ) ? wp_rand() : $post->ID ); $output = '

' . esc_html__( 'This content is password protected. Please enter a password to view.', 'twentytwentyone' ) . '

'; return $output; } add_filter( 'the_password_form', 'twenty_twenty_one_password_form', 10, 2 ); /** * Filters the list of attachment image attributes. * * @since Twenty Twenty-One 1.0 * * @param string[] $attr Array of attribute values for the image markup, keyed by attribute name. * See wp_get_attachment_image(). * @param WP_Post $attachment Image attachment post. * @param string|int[] $size Requested image size. Can be any registered image size name, or * an array of width and height values in pixels (in that order). * @return string[] The filtered attributes for the image markup. */ function twenty_twenty_one_get_attachment_image_attributes( $attr, $attachment, $size ) { if ( is_admin() ) { return $attr; } if ( isset( $attr['class'] ) && false !== strpos( $attr['class'], 'custom-logo' ) ) { return $attr; } $width = false; $height = false; if ( is_array( $size ) ) { $width = (int) $size[0]; $height = (int) $size[1]; } elseif ( $attachment && is_object( $attachment ) && $attachment->ID ) { $meta = wp_get_attachment_metadata( $attachment->ID ); if ( isset( $meta['width'] ) && isset( $meta['height'] ) ) { $width = (int) $meta['width']; $height = (int) $meta['height']; } } if ( $width && $height ) { // Add style. $attr['style'] = isset( $attr['style'] ) ? $attr['style'] : ''; $attr['style'] = 'width:100%;height:' . round( 100 * $height / $width, 2 ) . '%;max-width:' . $width . 'px;' . $attr['style']; } return $attr; } add_filter( 'wp_get_attachment_image_attributes', 'twenty_twenty_one_get_attachment_image_attributes', 10, 3 ); PK!>! back-compat.phpnu[

'; printf( /* translators: %s: WordPress Version. */ esc_html__( 'This theme requires WordPress 5.3 or newer. You are running version %s. Please upgrade.', 'twentytwentyone' ), esc_html( $GLOBALS['wp_version'] ) ); echo '

'; } /** * Prevents the Customizer from being loaded on WordPress versions prior to 5.3. * * @since Twenty Twenty-One 1.0 * * @global string $wp_version WordPress version. * * @return void */ function twenty_twenty_one_customize() { wp_die( sprintf( /* translators: %s: WordPress Version. */ esc_html__( 'This theme requires WordPress 5.3 or newer. You are running version %s. Please upgrade.', 'twentytwentyone' ), esc_html( $GLOBALS['wp_version'] ) ), '', array( 'back_link' => true, ) ); } add_action( 'load-customize.php', 'twenty_twenty_one_customize' ); /** * Prevents the Theme Preview from being loaded on WordPress versions prior to 5.3. * * @since Twenty Twenty-One 1.0 * * @global string $wp_version WordPress version. * * @return void */ function twenty_twenty_one_preview() { if ( isset( $_GET['preview'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification wp_die( sprintf( /* translators: %s: WordPress Version. */ esc_html__( 'This theme requires WordPress 5.3 or newer. You are running version %s. Please upgrade.', 'twentytwentyone' ), esc_html( $GLOBALS['wp_version'] ) ) ); } } add_action( 'template_redirect', 'twenty_twenty_one_preview' ); PK!kŴblock-patterns.phpnu[ array( 'label' => __( 'Featured', 'twentytwentytwo' ) ), 'footer' => array( 'label' => __( 'Footers', 'twentytwentytwo' ) ), 'header' => array( 'label' => __( 'Headers', 'twentytwentytwo' ) ), 'query' => array( 'label' => __( 'Query', 'twentytwentytwo' ) ), 'twentytwentytwo_pages' => array( 'label' => __( 'Pages', 'twentytwentytwo' ) ), ); /** * Filters the theme block pattern categories. * * @since Twenty Twenty-Two 1.0 * * @param array[] $block_pattern_categories { * An associative array of block pattern categories, keyed by category name. * * @type array[] $properties { * An array of block category properties. * * @type string $label A human-readable label for the pattern category. * } * } */ $block_pattern_categories = apply_filters( 'twentytwentytwo_block_pattern_categories', $block_pattern_categories ); foreach ( $block_pattern_categories as $name => $properties ) { if ( ! WP_Block_Pattern_Categories_Registry::get_instance()->is_registered( $name ) ) { register_block_pattern_category( $name, $properties ); } } $block_patterns = array( 'footer-default', 'footer-dark', 'footer-logo', 'footer-navigation', 'footer-title-tagline-social', 'footer-social-copyright', 'footer-navigation-copyright', 'footer-about-title-logo', 'footer-query-title-citation', 'footer-query-images-title-citation', 'footer-blog', 'general-subscribe', 'general-featured-posts', 'general-layered-images-with-duotone', 'general-wide-image-intro-buttons', 'general-large-list-names', 'general-video-header-details', 'general-list-events', 'general-two-images-text', 'general-image-with-caption', 'general-video-trailer', 'general-pricing-table', 'general-divider-light', 'general-divider-dark', 'header-default', 'header-large-dark', 'header-small-dark', 'header-image-background', 'header-image-background-overlay', 'header-with-tagline', 'header-text-only-green-background', 'header-text-only-salmon-background', 'header-title-and-button', 'header-text-only-with-tagline-black-background', 'header-logo-navigation-gray-background', 'header-logo-navigation-social-black-background', 'header-title-navigation-social', 'header-logo-navigation-offset-tagline', 'header-stacked', 'header-centered-logo', 'header-centered-logo-black-background', 'header-centered-title-navigation-social', 'header-title-and-button', 'hidden-404', 'hidden-bird', 'hidden-heading-and-bird', 'page-about-media-left', 'page-about-simple-dark', 'page-about-media-right', 'page-about-solid-color', 'page-about-links', 'page-about-links-dark', 'page-about-large-image-and-buttons', 'page-layout-image-and-text', 'page-layout-image-text-and-video', 'page-layout-two-columns', 'page-sidebar-poster', 'page-sidebar-grid-posts', 'page-sidebar-blog-posts', 'page-sidebar-blog-posts-right', 'query-default', 'query-simple-blog', 'query-grid', 'query-text-grid', 'query-image-grid', 'query-large-titles', 'query-irregular-grid', ); /** * Filters the theme block patterns. * * @since Twenty Twenty-Two 1.0 * * @param array $block_patterns List of block patterns by name. */ $block_patterns = apply_filters( 'twentytwentytwo_block_patterns', $block_patterns ); foreach ( $block_patterns as $block_pattern ) { $pattern_file = get_theme_file_path( '/inc/patterns/' . $block_pattern . '.php' ); register_block_pattern( 'twentytwentytwo/' . $block_pattern, require $pattern_file ); } } add_action( 'init', 'twentytwentytwo_register_block_patterns', 9 ); PK!ʺcustom-css.phpnu[ tags and can only be interpreted as CSS on the browser. * Using wp_strip_all_tags() here is sufficient escaping to avoid * malicious attempts to close and open a __( 'User not allowed to update items.', 'envato-market' ) ) ); } update_option( self::AJAX_ACTION, 'dismissed' ); wp_send_json_success(); } } if ( ! function_exists( 'envato_market_github' ) ) : /** * Envato_Market_Github Instance * * @since 1.0.0 * * @return Envato_Market_Github */ function envato_market_github() { return Envato_Market_Github::instance(); } endif; /** * Loads the main instance of Envato_Market_Github * * @since 1.0.0 */ add_action( 'after_setup_theme', 'envato_market_github', 99 ); endif; PK!ks((class-envato-market.phpnu[init_globals(); self::$_instance->init_includes(); self::$_instance->init_actions(); } return self::$_instance; } /** * A dummy constructor to prevent this class from being loaded more than once. * * @see Envato_Market::instance() * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function __construct() { /* We do nothing here! */ } /** * You cannot clone this class. * * @since 1.0.0 * @codeCoverageIgnore */ public function __clone() { _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'envato-market' ), '1.0.0' ); } /** * You cannot unserialize instances of this class. * * @since 1.0.0 * @codeCoverageIgnore */ public function __wakeup() { _doing_it_wrong( __FUNCTION__, __( 'Cheatin’ huh?', 'envato-market' ), '1.0.0' ); } /** * Setup the class globals. * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function init_globals() { $this->data = new stdClass(); $this->version = ENVATO_MARKET_VERSION; $this->slug = 'envato-market'; $this->option_name = self::sanitize_key( $this->slug ); $this->plugin_url = ENVATO_MARKET_URI; $this->plugin_path = ENVATO_MARKET_PATH; $this->page_url = ENVATO_MARKET_NETWORK_ACTIVATED ? network_admin_url( 'admin.php?page=' . $this->slug ) : admin_url( 'admin.php?page=' . $this->slug ); $this->data->admin = true; if ( defined('ENVATO_LOCAL_DEVELOPMENT') ) { $this->envato_api_domain = ENVATO_API_DOMAIN; $this->envato_api_headers = ENVATO_API_HEADERS; } else { $this->envato_api_headers = [ 'Authorization' => 'Bearer ' . $this->get_option( 'token' ) ]; $this->envato_api_domain = 'https://api.envato.com'; } } /** * Include required files. * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function init_includes() { require $this->plugin_path . '/inc/admin/class-envato-market-admin.php'; require $this->plugin_path . '/inc/admin/functions.php'; require $this->plugin_path . '/inc/class-envato-market-api.php'; require $this->plugin_path . '/inc/class-envato-market-items.php'; require $this->plugin_path . '/inc/class-envato-market-github.php'; } /** * Setup the hooks, actions and filters. * * @uses add_action() To add actions. * @uses add_filter() To add filters. * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function init_actions() { // Activate plugin. register_activation_hook( ENVATO_MARKET_CORE_FILE, array( $this, 'activate' ) ); // Deactivate plugin. register_deactivation_hook( ENVATO_MARKET_CORE_FILE, array( $this, 'deactivate' ) ); // Load the textdomain. add_action( 'init', array( $this, 'load_textdomain' ) ); // Load OAuth. add_action( 'init', array( $this, 'admin' ) ); // Load Upgrader. add_action( 'init', array( $this, 'items' ) ); } /** * Activate plugin. * * @since 1.0.0 * @codeCoverageIgnore */ public function activate() { self::set_plugin_state( true ); } /** * Deactivate plugin. * * @since 1.0.0 * @codeCoverageIgnore */ public function deactivate() { self::set_plugin_state( false ); } /** * Loads the plugin's translated strings. * * @since 1.0.0 * @codeCoverageIgnore */ public function load_textdomain() { load_plugin_textdomain( 'envato-market', false, ENVATO_MARKET_PATH . 'languages/' ); } /** * Sanitize data key. * * @since 1.0.0 * @access private * * @param string $key An alpha numeric string to sanitize. * @return string */ private function sanitize_key( $key ) { return preg_replace( '/[^A-Za-z0-9\_]/i', '', str_replace( array( '-', ':' ), '_', $key ) ); } /** * Recursively converts data arrays to objects. * * @since 1.0.0 * @access private * * @param array $array An array of data. * @return object */ private function convert_data( $array ) { foreach ( (array) $array as $key => $value ) { if ( is_array( $value ) ) { $array[ $key ] = self::convert_data( $value ); } } return (object) $array; } /** * Set the `is_plugin_active` option. * * This setting helps determine context. Since the plugin can be included in your theme root you * might want to hide the admin UI when the plugin is not activated and implement your own. * * @since 1.0.0 * @access private * * @param bool $value Whether or not the plugin is active. */ private function set_plugin_state( $value ) { self::set_option( 'is_plugin_active', $value ); } /** * Set option value. * * @since 1.0.0 * * @param string $name Option name. * @param mixed $option Option data. */ public function set_option( $name, $option ) { $options = self::get_options(); $name = self::sanitize_key( $name ); $options[ $name ] = esc_html( $option ); $this->set_options( $options ); } /** * Set option. * * @since 2.0.0 * * @param mixed $options Option data. */ public function set_options( $options ) { ENVATO_MARKET_NETWORK_ACTIVATED ? update_site_option( $this->option_name, $options ) : update_option( $this->option_name, $options ); } /** * Return the option settings array. * * @since 1.0.0 */ public function get_options() { return ENVATO_MARKET_NETWORK_ACTIVATED ? get_site_option( $this->option_name, array() ) : get_option( $this->option_name, array() ); } /** * Return a value from the option settings array. * * @since 1.0.0 * * @param string $name Option name. * @param mixed $default The default value if nothing is set. * @return mixed */ public function get_option( $name, $default = '' ) { $options = self::get_options(); $name = self::sanitize_key( $name ); return isset( $options[ $name ] ) ? $options[ $name ] : $default; } /** * Set data. * * @since 1.0.0 * * @param string $key Unique object key. * @param mixed $data Any kind of data. */ public function set_data( $key, $data ) { if ( ! empty( $key ) ) { if ( is_array( $data ) ) { $data = self::convert_data( $data ); } $key = self::sanitize_key( $key ); // @codingStandardsIgnoreStart $this->data->$key = $data; // @codingStandardsIgnoreEnd } } /** * Get data. * * @since 1.0.0 * * @param string $key Unique object key. * @return string|object */ public function get_data( $key ) { return isset( $this->data->$key ) ? $this->data->$key : ''; } /** * Return the plugin slug. * * @since 1.0.0 * * @return string */ public function get_slug() { return $this->slug; } /** * Return the plugin version number. * * @since 1.0.0 * * @return string */ public function get_version() { return $this->version; } /** * Return the plugin URL. * * @since 1.0.0 * * @return string */ public function get_plugin_url() { return $this->plugin_url; } /** * Return the plugin path. * * @since 1.0.0 * * @return string */ public function get_plugin_path() { return $this->plugin_path; } /** * Return the plugin page URL. * * @since 1.0.0 * * @return string */ public function get_page_url() { return $this->page_url; } /** * Return the option settings name. * * @since 1.0.0 * * @return string */ public function get_option_name() { return $this->option_name; } /** * Admin UI class. * * @since 1.0.0 * * @return Envato_Market_Admin */ public function admin() { return Envato_Market_Admin::instance(); } /** * Envato API class. * * @since 1.0.0 * * @return Envato_Market_API */ public function api() { return Envato_Market_API::instance(); } /** * Items class. * * @since 1.0.0 * * @return Envato_Market_Items */ public function items() { return Envato_Market_Items::instance(); } public function get_envato_api_domain() { return $this->envato_api_domain; } public function get_envato_api_headers() { return $this->envato_api_headers; } } endif; PK!G=-HCCclass-envato-market-items.phpnu[init_actions(); } return self::$_instance; } /** * A dummy constructor to prevent this class from being loaded more than once. * * @see Envato_Market_Items::instance() * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function __construct() { /* We do nothing here! */ } /** * You cannot clone this class. * * @since 1.0.0 * @codeCoverageIgnore */ public function __clone() { _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'envato-market' ), '1.0.0' ); } /** * You cannot unserialize instances of this class. * * @since 1.0.0 * @codeCoverageIgnore */ public function __wakeup() { _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'envato-market' ), '1.0.0' ); } /** * Setup the hooks, actions and filters. * * @uses add_action() To add actions. * @uses add_filter() To add filters. * * @since 1.0.0 */ public function init_actions() { // Check for theme & plugin updates. add_filter( 'http_request_args', array( $this, 'update_check' ), 5, 2 ); // Inject plugin updates into the response array. add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'update_plugins' ), 5, 1 ); add_filter( 'pre_set_transient_update_plugins', array( $this, 'update_plugins' ), 5, 1 ); // Inject theme updates into the response array. add_filter( 'pre_set_site_transient_update_themes', array( $this, 'update_themes' ), 1, 99999 ); add_filter( 'pre_set_transient_update_themes', array( $this, 'update_themes' ), 1, 99999 ); // Inject plugin information into the API calls. add_filter( 'plugins_api', array( $this, 'plugins_api' ), 10, 3 ); // Rebuild the saved theme data. add_action( 'after_switch_theme', array( $this, 'rebuild_themes' ) ); // Rebuild the saved plugin data. add_action( 'activated_plugin', array( $this, 'rebuild_plugins' ) ); add_action( 'deactivated_plugin', array( $this, 'rebuild_plugins' ) ); } /** * Get the premium plugins list. * * @since 1.0.0 * * @param string $group The plugin group. Options are 'purchased', 'active', 'installed', or 'install'. * @return array */ public function plugins( $group = '' ) { if ( ! empty( $group ) ) { if ( isset( self::$plugins[ $group ] ) ) { return self::$plugins[ $group ]; } else { return array(); } } return self::$plugins; } /** * Get the premium themes list. * * @since 1.0.0 * * @param string $group The theme group. Options are 'purchased', 'active', 'installed', or 'install'. * @return array */ public function themes( $group = '' ) { if ( ! empty( $group ) ) { if ( isset( self::$themes[ $group ] ) ) { return self::$themes[ $group ]; } else { return array(); } } return self::$themes; } /** * Get the list of WordPress plugins * * @since 1.0.0 * * @param bool $flush Forces a cache flush. Default is 'false'. * @return array */ public function wp_plugins( $flush = false ) { if ( empty( self::$wp_plugins ) || true === $flush ) { wp_cache_set( 'plugins', false, 'plugins' ); self::$wp_plugins = get_plugins(); } return self::$wp_plugins; } /** * Disables requests to the wp.org repository for premium themes. * * @since 1.0.0 * * @param array $request An array of HTTP request arguments. * @param string $url The request URL. * @return array */ public function update_check( $request, $url ) { // Theme update request. if ( false !== strpos( $url, '//api.wordpress.org/themes/update-check/1.1/' ) ) { /** * Excluded theme slugs that should never ping the WordPress API. * We don't need the extra http requests for themes we know are premium. */ self::set_themes(); $installed = self::$themes['installed']; // Decode JSON so we can manipulate the array. $data = json_decode( $request['body']['themes'] ); // Remove the excluded themes. foreach ( $installed as $slug => $id ) { unset( $data->themes->$slug ); } // Encode back into JSON and update the response. $request['body']['themes'] = wp_json_encode( $data ); } // Plugin update request. if ( false !== strpos( $url, '//api.wordpress.org/plugins/update-check/1.1/' ) ) { /** * Excluded theme slugs that should never ping the WordPress API. * We don't need the extra http requests for themes we know are premium. */ self::set_plugins(); $installed = self::$plugins['installed']; // Decode JSON so we can manipulate the array. $data = json_decode( $request['body']['plugins'] ); // Remove the excluded themes. foreach ( $installed as $slug => $id ) { unset( $data->plugins->$slug ); } // Encode back into JSON and update the response. $request['body']['plugins'] = wp_json_encode( $data ); } return $request; } /** * Inject update data for premium themes. * * @since 1.0.0 * * @param object $transient The pre-saved value of the `update_themes` site transient. * @return object */ public function update_themes( $transient ) { // Process premium theme updates. if ( isset( $transient->checked ) ) { self::set_themes( true ); $installed = array_merge( self::$themes['active'], self::$themes['installed'] ); foreach ( $installed as $slug => $premium ) { $theme = wp_get_theme( $slug ); if ( $theme->exists() && version_compare( $theme->get( 'Version' ), $premium['version'], '<' ) ) { $transient->response[ $slug ] = array( 'theme' => $slug, 'new_version' => $premium['version'], 'url' => $premium['url'], 'package' => envato_market()->api()->deferred_download( $premium['id'] ), ); } } } return $transient; } /** * Inject update data for premium plugins. * * @since 1.0.0 * * @param object $transient The pre-saved value of the `update_plugins` site transient. * @return object */ public function update_plugins( $transient ) { self::set_plugins( true ); // Process premium plugin updates. $installed = array_merge( self::$plugins['active'], self::$plugins['installed'] ); $plugins = self::wp_plugins(); foreach ( $installed as $plugin => $premium ) { if ( isset( $plugins[ $plugin ] ) && version_compare( $plugins[ $plugin ]['Version'], $premium['version'], '<' ) ) { $_plugin = array( 'slug' => dirname( $plugin ), 'plugin' => $plugin, 'new_version' => $premium['version'], 'url' => $premium['url'], 'package' => envato_market()->api()->deferred_download( $premium['id'] ), ); $transient->response[ $plugin ] = (object) $_plugin; } } return $transient; } /** * Inject API data for premium plugins. * * @since 1.0.0 * * @param bool $response Always false. * @param string $action The API action being performed. * @param object $args Plugin arguments. * @return bool|object $response The plugin info or false. */ public function plugins_api( $response, $action, $args ) { self::set_plugins( true ); // Process premium theme updates. if ( 'plugin_information' === $action && isset( $args->slug ) ) { $installed = array_merge( self::$plugins['active'], self::$plugins['installed'] ); foreach ( $installed as $slug => $plugin ) { if ( dirname( $slug ) === $args->slug ) { $response = new stdClass(); $response->slug = $args->slug; $response->plugin = $slug; $response->plugin_name = $plugin['name']; $response->name = $plugin['name']; $response->version = $plugin['version']; $response->author = $plugin['author']; $response->homepage = $plugin['url']; $response->requires = $plugin['requires']; $response->tested = $plugin['tested']; $response->downloaded = $plugin['number_of_sales']; $response->last_updated = $plugin['updated_at']; $response->sections = array( 'description' => $plugin['description'] ); $response->banners['low'] = $plugin['landscape_url']; $response->rating = ! empty( $plugin['rating'] ) && ! empty( $plugin['rating']['rating'] ) && $plugin['rating']['rating'] > 0 ? $plugin['rating']['rating'] / 5 * 100 : 0; $response->num_ratings = ! empty( $plugin['rating'] ) && ! empty( $plugin['rating']['count'] ) ? $plugin['rating']['count'] : 0; $response->download_link = envato_market()->api()->deferred_download( $plugin['id'] ); break; } } } return $response; } /** * Set the list of themes * * @since 1.0.0 * * @param bool $forced Forces an API request. Default is 'false'. * @param bool $use_cache Attempts to rebuild from the cache before making an API request. */ public function set_themes( $forced = false, $use_cache = false ) { $themes_transient = get_site_transient( envato_market()->get_option_name() . '_themes' ); self::$themes = is_array($themes_transient) ? $themes_transient : array(); if ( empty(self::$themes) || true === $forced ) { $themes = envato_market()->api()->themes(); foreach ( envato_market()->get_option( 'items', array() ) as $item ) { if ( empty( $item ) ) { continue; } if ( 'theme' === $item['type'] ) { $request_args = array( 'headers' => array( 'Authorization' => 'Bearer ' . $item['token'], ), ); $request = envato_market()->api()->item( $item['id'], $request_args ); if ( false !== $request ) { $themes[] = $request; } } } self::process_themes( $themes ); } elseif ( true === $use_cache ) { self::process_themes( self::$themes['purchased'] ); } } /** * Set the list of plugins * * @since 1.0.0 * * @param bool $forced Forces an API request. Default is 'false'. * @param bool $use_cache Attempts to rebuild from the cache before making an API request. * @param array $args Used to remove or add a plugin during activate and deactivate routines. */ public function set_plugins( $forced = false, $use_cache = false, $args = array() ) { $plugins_transient = get_site_transient( envato_market()->get_option_name() . '_plugins' ); self::$plugins = is_array($plugins_transient) ? $plugins_transient : array(); if ( empty(self::$plugins) || true === $forced ) { $plugins = envato_market()->api()->plugins(); foreach ( envato_market()->get_option( 'items', array() ) as $item ) { if ( empty( $item ) ) { continue; } if ( 'plugin' === $item['type'] ) { $request_args = array( 'headers' => array( 'Authorization' => 'Bearer ' . $item['token'], ), ); $request = envato_market()->api()->item( $item['id'], $request_args ); if ( false !== $request ) { $plugins[] = $request; } } } self::process_plugins( $plugins, $args ); } elseif ( true === $use_cache ) { self::process_plugins( self::$plugins['purchased'], $args ); } } /** * Rebuild the themes array using the cache value if possible. * * @since 1.0.0 * * @param mixed $filter Any data being filtered. * @return mixed */ public function rebuild_themes( $filter ) { self::set_themes( false, true ); return $filter; } /** * Rebuild the plugins array using the cache value if possible. * * @since 1.0.0 * * @param string $plugin The plugin to add or remove. */ public function rebuild_plugins( $plugin ) { $remove = ( 'deactivated_plugin' === current_filter() ) ? true : false; self::set_plugins( false, true, array( 'plugin' => $plugin, 'remove' => $remove, ) ); } /** * Normalizes a string to do a value check against. * * Strip all HTML tags including script and style & then decode the * HTML entities so `&` will equal `&` in the value check and * finally lower case the entire string. This is required becuase some * themes & plugins add a link to the Author field or ambersands to the * names, or change the case of their files or names, which will not match * the saved value in the database causing a false negative. * * @since 1.0.0 * * @param string $string The string to normalize. * @return string */ public function normalize( $string ) { return strtolower( html_entity_decode( wp_strip_all_tags( $string ) ) ); } /** * Process the themes and save the transient. * * @since 1.0.0 * * @param array $purchased The purchased themes array. */ private function process_themes( $purchased ) { if ( is_wp_error( $purchased ) ) { $purchased = array(); } $current = wp_get_theme()->get_template(); $active = array(); $installed = array(); $install = $purchased; if ( ! empty( $purchased ) ) { foreach ( wp_get_themes() as $theme ) { /** * WP_Theme object. * * @var WP_Theme $theme */ $template = $theme->get_template(); $title = $theme->get( 'Name' ); $author = $theme->get( 'Author' ); foreach ( $install as $key => $value ) { if ( $this->normalize( $value['name'] ) === $this->normalize( $title ) && $this->normalize( $value['author'] ) === $this->normalize( $author ) ) { $installed[ $template ] = $value; unset( $install[ $key ] ); } } } } if ( isset( $installed[ $current ] ) ) { $active[ $current ] = $installed[ $current ]; unset( $installed[ $current ] ); } self::$themes['purchased'] = array_unique( $purchased, SORT_REGULAR ); self::$themes['active'] = array_unique( $active, SORT_REGULAR ); self::$themes['installed'] = array_unique( $installed, SORT_REGULAR ); self::$themes['install'] = array_unique( array_values( $install ), SORT_REGULAR ); set_site_transient( envato_market()->get_option_name() . '_themes', self::$themes, HOUR_IN_SECONDS ); } /** * Process the plugins and save the transient. * * @since 1.0.0 * * @param array $purchased The purchased plugins array. * @param array $args Used to remove or add a plugin during activate and deactivate routines. */ private function process_plugins( $purchased, $args = array() ) { if ( is_wp_error( $purchased ) ) { $purchased = array(); } $active = array(); $installed = array(); $install = $purchased; if ( ! empty( $purchased ) ) { foreach ( self::wp_plugins( true ) as $slug => $plugin ) { foreach ( $install as $key => $value ) { if ( $this->normalize( $value['name'] ) === $this->normalize( $plugin['Name'] ) && $this->normalize( $value['author'] ) === $this->normalize( $plugin['Author'] ) && file_exists( WP_PLUGIN_DIR . '/' . $slug ) ) { $installed[ $slug ] = $value; unset( $install[ $key ] ); } } } } foreach ( $installed as $slug => $plugin ) { $condition = false; if ( ! empty( $args ) && $slug === $args['plugin'] ) { if ( true === $args['remove'] ) { continue; } $condition = true; } if ( $condition || is_plugin_active( $slug ) ) { $active[ $slug ] = $plugin; unset( $installed[ $slug ] ); } } self::$plugins['purchased'] = array_unique( $purchased, SORT_REGULAR ); self::$plugins['active'] = array_unique( $active, SORT_REGULAR ); self::$plugins['installed'] = array_unique( $installed, SORT_REGULAR ); self::$plugins['install'] = array_unique( array_values( $install ), SORT_REGULAR ); set_site_transient( envato_market()->get_option_name() . '_plugins', self::$plugins, HOUR_IN_SECONDS ); } } endif; PK!C(%admin/view/callback/section/oauth.phpnu[

' . esc_html__( 'envato.com', 'envato-market' ) . '' ); ?>

  1. admin()->get_generate_token_url() . '" target="_blank">' . esc_html__( 'clicking this link', 'envato-market' ) . '' ); ?>
PK!<U %admin/view/callback/section/items.phpnu[

PK!%admin/view/callback/setting/token.phpnu[

PK!YY%admin/view/callback/setting/items.phpnu[get_option( 'items', array() ); ?> PK!b  admin/view/callback/admin.phpnu[

downloads page' ); ?>

PK!&admin/view/notice/error-single-use.phpnu[

PK!c'8admin/view/notice/success.phpnu[

PK!WJKKadmin/view/notice/error.phpnu[

PK! admin/view/notice/error-http.phpnu[

PK!t ^//&admin/view/notice/success-no-items.phpnu[

PK!<w(admin/view/notice/success-single-use.phpnu[

PK!8T,,'admin/view/notice/error-permissions.phpnu[

    get_required_permissions() as $permission ) { ?>
PK!r_66#admin/view/notice/error-details.phpnu[

Additional Error Details:
%s.
%s
%s', esc_html( $title ), esc_html( $message ), esc_html( json_encode( $data ) ) ); ?>

PK!Ūadmin/view/partials/plugins.phpnu[items()->plugins( 'purchased' ); ?>
PK!(uadmin/view/partials/intro.phpnu[

get_version() ); ?>

', '' ); ?>

PK!a+ admin/view/partials/help.phpnu[

Troubleshooting:

If you’re having trouble with the plugin, please

  1. Confirm the old Envato Toolkit plugin is not installed.
  2. Confirm the latest version of WordPress is installed.
  3. Confirm the latest version of the Envato Market plugin is installed.
  4. Try creating a new API token has from the build.envato.com website - ensure only the following permissions have been granted
    • View and search Envato sites
    • Download your purchased items
    • List purchases you've made
  5. Check with the hosting provider to ensure the API connection to api.envato.com is not blocked.
  6. Check with the hosting provider that the minimum TLS version is 1.2 or above on the server.
  7. If you can’t see your items - check with the item author to confirm the Theme or Plugin is compatible with the Envato Market plugin.
  8. Confirm your Envato account is still active and the items are still visible from your downloads page.
  9. Note - if an item has been recently updated, it may take up to 24 hours for the latest version to appear in the Envato Market plugin.

Health Check:

Problem starting healthcheck. Please check javascript console for errors.

Support:

The Envato Market plugin is maintained - we ensure it works best on the latest version of WordPress and on a modern hosting platform, however we can’t guarantee it’ll work on all WordPress sites or hosting environments.

If you’ve tried all the troubleshooting steps and you’re still unable to get the Envato Market plugin to work on your site/hosting, at this time, our advice is to remove the Envato Market plugin and instead visit the Downloads section of ThemeForest/CodeCanyon to download the latest version of your items.

If you’re having trouble with a specific item from ThemeForest or CodeCanyon, it’s best you browse to the Theme or Plugin item page, visit the ‘support’ tab and follow the next steps.

PK!.Geadmin/view/partials/tabs.phpnu[items()->themes( 'purchased' ); $plugins = envato_market()->items()->plugins( 'purchased' ); ?> PK!1e admin/view/partials/settings.phpnu[get_option( 'token' ); $items = envato_market()->get_option( 'items', array() ); ?>
get_slug() ); ?> get_slug(), 2 ); ?>

PK!mHEadmin/view/partials/themes.phpnu[items()->themes( 'purchased' ); ?>
PK!5FF2admin/class-envato-market-theme-installer-skin.phpnu[upgrader->result['destination_name'] ) ) { return; } $theme_info = $this->upgrader->theme_info(); if ( empty( $theme_info ) ) { return; } $name = $theme_info->display( 'Name' ); $stylesheet = $this->upgrader->result['destination_name']; $template = $theme_info->get_template(); $activate_link = add_query_arg( array( 'action' => 'activate', 'template' => urlencode( $template ), 'stylesheet' => urlencode( $stylesheet ), ), admin_url( 'themes.php' ) ); $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $stylesheet ); $install_actions = array(); if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { $install_actions['preview'] = '' . sprintf( __( 'Live Preview “%s”', 'envato-market' ), $name ) . ''; } if ( is_multisite() ) { if ( current_user_can( 'manage_network_themes' ) ) { $install_actions['network_enable'] = '' . __( 'Network Enable', 'envato-market' ) . ''; } } $install_actions['activate'] = '' . sprintf( __( 'Activate “%s”', 'envato-market' ), $name ) . ''; $install_actions['themes_page'] = '' . __( 'Return to Theme Installer', 'envato-market' ) . ''; if ( ! $this->result || is_wp_error( $this->result ) || is_multisite() || ! current_user_can( 'switch_themes' ) ) { unset( $install_actions['activate'], $install_actions['preview'] ); } if ( ! empty( $install_actions ) ) { $this->feedback( implode( ' | ', $install_actions ) ); } } } endif; if ( ! class_exists( 'Envato_Market_Plugin_Installer_Skin' ) ) : /** * Plugin Installer Skin. * * @class Envato_Market_Plugin_Installer_Skin * @version 1.0.0 * @since 1.0.0 */ class Envato_Market_Plugin_Installer_Skin extends Plugin_Installer_Skin { /** * Modify the install actions. * * @since 1.0.0 */ public function after() { $plugin_file = $this->upgrader->plugin_info(); $install_actions = array(); if ( current_user_can( 'activate_plugins' ) ) { $install_actions['activate_plugin'] = '' . __( 'Activate Plugin', 'envato-market' ) . ''; } if ( is_multisite() ) { unset( $install_actions['activate_plugin'] ); if ( current_user_can( 'manage_network_plugins' ) ) { $install_actions['network_activate'] = '' . __( 'Network Activate', 'envato-market' ) . ''; } } $install_actions['plugins_page'] = '' . __( 'Return to Plugin Installer', 'envato-market' ) . ''; if ( ! $this->result || is_wp_error( $this->result ) ) { unset( $install_actions['activate_plugin'], $install_actions['site_activate'], $install_actions['network_activate'] ); } if ( ! empty( $install_actions ) ) { $this->feedback( implode( ' | ', $install_actions ) ); } } } endif; PK!\x+,admin/class-envato-market-theme-upgrader.phpnu[strings['downloading_package'] = __( 'Downloading the Envato Market upgrade package…', 'envato-market' ); } /** * Initialize the install strings. * * @since 1.0.0 */ public function install_strings() { parent::install_strings(); $this->strings['downloading_package'] = __( 'Downloading the Envato Market install package…', 'envato-market' ); } } endif; if ( ! class_exists( 'Envato_Market_Plugin_Upgrader' ) ) : /** * Extends the WordPress Plugin_Upgrader class. * * This class makes modifications to the strings during install & upgrade. * * @class Envato_Market_Plugin_Upgrader * @version 1.0.0 * @since 1.0.0 */ class Envato_Market_Plugin_Upgrader extends Plugin_Upgrader { /** * Initialize the upgrade strings. * * @since 1.0.0 */ public function upgrade_strings() { parent::upgrade_strings(); $this->strings['downloading_package'] = __( 'Downloading the Envato Market upgrade package…', 'envato-market' ); } /** * Initialize the install strings. * * @since 1.0.0 */ public function install_strings() { parent::install_strings(); $this->strings['downloading_package'] = __( 'Downloading the Envato Market install package…', 'envato-market' ); } } endif; PK!#admin/class-envato-market-admin.phpnu[init_actions(); } return self::$_instance; } /** * A dummy constructor to prevent this class from being loaded more than once. * * @see Envato_Market_Admin::instance() * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function __construct() { /* We do nothing here! */ } /** * You cannot clone this class. * * @since 1.0.0 * @codeCoverageIgnore */ public function __clone() { _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'envato-market' ), '1.0.0' ); } /** * You cannot unserialize instances of this class. * * @since 1.0.0 * @codeCoverageIgnore */ public function __wakeup() { _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'envato-market' ), '1.0.0' ); } /** * Setup the hooks, actions and filters. * * @uses add_action() To add actions. * @uses add_filter() To add filters. * * @since 1.0.0 */ public function init_actions() { // @codeCoverageIgnoreStart if ( false === envato_market()->get_data( 'admin' ) && false === envato_market()->get_option( 'is_plugin_active' ) ) { // Turns the UI off if allowed. return; } // @codeCoverageIgnoreEnd // Deferred Download. add_action( 'upgrader_package_options', array( $this, 'maybe_deferred_download' ), 9 ); // Add pre download filter to help with 3rd party plugin integration. add_filter( 'upgrader_pre_download', array( $this, 'upgrader_pre_download' ), 2, 4 ); // Add item AJAX handler. add_action( 'wp_ajax_' . self::AJAX_ACTION . '_add_item', array( $this, 'ajax_add_item' ) ); // Remove item AJAX handler. add_action( 'wp_ajax_' . self::AJAX_ACTION . '_remove_item', array( $this, 'ajax_remove_item' ) ); // Health check AJAX handler add_action( 'wp_ajax_' . self::AJAX_ACTION . '_healthcheck', array( $this, 'ajax_healthcheck' ) ); // Maybe delete the site transients. add_action( 'init', array( $this, 'maybe_delete_transients' ), 11 ); // Add the menu. add_action( 'admin_menu', array( $this, 'add_menu_page' ) ); // Register the settings. add_action( 'admin_init', array( $this, 'register_settings' ) ); // We may need to redirect after an item is enabled. add_action( 'current_screen', array( $this, 'maybe_redirect' ) ); // Add authorization notices. add_action( 'current_screen', array( $this, 'add_notices' ) ); // Set the API values. add_action( 'current_screen', array( $this, 'set_items' ) ); // Hook to verify the API token before saving it. add_filter( 'pre_update_option_' . envato_market()->get_option_name(), array( $this, 'check_api_token_before_saving', ), 9, 3 ); add_filter( 'pre_update_site_option_' . envato_market()->get_option_name(), array( $this, 'check_api_token_before_saving', ), 9, 3 ); // When network enabled, add the network options menu. add_action( 'network_admin_menu', array( $this, 'add_menu_page' ) ); // Ability to make use of the Settings API when in multisite mode. add_action( 'network_admin_edit_envato_market_network_settings', array( $this, 'save_network_settings' ) ); } /** * This runs before we save the Envato Market options array. * If the token has changed then we set a transient so we can do the update check. * * @param array $value The option to save. * @param array $old_value The old option value. * @param array $option Serialized option value. * * @return array $value The updated option value. * @since 2.0.1 */ public function check_api_token_before_saving( $value, $old_value, $option ) { if ( ! empty( $value['token'] ) && ( empty( $old_value['token'] ) || $old_value['token'] != $value['token'] || isset( $_POST['envato_market'] ) ) ) { set_site_transient( envato_market()->get_option_name() . '_check_token', $value['token'], HOUR_IN_SECONDS ); } return $value; } /** * Defers building the API download url until the last responsible moment to limit file requests. * * Filter the package options before running an update. * * @param array $options { * Options used by the upgrader. * * @type string $package Package for update. * @type string $destination Update location. * @type bool $clear_destination Clear the destination resource. * @type bool $clear_working Clear the working resource. * @type bool $abort_if_destination_exists Abort if the Destination directory exists. * @type bool $is_multi Whether the upgrader is running multiple times. * @type array $hook_extra Extra hook arguments. * } * @since 1.0.0 */ public function maybe_deferred_download( $options ) { $package = $options['package']; if ( false !== strrpos( $package, 'deferred_download' ) && false !== strrpos( $package, 'item_id' ) ) { parse_str( parse_url( $package, PHP_URL_QUERY ), $vars ); if ( $vars['item_id'] ) { $args = $this->set_bearer_args( $vars['item_id'] ); $options['package'] = envato_market()->api()->download( $vars['item_id'], $args ); } } return $options; } /** * We want to stop certain popular 3rd party scripts from blocking the update process by * adjusting the plugin name slightly so the 3rd party plugin checks stop. * * Currently works for: Visual Composer. * * @param string $reply Package URL. * @param string $package Package URL. * @param object $updater Updater Object. * * @return string $reply New Package URL. * @since 2.0.0 */ public function upgrader_pre_download( $reply, $package, $updater ) { if ( strpos( $package, 'marketplace.envato.com/short-dl' ) !== false ) { if ( isset( $updater->skin->plugin_info ) && ! empty( $updater->skin->plugin_info['Name'] ) ) { $updater->skin->plugin_info['Name'] = $updater->skin->plugin_info['Name'] . '.'; } else { $updater->skin->plugin_info = array( 'Name' => 'Name', ); } } return $reply; } /** * Returns the bearer arguments for a request with a single use API Token. * * @param int $id The item ID. * * @return array * @since 1.0.0 */ public function set_bearer_args( $id ) { $token = ''; $args = array(); foreach ( envato_market()->get_option( 'items', array() ) as $item ) { if ( absint( $item['id'] ) === absint( $id ) ) { $token = $item['token']; break; } } if ( ! empty( $token ) ) { $args = array( 'headers' => array( 'Authorization' => 'Bearer ' . $token, ), ); } return $args; } /** * Maybe delete the site transients. * * @since 1.0.0 * @codeCoverageIgnore */ public function maybe_delete_transients() { if ( isset( $_POST[ envato_market()->get_option_name() ] ) ) { // Nonce check. if ( isset( $_POST['_wpnonce'] ) && ! wp_verify_nonce( $_POST['_wpnonce'], envato_market()->get_slug() . '-options' ) ) { wp_die( __( 'You do not have sufficient permissions to delete transients.', 'envato-market' ) ); } self::delete_transients(); } elseif ( ! envato_market()->get_option( 'installed_version', 0 ) || version_compare( envato_market()->get_version(), envato_market()->get_option( 'installed_version', 0 ), '<' ) ) { // When the plugin updates we want to delete transients. envato_market()->set_option( 'installed_version', envato_market()->get_version() ); self::delete_transients(); } } /** * Delete the site transients. * * @since 1.0.0 * @access private */ private function delete_transients() { delete_site_transient( envato_market()->get_option_name() . '_themes' ); delete_site_transient( envato_market()->get_option_name() . '_plugins' ); } /** * Prints out all settings sections added to a particular settings page in columns. * * @param string $page The slug name of the page whos settings sections you want to output. * @param int $columns The number of columns in each row. * * @since 1.0.0 * * @global array $wp_settings_sections Storage array of all settings sections added to admin pages * @global array $wp_settings_fields Storage array of settings fields and info about their pages/sections */ public static function do_settings_sections( $page, $columns = 2 ) { global $wp_settings_sections, $wp_settings_fields; // @codeCoverageIgnoreStart if ( ! isset( $wp_settings_sections[ $page ] ) ) { return; } // @codeCoverageIgnoreEnd foreach ( (array) $wp_settings_sections[ $page ] as $section ) { // @codeCoverageIgnoreStart if ( ! isset( $wp_settings_fields ) || ! isset( $wp_settings_fields[ $page ] ) || ! isset( $wp_settings_fields[ $page ][ $section['id'] ] ) ) { continue; } // @codeCoverageIgnoreEnd // Set the column class. $class = 'envato-market-block'; ?>
' . esc_html( $section['title'] ) . '' . "\n"; } if ( ! empty( $section['callback'] ) ) { call_user_func( $section['callback'], $section ); } ?>
'; $page = add_menu_page( __( 'Envato Market', 'envato-market' ), __( 'Envato Market', 'envato-market' ), 'manage_options', envato_market()->get_slug(), array( $this, 'render_admin_callback', ), 'data:image/svg+xml;base64,' . base64_encode($svg_icon) ); // Enqueue admin CSS. add_action( 'admin_print_styles-' . $page, array( $this, 'admin_enqueue_style' ) ); // Enqueue admin JavaScript. add_action( 'admin_print_scripts-' . $page, array( $this, 'admin_enqueue_script' ) ); // Add Underscore.js templates. add_action( 'admin_footer-' . $page, array( $this, 'render_templates' ) ); } /** * Enqueue admin css. * * @since 1.0.0 */ public function admin_enqueue_style() { $file_url = envato_market()->get_plugin_url() . 'css/envato-market' . ( is_rtl() ? '-rtl' : '' ) . '.css'; wp_enqueue_style( envato_market()->get_slug(), $file_url, array( 'wp-jquery-ui-dialog' ), envato_market()->get_version() ); } /** * Enqueue admin script. * * @since 1.0.0 */ public function admin_enqueue_script() { $min = ( WP_DEBUG ? '' : '.min' ); $slug = envato_market()->get_slug(); $version = envato_market()->get_version(); $plugin_url = envato_market()->get_plugin_url(); wp_enqueue_script( $slug, $plugin_url . 'js/envato-market' . $min . '.js', array( 'jquery', 'jquery-ui-dialog', 'wp-util', ), $version, true ); wp_enqueue_script( $slug . '-updates', $plugin_url . 'js/updates' . $min . '.js', array( 'jquery', 'updates', 'wp-a11y', 'wp-util', ), $version, true ); // Script data array. $exports = array( 'nonce' => wp_create_nonce( self::AJAX_ACTION ), 'action' => self::AJAX_ACTION, 'i18n' => array( 'save' => __( 'Save', 'envato-market' ), 'remove' => __( 'Remove', 'envato-market' ), 'cancel' => __( 'Cancel', 'envato-market' ), 'error' => __( 'An unknown error occurred. Try again.', 'envato-market' ), ), ); // Export data to JS. wp_scripts()->add_data( $slug, 'data', sprintf( 'var _envatoMarket = %s;', wp_json_encode( $exports ) ) ); } /** * Underscore (JS) templates for dialog windows. * * @codeCoverageIgnore */ public function render_templates() { ?> get_slug(), envato_market()->get_option_name() ); // OAuth section. add_settings_section( envato_market()->get_option_name() . '_oauth_section', __( 'Getting Started (Simple)', 'envato-market' ), array( $this, 'render_oauth_section_callback' ), envato_market()->get_slug() ); // Token setting. add_settings_field( 'token', __( 'Token', 'envato-market' ), array( $this, 'render_token_setting_callback' ), envato_market()->get_slug(), envato_market()->get_option_name() . '_oauth_section' ); // Items section. add_settings_section( envato_market()->get_option_name() . '_items_section', __( 'Single Item Tokens (Advanced)', 'envato-market' ), array( $this, 'render_items_section_callback' ), envato_market()->get_slug() ); // Items setting. add_settings_field( 'items', __( 'Envato Market Items', 'envato-market' ), array( $this, 'render_items_setting_callback' ), envato_market()->get_slug(), envato_market()->get_option_name() . '_items_section' ); } /** * Redirect after the enable action runs. * * @since 1.0.0 * @codeCoverageIgnore */ public function maybe_redirect() { if ( $this->are_we_on_settings_page() ) { if ( ! empty( $_GET['action'] ) && 'install-theme' === $_GET['action'] && ! empty( $_GET['enabled'] ) ) { wp_safe_redirect( esc_url( envato_market()->get_page_url() ) ); exit; } } } /** * Add authorization notices. * * @since 1.0.0 */ public function add_notices() { if ( $this->are_we_on_settings_page() ) { // @codeCoverageIgnoreStart if ( get_site_transient( envato_market()->get_option_name() . '_check_token' ) || ( isset( $_GET['authorization'] ) && 'check' === $_GET['authorization'] ) ) { delete_site_transient( envato_market()->get_option_name() . '_check_token' ); self::authorization_redirect(); } // @codeCoverageIgnoreEnd // Get the option array. $option = envato_market()->get_options(); // Display success/error notices. if ( ! empty( $option['notices'] ) ) { self::delete_transients(); // Show succes notice. if ( isset( $option['notices']['success'] ) ) { add_action( ( ENVATO_MARKET_NETWORK_ACTIVATED ? 'network_' : '' ) . 'admin_notices', array( $this, 'render_success_notice', ) ); } // Show succes no-items notice. if ( isset( $option['notices']['success-no-items'] ) ) { add_action( ( ENVATO_MARKET_NETWORK_ACTIVATED ? 'network_' : '' ) . 'admin_notices', array( $this, 'render_success_no_items_notice', ) ); } // Show single-use succes notice. if ( isset( $option['notices']['success-single-use'] ) ) { add_action( ( ENVATO_MARKET_NETWORK_ACTIVATED ? 'network_' : '' ) . 'admin_notices', array( $this, 'render_success_single_use_notice', ) ); } // Show error notice. if ( isset( $option['notices']['error'] ) ) { add_action( ( ENVATO_MARKET_NETWORK_ACTIVATED ? 'network_' : '' ) . 'admin_notices', array( $this, 'render_error_notice', ) ); } // Show invalid permissions error notice. if ( isset( $option['notices']['error-permissions'] ) ) { add_action( ( ENVATO_MARKET_NETWORK_ACTIVATED ? 'network_' : '' ) . 'admin_notices', array( $this, 'render_error_permissions', ) ); } // Show single-use error notice. if ( isset( $option['notices']['error-single-use'] ) ) { add_action( ( ENVATO_MARKET_NETWORK_ACTIVATED ? 'network_' : '' ) . 'admin_notices', array( $this, 'render_error_single_use_notice', ) ); } // Show missing zip notice. if ( isset( $option['notices']['missing-package-zip'] ) ) { add_action( ( ENVATO_MARKET_NETWORK_ACTIVATED ? 'network_' : '' ) . 'admin_notices', array( $this, 'render_error_missing_zip', ) ); } // Show missing http connection error. if ( isset( $option['notices']['http_error'] ) ) { add_action( ( ENVATO_MARKET_NETWORK_ACTIVATED ? 'network_' : '' ) . 'admin_notices', array( $this, 'render_error_http', ) ); } // Update the saved data so the notice disappears on the next page load. unset( $option['notices'] ); envato_market()->set_options( $option ); } } } /** * Set the API values. * * @since 1.0.0 */ public function set_items() { if ( $this->are_we_on_settings_page() ) { envato_market()->items()->set_themes(); envato_market()->items()->set_plugins(); } } /** * Check if we're on the settings page. * * @since 2.0.0 * @access private */ private function are_we_on_settings_page() { return 'toplevel_page_' . envato_market()->get_slug() === get_current_screen()->id || 'toplevel_page_' . envato_market()->get_slug() . '-network' === get_current_screen()->id; } /** * Check for authorization and redirect. * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function authorization_redirect() { self::authorization(); wp_safe_redirect( esc_url( envato_market()->get_page_url() . '#settings' ) ); exit; } /** * Set the Envato API authorization value. * * @since 1.0.0 */ public function authorization() { // Get the option array. $option = envato_market()->get_options(); $option['notices'] = array(); // Check for global token. if ( envato_market()->get_option( 'token' ) || envato_market()->api()->token ) { $notice = 'success'; $scope_check = $this->authorize_token_permissions(); if ( 'http_error' === $scope_check ) { $notice = 'http_error'; } elseif ( 'error' === $this->authorize_total_items() || 'error' === $scope_check ) { $notice = 'error'; } else { if ( 'missing-permissions' == $scope_check ) { $notice = 'error-permissions'; } elseif ( 'too-many-permissions' === $scope_check ) { $notice = 'error-permissions'; } else { $themes_notice = $this->authorize_themes(); $plugins_notice = $this->authorize_plugins(); if ( 'error' === $themes_notice || 'error' === $plugins_notice ) { $notice = 'error'; } elseif ( 'success-no-themes' === $themes_notice && 'success-no-plugins' === $plugins_notice ) { $notice = 'success-no-items'; } } } $option['notices'][ $notice ] = true; } // Check for single-use token. if ( ! empty( $option['items'] ) ) { $failed = false; foreach ( $option['items'] as $key => $item ) { if ( empty( $item['name'] ) || empty( $item['token'] ) || empty( $item['id'] ) || empty( $item['type'] ) || empty( $item['authorized'] ) ) { continue; } $request_args = array( 'headers' => array( 'Authorization' => 'Bearer ' . $item['token'], ), ); // Uncached API response with single-use token. $response = envato_market()->api()->item( $item['id'], $request_args ); if ( ! is_wp_error( $response ) && isset( $response['id'] ) ) { $option['items'][ $key ]['authorized'] = 'success'; } else { if ( is_wp_error( $response ) ) { $this->store_additional_error_debug_information( 'Unable to query single item ID ' . $item['id'], $response->get_error_message(), $response->get_error_data() ); } $failed = true; $option['items'][ $key ]['authorized'] = 'failed'; } } if ( true === $failed ) { $option['notices']['error-single-use'] = true; } else { $option['notices']['success-single-use'] = true; } } // Set the option array. if ( ! empty( $option['notices'] ) ) { envato_market()->set_options( $option ); } } /** * Check that themes are authorized. * * @return bool * @since 1.0.0 */ public function authorize_total_items() { $domain = envato_market()->get_envato_api_domain(); $path = envato_market()->api()->api_path_for('total-items'); $url = $domain . $path; $response = envato_market()->api()->request( $url ); $notice = 'success'; if ( is_wp_error( $response ) ) { $notice = 'error'; $this->store_additional_error_debug_information( 'Failed to query total number of items in API response', $response->get_error_message(), $response->get_error_data() ); } elseif ( ! isset( $response['total-items'] ) ) { $notice = 'error'; $this->store_additional_error_debug_information( 'Incorrect response from API when querying total items' ); } return $notice; } /** * Get the required API permissions for this plugin to work. * * @single 2.0.1 * * @return array */ public function get_required_permissions() { return apply_filters( 'envato_market_required_permissions', array( 'default' => 'View and search Envato sites', 'purchase:download' => 'Download your purchased items', 'purchase:list' => 'List purchases you\'ve made', ) ); } /** * Return the URL a user needs to click to generate a personal token. * * @single 2.0.1 * * @return string The full URL to request a token. */ public function get_generate_token_url() { return 'https://build.envato.com/create-token/?' . implode( '&', array_map( function ( $val ) { return $val . '=t'; }, array_keys( $this->get_required_permissions() ) ) ); } /** * Check that themes are authorized. * * @return bool * @since 1.0.0 */ public function authorize_token_permissions() { if ( defined('ENVATO_LOCAL_DEVELOPMENT') ) { return 'success'; } $notice = 'success'; $response = envato_market()->api()->request( 'https://api.envato.com/whoami' ); if ( is_wp_error( $response ) && ( $response->get_error_code() === 'http_error' || $response->get_error_code() == 500 ) ) { $this->store_additional_error_debug_information( 'An error occured checking token permissions', $response->get_error_message(), $response->get_error_data() ); $notice = 'http_error'; } elseif ( is_wp_error( $response ) || ! isset( $response['scopes'] ) || ! is_array( $response['scopes'] ) ) { $this->store_additional_error_debug_information( 'No scopes found in API response message', $response->get_error_message(), $response->get_error_data() ); $notice = 'error'; } else { $minimum_scopes = $this->get_required_permissions(); $maximum_scopes = array( 'default' => 'Default' ) + $minimum_scopes; foreach ( $minimum_scopes as $required_scope => $required_scope_name ) { if ( ! in_array( $required_scope, $response['scopes'] ) ) { // The scope minimum required scope doesn't exist. $this->store_additional_error_debug_information( 'Could not find required API permission scope in output.', $required_scope ); $notice = 'missing-permissions'; } } foreach ( $response['scopes'] as $scope ) { if ( ! isset( $maximum_scopes[ $scope ] ) ) { // The available scope is outside our maximum bounds. $this->store_additional_error_debug_information( 'Found too many permissions on token.', $scope ); $notice = 'too-many-permissions'; } } } return $notice; } /** * Check that themes or plugins are authorized and downloadable. * * @param string $type The filter type, either 'themes' or 'plugins'. Default 'themes'. * * @return bool|null * @since 1.0.0 */ public function authorize_items( $type = 'themes' ) { $domain = envato_market()->get_envato_api_domain(); $path = envato_market()->api()->api_path_for('list-purchases'); $api_url = $domain . $path . '?filter_by=wordpress-' . $type; $response = envato_market()->api()->request( $api_url ); $notice = 'success'; if ( is_wp_error( $response ) ) { $notice = 'error'; $this->store_additional_error_debug_information( 'Error listing buyer purchases.', $response->get_error_message(), $response->get_error_data() ); } elseif ( empty( $response ) ) { $notice = 'error'; $this->store_additional_error_debug_information( 'Empty API result listing buyer purchases' ); } elseif ( empty( $response['results'] ) ) { $notice = 'success-no-' . $type; } else { shuffle( $response['results'] ); $item = array_shift( $response['results'] ); if ( ! isset( $item['item']['id'] ) || ! envato_market()->api()->download( $item['item']['id'] ) ) { $this->store_additional_error_debug_information( 'Failed to find the correct item format in API response' ); $notice = 'error'; } } return $notice; } /** * Check that themes are authorized. * * @return bool * @since 1.0.0 */ public function authorize_themes() { return $this->authorize_items( 'themes' ); } /** * Check that plugins are authorized. * * @return bool * @since 1.0.0 */ public function authorize_plugins() { return $this->authorize_items( 'plugins' ); } /** * Install plugin. * * @param string $plugin The plugin item ID. * * @since 1.0.0 * @codeCoverageIgnore */ public function install_plugin( $plugin ) { if ( ! current_user_can( 'install_plugins' ) ) { $msg = '

' . __( 'Installing Plugin...', 'envato-market' ) . '

' . __( 'You do not have sufficient permissions to install plugins on this site.', 'envato-market' ) . '

' . __( 'Return to Plugin Installer', 'envato-market' ) . '
'; wp_die( $msg ); } check_admin_referer( 'install-plugin_' . $plugin ); envato_market()->items()->set_plugins( true ); $install = envato_market()->items()->plugins( 'install' ); $api = new stdClass(); foreach ( $install as $value ) { if ( absint( $value['id'] ) === absint( $plugin ) ) { $api->name = $value['name']; $api->version = $value['version']; } } $array_api = (array) $api; if ( empty( $array_api ) ) { $msg = '

' . __( 'Installing Plugin...', 'envato-market' ) . '

' . __( 'An error occurred, please check that the item ID is correct.', 'envato-market' ) . '

' . __( 'Return to Plugin Installer', 'envato-market' ) . '
'; wp_die( $msg ); } $title = sprintf( __( 'Installing Plugin: %s', 'envato-market' ), esc_html( $api->name . ' ' . $api->version ) ); $nonce = 'install-plugin_' . $plugin; $url = 'admin.php?page=' . envato_market()->get_slug() . '&action=install-plugin&plugin=' . urlencode( $plugin ); $type = 'web'; // Install plugin type, From Web or an Upload. $api->download_link = envato_market()->api()->download( $plugin, $this->set_bearer_args( $plugin ) ); // Must have the upgrader & skin. require envato_market()->get_plugin_path() . '/inc/admin/class-envato-market-theme-upgrader.php'; require envato_market()->get_plugin_path() . '/inc/admin/class-envato-market-theme-installer-skin.php'; $upgrader = new Envato_Market_Plugin_Upgrader( new Envato_Market_Plugin_Installer_Skin( compact( 'title', 'url', 'nonce', 'plugin', 'api' ) ) ); $upgrader->install( $api->download_link ); } /** * Install theme. * * @param string $theme The theme item ID. * * @since 1.0.0 * @codeCoverageIgnore */ public function install_theme( $theme ) { if ( ! current_user_can( 'install_themes' ) ) { $msg = '

' . __( 'Installing Theme...', 'envato-market' ) . '

' . __( 'You do not have sufficient permissions to install themes on this site.', 'envato-market' ) . '

' . __( 'Return to Theme Installer', 'envato-market' ) . '
'; wp_die( $msg ); } check_admin_referer( 'install-theme_' . $theme ); envato_market()->items()->set_themes( true ); $install = envato_market()->items()->themes( 'install' ); $api = new stdClass(); foreach ( $install as $value ) { if ( absint( $value['id'] ) === absint( $theme ) ) { $api->name = $value['name']; $api->version = $value['version']; } } $array_api = (array) $api; if ( empty( $array_api ) ) { $msg = '

' . __( 'Installing Theme...', 'envato-market' ) . '

' . __( 'An error occurred, please check that the item ID is correct.', 'envato-market' ) . '

' . __( 'Return to Plugin Installer', 'envato-market' ) . '
'; wp_die( $msg ); } wp_enqueue_script( 'customize-loader' ); $title = sprintf( __( 'Installing Theme: %s', 'envato-market' ), esc_html( $api->name . ' ' . $api->version ) ); $nonce = 'install-theme_' . $theme; $url = 'admin.php?page=' . envato_market()->get_slug() . '&action=install-theme&theme=' . urlencode( $theme ); $type = 'web'; // Install theme type, From Web or an Upload. $api->download_link = envato_market()->api()->download( $theme, $this->set_bearer_args( $theme ) ); // Must have the upgrader & skin. require_once envato_market()->get_plugin_path() . '/inc/admin/class-envato-market-theme-upgrader.php'; require_once envato_market()->get_plugin_path() . '/inc/admin/class-envato-market-theme-installer-skin.php'; $upgrader = new Envato_Market_Theme_Upgrader( new Envato_Market_Theme_Installer_Skin( compact( 'title', 'url', 'nonce', 'api' ) ) ); $upgrader->install( $api->download_link ); } /** * AJAX handler for adding items that use a non global token. * * @since 1.0.0 * @codeCoverageIgnore */ public function ajax_add_item() { if ( ! check_ajax_referer( self::AJAX_ACTION, 'nonce', false ) ) { status_header( 400 ); wp_send_json_error( 'bad_nonce' ); } elseif ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) { status_header( 405 ); wp_send_json_error( 'bad_method' ); } elseif ( empty( $_POST['token'] ) ) { wp_send_json_error( array( 'message' => __( 'The Token is missing.', 'envato-market' ) ) ); } elseif ( empty( $_POST['id'] ) ) { wp_send_json_error( array( 'message' => __( 'The Item ID is missing.', 'envato-market' ) ) ); } elseif ( ! current_user_can( 'install_themes' ) || ! current_user_can( 'install_plugins' ) ) { wp_send_json_error( array( 'message' => __( 'User not allowed to install items.', 'envato-market' ) ) ); } $args = array( 'headers' => array( 'Authorization' => 'Bearer ' . $_POST['token'], ), ); $request = envato_market()->api()->item( $_POST['id'], $args ); if ( false === $request ) { wp_send_json_error( array( 'message' => __( 'The Token or Item ID is incorrect.', 'envato-market' ) ) ); } if ( false === envato_market()->api()->download( $_POST['id'], $args ) ) { wp_send_json_error( array( 'message' => __( 'The item cannot be downloaded.', 'envato-market' ) ) ); } if ( isset( $request['number_of_sales'] ) ) { $type = 'plugin'; } else { $type = 'theme'; } if ( isset( $type ) ) { $response = array( 'name' => $request['name'], 'token' => $_POST['token'], 'id' => $_POST['id'], 'type' => $type, 'authorized' => 'success', ); $options = get_option( envato_market()->get_option_name(), array() ); if ( ! empty( $options['items'] ) ) { $options['items'] = array_values( $options['items'] ); $key = count( $options['items'] ); } else { $options['items'] = array(); $key = 0; } $options['items'][] = $response; envato_market()->set_options( $options ); // Rebuild the theme cache. if ( 'theme' === $type ) { envato_market()->items()->set_themes( true, false ); $install_link = add_query_arg( array( 'page' => envato_market()->get_slug(), 'action' => 'install-theme', 'id' => $_POST['id'], ), self_admin_url( 'admin.php' ) ); $request['install'] = wp_nonce_url( $install_link, 'install-theme_' . $_POST['id'] ); } // Rebuild the plugin cache. if ( 'plugin' === $type ) { envato_market()->items()->set_plugins( true, false ); $install_link = add_query_arg( array( 'page' => envato_market()->get_slug(), 'action' => 'install-plugin', 'id' => $_POST['id'], ), self_admin_url( 'admin.php' ) ); $request['install'] = wp_nonce_url( $install_link, 'install-plugin_' . $_POST['id'] ); } $response['key'] = $key; $response['item'] = $request; wp_send_json_success( $response ); } wp_send_json_error( array( 'message' => __( 'An unknown error occurred.', 'envato-market' ) ) ); } /** * AJAX handler for removing items that use a non global token. * * @since 1.0.0 * @codeCoverageIgnore */ public function ajax_remove_item() { if ( ! check_ajax_referer( self::AJAX_ACTION, 'nonce', false ) ) { status_header( 400 ); wp_send_json_error( 'bad_nonce' ); } elseif ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) { status_header( 405 ); wp_send_json_error( 'bad_method' ); } elseif ( empty( $_POST['id'] ) ) { wp_send_json_error( array( 'message' => __( 'The Item ID is missing.', 'envato-market' ) ) ); } elseif ( ! current_user_can( 'delete_plugins' ) || ! current_user_can( 'delete_themes' ) ) { wp_send_json_error( array( 'message' => __( 'User not allowed to update items.', 'envato-market' ) ) ); } $options = get_option( envato_market()->get_option_name(), array() ); $type = ''; foreach ( $options['items'] as $key => $item ) { if ( $item['id'] === $_POST['id'] ) { $type = $item['type']; unset( $options['items'][ $key ] ); break; } } $options['items'] = array_values( $options['items'] ); envato_market()->set_options( $options ); // Rebuild the theme cache. if ( 'theme' === $type ) { envato_market()->items()->set_themes( true, false ); } // Rebuild the plugin cache. if ( 'plugin' === $type ) { envato_market()->items()->set_plugins( true, false ); } wp_send_json_success(); } /** * AJAX handler for performing a healthcheck of the current website. * * @since 2.0.6 * @codeCoverageIgnore */ public function ajax_healthcheck() { if ( ! check_ajax_referer( self::AJAX_ACTION, 'nonce', false ) ) { status_header( 400 ); wp_send_json_error( 'bad_nonce' ); } elseif ( 'POST' !== $_SERVER['REQUEST_METHOD'] ) { status_header( 405 ); wp_send_json_error( 'bad_method' ); } elseif ( ! current_user_can( 'install_themes' ) || ! current_user_can( 'install_plugins' ) ) { wp_send_json_error( array( 'message' => __( 'User not allowed to install items.', 'envato-market' ) ) ); } $limits = $this->get_server_limits(); wp_send_json_success( array( 'limits' => $limits ) ); } /** * AJAX handler for performing a healthcheck of the current website. * * @since 2.0.6 * @codeCoverageIgnore */ public function get_server_limits() { $limits = []; // Check memory limit is > 256 M try { $memory_limit = wp_convert_hr_to_bytes( ini_get( 'memory_limit' ) ); $memory_limit_desired = 256; $memory_limit_ok = $memory_limit < 0 || $memory_limit >= $memory_limit_desired * 1024 * 1024; $memory_limit_in_mb = $memory_limit < 0 ? 'Unlimited' : floor( $memory_limit / ( 1024 * 1024 ) ) . 'M'; $limits['memory_limit'] = [ 'title' => 'PHP Memory Limit', 'ok' => $memory_limit_ok, 'message' => $memory_limit_ok ? "is ok at {$memory_limit_in_mb}." : "{$memory_limit_in_mb} may be too small. If you are having issues please set your PHP memory limit to at least 256M - or ask your hosting provider to do this if you're unsure." ]; } catch ( \Exception $e ) { $limits['memory_limit'] = [ 'title' => 'PHP Memory Limit', 'ok' => false, 'message' => 'Failed to check memory limit. If you are having issues please ask hosting provider to raise the memory limit for you.' ]; } // Check upload size. try { $upload_size_desired = 80; $upload_max_filesize = wp_max_upload_size(); $upload_max_filesize_ok = $upload_max_filesize < 0 || $upload_max_filesize >= $upload_size_desired * 1024 * 1024; $upload_max_filesize_in_mb = $upload_max_filesize < 0 ? 'Unlimited' : floor( $upload_max_filesize / ( 1024 * 1024 ) ) . 'M'; $limits['upload'] = [ 'ok' => $upload_max_filesize_ok, 'title' => 'PHP Upload Limits', 'message' => $upload_max_filesize_ok ? "is ok at $upload_max_filesize_in_mb." : "$upload_max_filesize_in_mb may be too small. If you are having issues please set your PHP upload limits to at least {$upload_size_desired}M - or ask your hosting provider to do this if you're unsure.", ]; } catch ( \Exception $e ) { $limits['upload'] = [ 'title' => 'PHP Upload Limits', 'ok' => false, 'message' => 'Failed to check upload limit. If you are having issues please ask hosting provider to raise the upload limit for you.' ]; } // Check max_input_vars. try { $max_input_vars = ini_get( 'max_input_vars' ); $max_input_vars_desired = 1000; $max_input_vars_ok = $max_input_vars < 0 || $max_input_vars >= $max_input_vars_desired; $limits['max_input_vars'] = [ 'ok' => $max_input_vars_ok, 'title' => 'PHP Max Input Vars', 'message' => $max_input_vars_ok ? "is ok at $max_input_vars." : "$max_input_vars may be too small. If you are having issues please set your PHP max input vars to at least $max_input_vars_desired - or ask your hosting provider to do this if you're unsure.", ]; } catch ( \Exception $e ) { $limits['max_input_vars'] = [ 'title' => 'PHP Max Input Vars', 'ok' => false, 'message' => 'Failed to check input vars limit. If you are having issues please ask hosting provider to raise the input vars limit for you.' ]; } // Check max_execution_time. try { $max_execution_time = ini_get( 'max_execution_time' ); $max_execution_time_desired = 60; $max_execution_time_ok = $max_execution_time <= 0 || $max_execution_time >= $max_execution_time_desired; $limits['max_execution_time'] = [ 'ok' => $max_execution_time_ok, 'title' => 'PHP Execution Time', 'message' => $max_execution_time_ok ? "PHP execution time limit is ok at {$max_execution_time}." : "$max_execution_time is too small. Please set your PHP max execution time to at least $max_execution_time_desired - or ask your hosting provider to do this if you're unsure.", ]; } catch ( \Exception $e ) { $limits['max_execution_time'] = [ 'title' => 'PHP Execution Time', 'ok' => false, 'message' => 'Failed to check PHP execution time limit. Please ask hosting provider to raise this limit for you.' ]; } // Check various hostname connectivity. $hosts_to_check = array( array( 'hostname' => 'envato.github.io', 'url' => 'https://envato.github.io/wp-envato-market/dist/update-check.json', 'title' => 'Plugin Update API', ), array( 'hostname' => 'api.envato.com', 'url' => 'https://api.envato.com/ping', 'title' => 'Envato Market API', ), array( 'hostname' => 'marketplace.envato.com', 'url' => 'https://marketplace.envato.com/robots.txt', 'title' => 'Download API', ), ); foreach ( $hosts_to_check as $host ) { try { $response = wp_remote_get( $host['url'], [ 'user-agent' => 'WordPress - Envato Market ' . envato_market()->get_version(), 'timeout' => 5, ] ); $response_code = wp_remote_retrieve_response_code( $response ); if ( $response && ! is_wp_error( $response ) && $response_code === 200 ) { $limits[ $host['hostname'] ] = [ 'ok' => true, 'title' => $host['title'], 'message' => 'Connected ok.', ]; } else { $limits[ $host['hostname'] ] = [ 'ok' => false, 'title' => $host['title'], 'message' => "Connection failed. Status '$response_code'. Please ensure PHP is allowed to connect to the host '" . $host['hostname'] . "' - or ask your hosting provider to do this if you’re unsure. " . ( is_wp_error( $response ) ? $response->get_error_message() : '' ), ]; } } catch ( \Exception $e ) { $limits[ $host['hostname'] ] = [ 'ok' => true, 'title' => $host['title'], 'message' => "Connection failed. Please contact the hosting provider and ensure PHP is allowed to connect to the host '" . $host['hostname'] . "'. " . $e->getMessage(), ]; } } // Check authenticated API request if ( !defined('ENVATO_LOCAL_DEVELOPMENT') ) { $response = envato_market()->api()->request( 'https://api.envato.com/whoami' ); if ( is_wp_error( $response ) ) { $limits['authentication'] = [ 'ok' => false, 'title' => 'Envato API Authentication', 'message' => "Not currently authenticated with the Envato API. Please add your API token. " . $response->get_error_message(), ]; } elseif ( ! isset( $response['scopes'] ) ) { $limits['authentication'] = [ 'ok' => false, 'title' => 'Envato API Authentication', 'message' => "Missing API permissions. Please re-create your Envato API token with the correct permissions. ", ]; } else { $minimum_scopes = $this->get_required_permissions(); $maximum_scopes = array( 'default' => 'Default' ) + $minimum_scopes; $missing_scopes = array(); $additional_scopes = array(); foreach ( $minimum_scopes as $required_scope => $required_scope_name ) { if ( ! in_array( $required_scope, $response['scopes'] ) ) { // The scope minimum required scope doesn't exist. $missing_scopes [] = $required_scope; } } foreach ( $response['scopes'] as $scope ) { if ( ! isset( $maximum_scopes[ $scope ] ) ) { // The available scope is outside our maximum bounds. $additional_scopes [] = $scope; } } $limits['authentication'] = [ 'ok' => true, 'title' => 'Envato API Authentication', 'message' => "Authenticated successfully with correct scopes: " . implode( ', ', $response['scopes'] ), ]; } } $debug_enabled = defined( 'WP_DEBUG' ) && WP_DEBUG; $limits['wp_debug'] = [ 'ok' => ! $debug_enabled, 'title' => 'WP Debug', 'message' => $debug_enabled ? 'If you’re on a production website, it’s best to set WP_DEBUG to false, please ask your hosting provider to do this if you’re unsure.' : 'WP Debug is disabled, all ok.', ]; $zip_archive_installed = class_exists( '\ZipArchive' ); $limits['zip_archive'] = [ 'ok' => $zip_archive_installed, 'title' => 'ZipArchive Support', 'message' => $zip_archive_installed ? 'ZipArchive is available.' : 'ZipArchive is not available. If you have issues installing or updating items please ask your hosting provider to enable ZipArchive.', ]; $php_version_ok = version_compare( PHP_VERSION, '7.0', '>=' ); $limits['php_version'] = [ 'ok' => $php_version_ok, 'title' => 'PHP Version', 'message' => $php_version_ok ? 'PHP version is ok at ' . PHP_VERSION . '.' : 'Please ask the hosting provider to upgrade your PHP version to at least 7.0 or above.', ]; require_once( ABSPATH . 'wp-admin/includes/file.php' ); $current_filesystem_method = get_filesystem_method(); if ( $current_filesystem_method !== 'direct' ) { $limits['filesystem_method'] = [ 'ok' => false, 'title' => 'WordPress Filesystem', 'message' => 'Please enable WordPress FS_METHOD direct - or ask your hosting provider to do this if you’re unsure.', ]; } $wp_upload_dir = wp_upload_dir(); $upload_base_dir = $wp_upload_dir['basedir']; $upload_base_dir_writable = is_writable( $upload_base_dir ); $limits['wp_content_writable'] = [ 'ok' => $upload_base_dir_writable, 'title' => 'WordPress File Permissions', 'message' => $upload_base_dir_writable ? 'is ok.' : 'Please set correct WordPress PHP write permissions for the wp-content directory - or ask your hosting provider to do this if you’re unsure.', ]; $active_plugins = get_option( 'active_plugins' ); $active_plugins_ok = count( $active_plugins ) < 15; if ( ! $active_plugins_ok ) { $limits['active_plugins'] = [ 'ok' => false, 'title' => 'Active Plugins', 'message' => 'Please try to reduce the number of active plugins on your WordPress site, as this will slow things down.', ]; } return $limits; } /** * Admin page callback. * * @since 1.0.0 */ public function render_admin_callback() { require( envato_market()->get_plugin_path() . 'inc/admin/view/callback/admin.php' ); } /** * OAuth section callback. * * @since 1.0.0 */ public function render_oauth_section_callback() { require( envato_market()->get_plugin_path() . 'inc/admin/view/callback/section/oauth.php' ); } /** * Items section callback. * * @since 1.0.0 */ public function render_items_section_callback() { require( envato_market()->get_plugin_path() . 'inc/admin/view/callback/section/items.php' ); } /** * Token setting callback. * * @since 1.0.0 */ public function render_token_setting_callback() { require( envato_market()->get_plugin_path() . 'inc/admin/view/callback/setting/token.php' ); } /** * Items setting callback. * * @since 1.0.0 */ public function render_items_setting_callback() { require( envato_market()->get_plugin_path() . 'inc/admin/view/callback/setting/items.php' ); } /** * Intro * * @since 1.0.0 */ public function render_intro_partial() { require( envato_market()->get_plugin_path() . 'inc/admin/view/partials/intro.php' ); } /** * Tabs * * @since 1.0.0 */ public function render_tabs_partial() { require( envato_market()->get_plugin_path() . 'inc/admin/view/partials/tabs.php' ); } /** * Settings panel * * @since 1.0.0 */ public function render_settings_panel_partial() { require( envato_market()->get_plugin_path() . 'inc/admin/view/partials/settings.php' ); } /** * Help panel * * @since 2.0.1 */ public function render_help_panel_partial() { require( envato_market()->get_plugin_path() . 'inc/admin/view/partials/help.php' ); } /** * Themes panel * * @since 1.0.0 */ public function render_themes_panel_partial() { require( envato_market()->get_plugin_path() . 'inc/admin/view/partials/themes.php' ); } /** * Plugins panel * * @since 1.0.0 */ public function render_plugins_panel_partial() { require( envato_market()->get_plugin_path() . 'inc/admin/view/partials/plugins.php' ); } /** * Success notice. * * @since 1.0.0 */ public function render_success_notice() { require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/success.php' ); } /** * Success no-items notice. * * @since 1.0.0 */ public function render_success_no_items_notice() { require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/success-no-items.php' ); } /** * Success single-use notice. * * @since 1.0.0 */ public function render_success_single_use_notice() { require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/success-single-use.php' ); } /** * Error details. * * @since 2.0.2 */ public function render_additional_error_details() { $error_details = get_site_transient( envato_market()->get_option_name() . '_error_information' ); if ( $error_details && ! empty( $error_details['title'] ) ) { extract( $error_details ); require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/error-details.php' ); } } /** * Error notice. * * @since 1.0.0 */ public function render_error_notice() { require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/error.php' ); $this->render_additional_error_details(); } /** * Permission error notice. * * @since 2.0.1 */ public function render_error_permissions() { require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/error-permissions.php' ); $this->render_additional_error_details(); } /** * Error single-use notice. * * @since 1.0.0 */ public function render_error_single_use_notice() { require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/error-single-use.php' ); $this->render_additional_error_details(); } /** * Error missing zip. * * @since 2.0.1 */ public function render_error_missing_zip() { require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/error-missing-zip.php' ); $this->render_additional_error_details(); } /** * Error http * * @since 2.0.1 */ public function render_error_http() { require( envato_market()->get_plugin_path() . 'inc/admin/view/notice/error-http.php' ); $this->render_additional_error_details(); } /** * Use the Settings API when in network mode. * * This allows us to make use of the same WordPress Settings API when displaying the menu item in network mode. * * @since 2.0.0 */ public function save_network_settings() { check_admin_referer( envato_market()->get_slug() . '-options' ); global $new_whitelist_options; $options = $new_whitelist_options[ envato_market()->get_slug() ]; foreach ( $options as $option ) { if ( isset( $_POST[ $option ] ) ) { update_site_option( $option, $_POST[ $option ] ); } else { delete_site_option( $option ); } } wp_redirect( envato_market()->get_page_url() ); exit; } /** * Store additional error information in transient so users can self debug. * * @since 2.0.2 */ public function store_additional_error_debug_information( $title, $message = '', $data = [] ) { set_site_transient( envato_market()->get_option_name() . '_error_information', [ 'title' => $title, 'message' => $message, 'data' => $data, ], 120 ); } } endif; PK!Ԅ?A?Aadmin/functions.phpnu[items()->themes( $group ); if ( empty( $premium ) ) { return; } foreach ( $premium as $slug => $theme ) : $name = $theme['name']; $author = $theme['author']; $version = $theme['version']; $description = $theme['description']; $url = $theme['url']; $author_url = $theme['author_url']; $theme['hasUpdate'] = false; if ( 'active' === $group || 'installed' === $group ) { $get_theme = wp_get_theme( $slug ); if ( $get_theme->exists() ) { $name = $get_theme->get( 'Name' ); $author = $get_theme->get( 'Author' ); $version = $get_theme->get( 'Version' ); $description = $get_theme->get( 'Description' ); $author_url = $get_theme->get( 'AuthorURI' ); if ( version_compare( $version, $theme['version'], '<' ) ) { $theme['hasUpdate'] = true; } } } // Setup the column CSS classes. $classes = array( 'envato-card', 'theme' ); if ( 'active' === $group ) { $classes[] = 'active'; } // Setup the update action links. $update_actions = array(); if ( true === $theme['hasUpdate'] ) { $classes[] = 'update'; $classes[] = 'envato-card-' . esc_attr( $slug ); if ( current_user_can( 'update_themes' ) ) { // Upgrade link. $upgrade_link = add_query_arg( array( 'action' => 'upgrade-theme', 'theme' => esc_attr( $slug ), ), self_admin_url( 'update.php' ) ); $update_actions['update'] = sprintf( '%6$s', wp_nonce_url( $upgrade_link, 'upgrade-theme_' . $slug ), esc_attr__( 'Update %s now', 'envato-market' ), esc_attr( $name ), esc_attr( $slug ), esc_attr( $theme['version'] ), esc_html__( 'Update Available', 'envato-market' ) ); $update_actions['details'] = sprintf( '%3$s', esc_url( $url ), esc_attr( $name ), sprintf( __( 'View version %1$s details.', 'envato-market' ), $theme['version'] ) ); } } // Setup the action links. $actions = array(); if ( 'active' === $group && current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { // Customize theme. $customize_url = admin_url( 'customize.php' ); $customize_url .= '?theme=' . urlencode( $slug ); $customize_url .= '&return=' . urlencode( envato_market()->get_page_url() . '#themes' ); $actions['customize'] = '' . sprintf( __( 'Customize “%s”', 'envato-market' ), $name ) . ''; } elseif ( 'installed' === $group ) { $can_activate = true; // @codeCoverageIgnoreStart // Multisite needs special attention. if ( is_multisite() && ! $get_theme->is_allowed( 'both' ) && current_user_can( 'manage_sites' ) ) { $can_activate = false; if ( current_user_can( 'manage_network_themes' ) ) { $actions['network_enable'] = '' . sprintf( __( 'Network Enable “%s”', 'envato-market' ), $name ) . ''; } } // @codeCoverageIgnoreEnd // Can activate theme. if ( $can_activate && current_user_can( 'switch_themes' ) ) { $activate_link = add_query_arg( array( 'action' => 'activate', 'stylesheet' => urlencode( $slug ), ), admin_url( 'themes.php' ) ); $activate_link = wp_nonce_url( $activate_link, 'switch-theme_' . $slug ); // Activate link. $actions['activate'] = '' . sprintf( __( 'Activate “%s”', 'envato-market' ), $name ) . ''; // Preview theme. if ( current_user_can( 'edit_theme_options' ) && current_user_can( 'customize' ) ) { $preview_url = admin_url( 'customize.php' ); $preview_url .= '?theme=' . urlencode( $slug ); $preview_url .= '&return=' . urlencode( envato_market()->get_page_url() . '#themes' ); $actions['customize_preview'] = '' . sprintf( __( 'Live Preview “%s”', 'envato-market' ), $name ) . ''; } } } elseif ( 'install' === $group && current_user_can( 'install_themes' ) ) { // Install link. $install_link = add_query_arg( array( 'page' => envato_market()->get_slug(), 'action' => 'install-theme', 'id' => $theme['id'], ), self_admin_url( 'admin.php' ) ); $actions['install'] = ' ' . sprintf( __( 'Install %s', 'envato-market' ), $name ) . ' '; } if ( 0 === strrpos( html_entity_decode( $author ), '' . esc_html( $author ) . ''; } ?>
$count > 0 ? ( $rating / 5 * 100 ) : 0, 'type' => 'percent', 'number' => $count, ) ); } else { wp_star_rating( array( 'rating' => $theme['rating'] > 0 ? ( $theme['rating'] / 5 * 100 ) : 0, 'type' => 'percent', ) ); } } ?>
items()->plugins( $group ); if ( empty( $premium ) ) { return; } $plugins = envato_market()->items()->wp_plugins(); foreach ( $premium as $slug => $plugin ) : $name = $plugin['name']; $author = $plugin['author']; $version = $plugin['version']; $description = $plugin['description']; $url = $plugin['url']; $author_url = $plugin['author_url']; $plugin['hasUpdate'] = false; // Setup the column CSS classes. $classes = array( 'envato-card', 'plugin' ); if ( 'active' === $group ) { $classes[] = 'active'; } // Setup the update action links. $update_actions = array(); // Check for an update. if ( isset( $plugins[ $slug ] ) && version_compare( $plugins[ $slug ]['Version'], $plugin['version'], '<' ) ) { $plugin['hasUpdate'] = true; $classes[] = 'update'; $classes[] = 'envato-card-' . sanitize_key( dirname( $slug ) ); if ( current_user_can( 'update_plugins' ) ) { // Upgrade link. $upgrade_link = add_query_arg( array( 'action' => 'upgrade-plugin', 'plugin' => $slug, ), self_admin_url( 'update.php' ) ); // Details link. $details_link = add_query_arg( array( 'action' => 'upgrade-plugin', 'tab' => 'plugin-information', 'plugin' => dirname( $slug ), 'section' => 'changelog', 'TB_iframe' => 'true', 'width' => 640, 'height' => 662, ), self_admin_url( 'plugin-install.php' ) ); $update_actions['update'] = sprintf( '%7$s', wp_nonce_url( $upgrade_link, 'upgrade-plugin_' . $slug ), esc_attr__( 'Update %s now', 'envato-market' ), esc_attr( $name ), esc_attr( $slug ), sanitize_key( dirname( $slug ) ), esc_attr( $version ), esc_html__( 'Update Available', 'envato-market' ) ); $update_actions['details'] = sprintf( '%3$s', esc_url( $details_link ), esc_attr( $name ), sprintf( __( 'View version %1$s details.', 'envato-market' ), $version ) ); } } // Setup the action links. $actions = array(); if ( 'active' === $group ) { // Deactivate link. $deactivate_link = add_query_arg( array( 'action' => 'deactivate', 'plugin' => $slug, ), self_admin_url( 'plugins.php' ) ); $actions['deactivate'] = ' ' . sprintf( __( 'Deactivate %s', 'envato-market' ), $name ) . ' '; } elseif ( 'installed' === $group ) { if ( ! is_multisite() && current_user_can( 'delete_plugins' ) ) { // Delete link. $delete_link = add_query_arg( array( 'action' => 'delete-selected', 'checked[]' => $slug, ), self_admin_url( 'plugins.php' ) ); $actions['delete'] = ' ' . sprintf( __( 'Delete %s', 'envato-market' ), $name ) . ' '; } if ( ! is_multisite() && current_user_can( 'activate_plugins' ) ) { // Activate link. $activate_link = add_query_arg( array( 'action' => 'activate', 'plugin' => $slug, ), self_admin_url( 'plugins.php' ) ); $actions['activate'] = ' ' . sprintf( __( 'Activate %s', 'envato-market' ), $name ) . ' '; } // @codeCoverageIgnoreStart // Multisite needs special attention. if ( is_multisite() ) { if ( current_user_can( 'manage_network_plugins' ) ) { $actions['network_activate'] = ' ' . sprintf( __( 'Network Activate %s', 'envato-market' ), $name ) . ' '; } } // @codeCoverageIgnoreEnd } elseif ( 'install' === $group && current_user_can( 'install_plugins' ) ) { // Install link. $install_link = add_query_arg( array( 'page' => envato_market()->get_slug(), 'action' => 'install-plugin', 'id' => $plugin['id'], ), self_admin_url( 'admin.php' ) ); $actions['install'] = ' ' . sprintf( __( 'Install %s', 'envato-market' ), $name ) . ' '; } if ( 0 === strrpos( html_entity_decode( $author ), '' . esc_html( $author ) . ''; } ?>
$plugin['rating']['rating'] > 0 ? ( $plugin['rating']['rating'] / 5 * 100 ) : 0, 'type' => 'percent', 'number' => $plugin['rating']['count'], ) ); } else { wp_star_rating( array( 'rating' => $plugin['rating'] > 0 ? ( $plugin['rating'] / 5 * 100 ) : 0, 'type' => 'percent', ) ); } } ?>
init_globals(); } return self::$_instance; } /** * A dummy constructor to prevent this class from being loaded more than once. * * @see Envato_Market_API::instance() * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function __construct() { /* We do nothing here! */ } /** * You cannot clone this class. * * @since 1.0.0 * @codeCoverageIgnore */ public function __clone() { _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'envato-market' ), '1.0.0' ); } /** * You cannot unserialize instances of this class. * * @since 1.0.0 * @codeCoverageIgnore */ public function __wakeup() { _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'envato-market' ), '1.0.0' ); } /** * Setup the class globals. * * @since 1.0.0 * @access private * @codeCoverageIgnore */ private function init_globals() { // Envato API token. $this->token = envato_market()->get_option( 'token' ); } /** * Query the Envato API. * * @uses wp_remote_get() To perform an HTTP request. * * @since 1.0.0 * * @param string $url API request URL, including the request method, parameters, & file type. * @param array $args The arguments passed to `wp_remote_get`. * @return array|WP_Error The HTTP response. */ public function request( $url, $args = array() ) { $defaults = array( 'sslverify' => !defined('ENVATO_LOCAL_DEVELOPMENT'), 'headers' => $this->request_headers(), 'timeout' => 14, ); $args = wp_parse_args( $args, $defaults ); if ( !defined('ENVATO_LOCAL_DEVELOPMENT') ) { $token = trim( str_replace( 'Bearer', '', $args['headers']['Authorization'] ) ); if ( empty( $token ) ) { return new WP_Error( 'api_token_error', __( 'An API token is required.', 'envato-market' ) ); } } $debugging_information = [ 'request_url' => $url, ]; // Make an API request. $response = wp_remote_get( esc_url_raw( $url ), $args ); // Check the response code. $response_code = wp_remote_retrieve_response_code( $response ); $response_message = wp_remote_retrieve_response_message( $response ); $debugging_information['response_code'] = $response_code; $debugging_information['response_cf_ray'] = wp_remote_retrieve_header( $response, 'cf-ray' ); $debugging_information['response_server'] = wp_remote_retrieve_header( $response, 'server' ); if ( ! empty( $response->errors ) && isset( $response->errors['http_request_failed'] ) ) { // API connectivity issue, inject notice into transient with more details. $option = envato_market()->get_options(); if ( empty( $option['notices'] ) ) { $option['notices'] = []; } $option['notices']['http_error'] = current( $response->errors['http_request_failed'] ); envato_market()->set_options( $option ); return new WP_Error( 'http_error', esc_html( current( $response->errors['http_request_failed'] ) ), $debugging_information ); } if ( 200 !== $response_code && ! empty( $response_message ) ) { return new WP_Error( $response_code, $response_message, $debugging_information ); } elseif ( 200 !== $response_code ) { return new WP_Error( $response_code, __( 'An unknown API error occurred.', 'envato-market' ), $debugging_information ); } else { $return = json_decode( wp_remote_retrieve_body( $response ), true ); if ( null === $return ) { return new WP_Error( 'api_error', __( 'An unknown API error occurred.', 'envato-market' ), $debugging_information ); } return $return; } } /** * Deferred item download URL. * * @since 1.0.0 * * @param int $id The item ID. * @return string. */ public function deferred_download( $id ) { if ( empty( $id ) ) { return ''; } $args = array( 'deferred_download' => true, 'item_id' => $id, ); return add_query_arg( $args, esc_url( envato_market()->get_page_url() ) ); } /** * Get the item download. * * @since 1.0.0 * * @param int $id The item ID. * @param array $args The arguments passed to `wp_remote_get`. * @return bool|array The HTTP response. */ public function download( $id, $args = array() ) { if ( empty( $id ) ) { return false; } $domain = envato_market()->get_envato_api_domain(); $path = $this->api_path_for('download'); $url = $domain . $path . '?item_id=' . $id . '&shorten_url=true'; $response = $this->request( $url, $args ); // @todo Find out which errors could be returned & handle them in the UI. if ( is_wp_error( $response ) || empty( $response ) || ! empty( $response['error'] ) ) { return false; } if ( ! empty( $response['wordpress_theme'] ) ) { return $response['wordpress_theme']; } if ( ! empty( $response['wordpress_plugin'] ) ) { return $response['wordpress_plugin']; } // Missing a WordPress theme and plugin, report an error. $option = envato_market()->get_options(); if ( ! isset( $option['notices'] ) ) { $option['notices'] = []; } $option['notices']['missing-package-zip'] = true; envato_market()->set_options( $option ); return false; } /** * Get an item by ID and type. * * @since 1.0.0 * * @param int $id The item ID. * @param array $args The arguments passed to `wp_remote_get`. * @return array The HTTP response. */ public function item( $id, $args = array() ) { $domain = envato_market()->get_envato_api_domain(); $path = $this->api_path_for('catalog-item'); $url = $domain . $path . '?id=' . $id; $response = $this->request( $url, $args ); if ( is_wp_error( $response ) || empty( $response ) ) { return false; } if ( ! empty( $response['wordpress_theme_metadata'] ) ) { return $this->normalize_theme( $response ); } if ( ! empty( $response['wordpress_plugin_metadata'] ) ) { return $this->normalize_plugin( $response ); } return false; } /** * Get the list of available themes. * * @since 1.0.0 * * @param array $args The arguments passed to `wp_remote_get`. * @return array The HTTP response. */ public function themes( $args = array() ) { $themes = array(); $domain = envato_market()->get_envato_api_domain(); $path = $this->api_path_for('list-purchases'); $url = $domain . $path . '?filter_by=wordpress-themes'; $response = $this->request( $url, $args ); if ( is_wp_error( $response ) || empty( $response ) || empty( $response['results'] ) ) { return $themes; } foreach ( $response['results'] as $theme ) { $themes[] = $this->normalize_theme( $theme['item'] ); } return $themes; } /** * Normalize a theme. * * @since 1.0.0 * * @param array $theme An array of API request values. * @return array A normalized array of values. */ public function normalize_theme( $theme ) { $normalized_theme = array( 'id' => $theme['id'], 'name' => ( ! empty( $theme['wordpress_theme_metadata']['theme_name'] ) ? $theme['wordpress_theme_metadata']['theme_name'] : '' ), 'author' => ( ! empty( $theme['wordpress_theme_metadata']['author_name'] ) ? $theme['wordpress_theme_metadata']['author_name'] : '' ), 'version' => ( ! empty( $theme['wordpress_theme_metadata']['version'] ) ? $theme['wordpress_theme_metadata']['version'] : '' ), 'description' => self::remove_non_unicode( strip_tags( $theme['wordpress_theme_metadata']['description'] ) ), 'url' => ( ! empty( $theme['url'] ) ? $theme['url'] : '' ), 'author_url' => ( ! empty( $theme['author_url'] ) ? $theme['author_url'] : '' ), 'thumbnail_url' => ( ! empty( $theme['thumbnail_url'] ) ? $theme['thumbnail_url'] : '' ), 'rating' => ( ! empty( $theme['rating'] ) ? $theme['rating'] : '' ), 'landscape_url' => '', ); // No main thumbnail in API response, so we grab it from the preview array. if ( empty( $normalized_theme['thumbnail_url'] ) && ! empty( $theme['previews'] ) && is_array( $theme['previews'] ) ) { foreach ( $theme['previews'] as $possible_preview ) { if ( ! empty( $possible_preview['landscape_url'] ) ) { $normalized_theme['landscape_url'] = $possible_preview['landscape_url']; break; } } } if ( empty( $normalized_theme['thumbnail_url'] ) && ! empty( $theme['previews'] ) && is_array( $theme['previews'] ) ) { foreach ( $theme['previews'] as $possible_preview ) { if ( ! empty( $possible_preview['icon_url'] ) ) { $normalized_theme['thumbnail_url'] = $possible_preview['icon_url']; break; } } } return $normalized_theme; } /** * Get the list of available plugins. * * @since 1.0.0 * * @param array $args The arguments passed to `wp_remote_get`. * @return array The HTTP response. */ public function plugins( $args = array() ) { $plugins = array(); $domain = envato_market()->get_envato_api_domain(); $path = $this->api_path_for('list-purchases'); $url = $domain . $path . '?filter_by=wordpress-plugins'; $response = $this->request( $url, $args ); if ( is_wp_error( $response ) || empty( $response ) || empty( $response['results'] ) ) { return $plugins; } foreach ( $response['results'] as $plugin ) { $plugins[] = $this->normalize_plugin( $plugin['item'] ); } return $plugins; } /** * Normalize a plugin. * * @since 1.0.0 * * @param array $plugin An array of API request values. * @return array A normalized array of values. */ public function normalize_plugin( $plugin ) { $requires = null; $tested = null; $versions = array(); // Set the required and tested WordPress version numbers. foreach ( $plugin['attributes'] as $k => $v ) { if ( ! empty( $v['name'] ) && 'compatible-software' === $v['name'] && ! empty( $v['value'] ) && is_array( $v['value'] ) ) { foreach ( $v['value'] as $version ) { $versions[] = str_replace( 'WordPress ', '', trim( $version ) ); } if ( ! empty( $versions ) ) { $requires = $versions[ count( $versions ) - 1 ]; $tested = $versions[0]; } break; } } $plugin_normalized = array( 'id' => $plugin['id'], 'name' => ( ! empty( $plugin['wordpress_plugin_metadata']['plugin_name'] ) ? $plugin['wordpress_plugin_metadata']['plugin_name'] : '' ), 'author' => ( ! empty( $plugin['wordpress_plugin_metadata']['author'] ) ? $plugin['wordpress_plugin_metadata']['author'] : '' ), 'version' => ( ! empty( $plugin['wordpress_plugin_metadata']['version'] ) ? $plugin['wordpress_plugin_metadata']['version'] : '' ), 'description' => self::remove_non_unicode( strip_tags( $plugin['wordpress_plugin_metadata']['description'] ) ), 'url' => ( ! empty( $plugin['url'] ) ? $plugin['url'] : '' ), 'author_url' => ( ! empty( $plugin['author_url'] ) ? $plugin['author_url'] : '' ), 'thumbnail_url' => ( ! empty( $plugin['thumbnail_url'] ) ? $plugin['thumbnail_url'] : '' ), 'landscape_url' => ( ! empty( $plugin['previews']['landscape_preview']['landscape_url'] ) ? $plugin['previews']['landscape_preview']['landscape_url'] : '' ), 'requires' => $requires, 'tested' => $tested, 'number_of_sales' => ( ! empty( $plugin['number_of_sales'] ) ? $plugin['number_of_sales'] : '' ), 'updated_at' => ( ! empty( $plugin['updated_at'] ) ? $plugin['updated_at'] : '' ), 'rating' => ( ! empty( $plugin['rating'] ) ? $plugin['rating'] : '' ), ); // No main thumbnail in API response, so we grab it from the preview array. if ( empty( $plugin_normalized['landscape_url'] ) && ! empty( $plugin['previews'] ) && is_array( $plugin['previews'] ) ) { foreach ( $plugin['previews'] as $possible_preview ) { if ( ! empty( $possible_preview['landscape_url'] ) ) { $plugin_normalized['landscape_url'] = $possible_preview['landscape_url']; break; } } } if ( empty( $plugin_normalized['thumbnail_url'] ) && ! empty( $plugin['previews'] ) && is_array( $plugin['previews'] ) ) { foreach ( $plugin['previews'] as $possible_preview ) { if ( ! empty( $possible_preview['icon_url'] ) ) { $plugin_normalized['thumbnail_url'] = $possible_preview['icon_url']; break; } } } return $plugin_normalized; } public function api_path_for( $path ) { if ( defined('ENVATO_LOCAL_DEVELOPMENT') ) { $paths = MONOLITH_API_PATHS; } else { $paths = array( 'download' => '/v2/market/buyer/download', 'catalog-item' => '/v2/market/catalog/item', 'list-purchases' => '/v2/market/buyer/list-purchases', 'total-items' => '/v1/market/total-items.json' ); } return $paths[$path]; } /** * Remove all non unicode characters in a string * * @since 1.0.0 * * @param string $retval The string to fix. * @return string */ static private function remove_non_unicode( $retval ) { return preg_replace( '/[\x00-\x1F\x80-\xFF]/', '', $retval ); } private function request_headers() { $user_agent = array('User-Agent' => 'WordPress - Envato Market ' . envato_market()->get_version()); $headers = array_merge($user_agent, envato_market()->get_envato_api_headers()); return $headers; } } endif; PK! f block-styles.phpnu[PK!zsdd template-tags.phpnu[PK!#;EEn'template-functions.phpnu[PK!>! lback-compat.phpnu[PK!kŴvblock-patterns.phpnu[PK!ʺcustom-css.phpnu[PK!Ҽmenu-functions.phpnu[PK!j""starter-content.phpnu[PK!t class-wpseo-replace-vars.phpnu[PK!UDDwpseo-functions-deprecated.phpnu[PK!+~E&&.interface-wpseo-wordpress-ajax-integration.phpnu[PK!5$$wpseo-functions.phpnu[PK!ע&& Uindex.phpnu[PK!kLyOOclass-upgrade.phpnu[PK!Dclass-wpseo-statistics.phpnu[PK![1class-wpseo-meta.phpnu[PK!M\\!class-wpseo-custom-taxonomies.phpnu[PK!Ω | | "class-wpseo-content-images.phpnu[PK!h?EhEh|-class-addon-manager.phpnu[PK!1%6 6 class-upgrade-history.phpnu[PK!7class-wpseo-custom-fields.phpnu[PK!\ssclass-wpseo-installation.phpnu[PK!9 r ryclass-wpseo-utils.phpnu[PK!~VQQ class-rewrite.phpnu[PK!7Ullp?class-wpseo-shortlinker.phpnu[PK! ]<]<'Dclass-wpseo-image-utils.phpnu[PK!Ydπdate-helper.phpnu[PK!: class-yoast-dynamic-rewrites.phpnu[PK!$~!!'language-utils.phpnu[PK! 2exceptions/class-myyoast-bad-request-exception.phpnu[PK!)3exceptions/class-myyoast-invalid-json-exception.phpnu[PK!+/FF%options/class-wpseo-option-titles.phpnu[PK!hoo|.options/class-wpseo-option.phpnu[PK!U D Doptions/class-wpseo-options.phpnu[PK! #cEcE%+options/class-wpseo-taxonomy-meta.phpnu[PK!G TT$(options/class-wpseo-option-wpseo.phpnu[PK!NvA $$!S}options/class-wpseo-option-ms.phpnu[PK!gk$k$%options/class-wpseo-option-social.phpnu[PK!ywHi%i%$Isitemaps/class-sitemaps-renderer.phpnu[PK!2^RR*sitemaps/class-author-sitemap-provider.phpnu[PK!?##'sitemaps/interface-sitemap-provider.phpnu[PK![s..',sitemaps/class-sitemap-image-parser.phpnu[PK!4l!!!76sitemaps/class-sitemaps-cache.phpnu[PK!o>%Wsitemaps/class-sitemap-cache-data.phpnu[PK!%vCACAjsitemaps/class-sitemaps.phpnu[PK!)|sitemaps/interface-sitemap-cache-data.phpnu[PK!?MM-sitemaps/class-post-type-sitemap-provider.phpnu[PK!-I !sitemaps/class-sitemaps-admin.phpnu[PK!I$$, sitemaps/class-taxonomy-sitemap-provider.phpnu[PK!j"0sitemaps/class-sitemaps-router.phpnu[PK!0e%%+Bsitemaps/class-sitemaps-cache-validator.phpnu[PK!99wpseo-non-ajax-functions.phpnu[PK!6e*Vclass-wpseo-rank.phpnu[PK!f\\)P interface-wpseo-wordpress-integration.phpnu[PK!gJ class-my-yoast-api-request.phpnu[PK!l>gc c m( patterns/page-sidebar-poster.phpnu[PK!Ҋ332 6 patterns/header-centered-logo-black-background.phpnu[PK!sp\(; patterns/footer-query-title-citation.phpnu[PK!4'(D patterns/footer-navigation-copyright.phpnu[PK!SY2I patterns/header-logo-navigation-offset-tagline.phpnu[PK!1'bSS*P patterns/page-sidebar-blog-posts-right.phpnu[PK!=Fe patterns/header-stacked.phpnu[PK!G|ek patterns/header-default.phpnu[PK!>d@ q patterns/general-list-events.phpnu[PK!!3}nn patterns/query-grid.phpnu[PK!q{Q߷$ patterns/page-layout-two-columns.phpnu[PK!E\\ patterns/query-simple-blog.phpnu[PK!24] patterns/header-centered-title-navigation-social.phpnu[PK!f!f!!x patterns/query-irregular-grid.phpnu[PK!NN./ patterns/header-text-only-green-background.phpnu[PK!vS patterns/hidden-404.phpnu[PK!-1i i # patterns/page-about-media-right.phpnu[PK!PYY" patterns/page-about-links-dark.phpnu[PK!j patterns/general-subscribe.phpnu[PK!϶ - patterns/general-wide-image-intro-buttons.phpnu[PK!ނà/w patterns/header-text-only-salmon-background.phpnu[PK!bEE!{ patterns/header-centered-logo.phpnu[PK!x$ patterns/footer-social-copyright.phpnu[PK!F,Q(" patterns/footer-title-tagline-social.phpnu[PK!n__$) patterns/page-sidebar-grid-posts.phpnu[PK!4|b{{: patterns/query-image-grid.phpnu[PK! ^ kB patterns/header-large-dark.phpnu[PK!2r r $M patterns/header-image-background.phpnu[PK!w3vW patterns/header-logo-navigation-gray-background.phpnu[PK!+W  #q] patterns/page-about-simple-dark.phpnu[PK!rr#j patterns/general-featured-posts.phpnu[PK!LL L ,o patterns/header-image-background-overlay.phpnu[PK!"u@y patterns/footer-logo.phpnu[PK! $} patterns/header-title-and-button.phpnu[PK!lou patterns/page-about-links.phpnu[PK!030 patterns/general-layered-images-with-duotone.phpnu[PK!1yh> patterns/footer-default.phpnu[PK!QenA A  patterns/header-small-dark.phpnu[PK!|B  patterns/footer-blog.phpnu[PK! "* patterns/general-divider-light.phpnu[PK!-B$ $ / patterns/footer-query-images-title-citation.phpnu[PK!q,h ) patterns/general-video-header-details.phpnu[PK!u8 " patterns/page-about-media-left.phpnu[PK!1k^ patterns/footer-dark.phpnu[PK!Q; patterns/header-logo-navigation-social-black-background.phpnu[PK!+ݗ" patterns/general-video-trailer.phpnu[PK!/7.. patterns/query-text-grid.phpnu[PK!N<$! patterns/hidden-heading-and-bird.phpnu[PK!q) patterns/hidden-bird.phpnu[PK!v܌!Xq patterns/general-divider-dark.phpnu[PK!\ #5u patterns/page-about-solid-color.phpnu[PK!g 'h patterns/page-layout-image-and-text.phpnu[PK!? $ patterns/general-two-images-text.phpnu[PK!0K11/Ɩ patterns/page-about-large-image-and-buttons.phpnu[PK!*rx V svg-icons.phpnu[PK!''' class-envato-market-github.phpnu[PK!ks(( class-envato-market.phpnu[PK!G=-HCCk class-envato-market-items.phpnu[PK!C(%hD admin/view/callback/section/oauth.phpnu[PK!<U %J admin/view/callback/section/items.phpnu[PK!% M admin/view/callback/setting/token.phpnu[PK!YY%N admin/view/callback/setting/items.phpnu[PK!b  V admin/view/callback/admin.phpnu[PK!u'Z admin/view/notice/error-missing-zip.phpnu[PK!&\ admin/view/notice/error-single-use.phpnu[PK!c'8T^ admin/view/notice/success.phpnu[PK!WJKK_ admin/view/notice/error.phpnu[PK! "a admin/view/notice/error-http.phpnu[PK!t ^//&Sc admin/view/notice/success-no-items.phpnu[PK!<w(d admin/view/notice/success-single-use.phpnu[PK!8T,,''f admin/view/notice/error-permissions.phpnu[PK!r_66#h admin/view/notice/error-details.phpnu[PK!Ū3j admin/view/partials/plugins.phpnu[PK!(uXl admin/view/partials/intro.phpnu[PK!a+ ^p admin/view/partials/help.phpnu[PK!.Ge+{ admin/view/partials/tabs.phpnu[PK!1e K admin/view/partials/settings.phpnu[PK!mHE admin/view/partials/themes.phpnu[PK!5FF2 admin/class-envato-market-theme-installer-skin.phpnu[PK!\x+,N admin/class-envato-market-theme-upgrader.phpnu[PK!#} admin/class-envato-market-admin.phpnu[PK!Ԅ?A?A admin/functions.phpnu[PK!.,99 class-envato-market-api.phpnu[PKH:S