Make WordPress Core


Ignore:
Timestamp:
10/20/2023 07:33:59 PM (14 months ago)
Author:
joemcgill
Message:

Themes: Make caches for block patterns clearable.

In [56765], theme block pattern files were cached to a transient as a performance enhancement. However, transients are not easily clearable when caches are flushed on environments not using a persistent cache, which can lead to errors if the theme files are renamed, edited, or moved.

This changes the caching mechanism to use wp_cache_set() instead, and caches these values to the global group so they are still persistent on environments using an object cache, and will be cleared by a cache flush.

In addition, the helper _wp_get_block_patterns has been moved WP_Theme::get_block_patterns for consistency with other block related theme methods and cache helpers for these values, WP_Theme::get_pattern_cache and WP_Theme::set_pattern_cache, have been made private.

Relevant unit tests updated.

Props afercia, flixos90, mukesh27, joemcgill.
Merges [56978] to the 6.4 branch.
Fixes #59633. See #59591, #59490.

Location:
branches/6.4
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • branches/6.4

    • Property svn:mergeinfo changed
      /trunk (added)merged: 56978
  • branches/6.4/src/wp-includes/class-wp-theme.php

    r56943 r56979  
    846846
    847847    /**
    848      * Gets block pattern cache.
    849      *
    850      * @since 6.4.0
    851      *
    852      * @return array|false Returns an array of patterns if cache is found, otherwise false.
    853      */
    854     public function get_pattern_cache() {
    855         if ( ! $this->exists() ) {
    856             return false;
    857         }
    858         $pattern_data = get_transient( 'wp_theme_patterns_' . $this->stylesheet );
    859         if ( is_array( $pattern_data ) && $pattern_data['version'] === $this->get( 'Version' ) ) {
    860             return $pattern_data['patterns'];
    861         }
    862         return false;
    863     }
    864 
    865     /**
    866      * Sets block pattern cache.
    867      *
    868      * @since 6.4.0
    869      *
    870      * @param array $patterns Block patterns data to set in cache.
    871      */
    872     public function set_pattern_cache( array $patterns ) {
    873         $pattern_data = array(
    874             'version'  => $this->get( 'Version' ),
    875             'patterns' => $patterns,
    876         );
    877         set_transient( 'wp_theme_patterns_' . $this->stylesheet, $pattern_data );
    878     }
    879 
    880     /**
    881      * Clears block pattern cache.
    882      *
    883      * @since 6.4.0
    884      */
    885     public function delete_pattern_cache() {
    886         delete_transient( 'wp_theme_patterns_' . $this->stylesheet );
    887     }
    888 
    889     /**
    890848     * Gets a raw, unformatted theme header.
    891849     *
     
    18421800
    18431801    /**
     1802     * Gets block pattern data for a specified theme.
     1803     * Each pattern is defined as a PHP file and defines
     1804     * its metadata using plugin-style headers. The minimum required definition is:
     1805     *
     1806     *     /**
     1807     *      * Title: My Pattern
     1808     *      * Slug: my-theme/my-pattern
     1809     *      *
     1810     *
     1811     * The output of the PHP source corresponds to the content of the pattern, e.g.:
     1812     *
     1813     *     <main><p><?php echo "Hello"; ?></p></main>
     1814     *
     1815     * If applicable, this will collect from both parent and child theme.
     1816     *
     1817     * Other settable fields include:
     1818     *
     1819     *     - Description
     1820     *     - Viewport Width
     1821     *     - Inserter         (yes/no)
     1822     *     - Categories       (comma-separated values)
     1823     *     - Keywords         (comma-separated values)
     1824     *     - Block Types      (comma-separated values)
     1825     *     - Post Types       (comma-separated values)
     1826     *     - Template Types   (comma-separated values)
     1827     *
     1828     * @since 6.4.0
     1829     *
     1830     * @return array Block pattern data.
     1831     */
     1832    public function get_block_patterns() {
     1833        $can_use_cached = ! wp_is_development_mode( 'theme' );
     1834
     1835        $pattern_data = $this->get_pattern_cache();
     1836        if ( is_array( $pattern_data ) ) {
     1837            if ( $can_use_cached ) {
     1838                return $pattern_data;
     1839            }
     1840            // If in development mode, clear pattern cache.
     1841            $this->delete_pattern_cache();
     1842        }
     1843
     1844        $dirpath      = $this->get_stylesheet_directory() . '/patterns/';
     1845        $pattern_data = array();
     1846
     1847        if ( ! file_exists( $dirpath ) ) {
     1848            if ( $can_use_cached ) {
     1849                $this->set_pattern_cache( $pattern_data );
     1850            }
     1851            return $pattern_data;
     1852        }
     1853        $files = glob( $dirpath . '*.php' );
     1854        if ( ! $files ) {
     1855            if ( $can_use_cached ) {
     1856                $this->set_pattern_cache( $pattern_data );
     1857            }
     1858            return $pattern_data;
     1859        }
     1860
     1861        $default_headers = array(
     1862            'title'         => 'Title',
     1863            'slug'          => 'Slug',
     1864            'description'   => 'Description',
     1865            'viewportWidth' => 'Viewport Width',
     1866            'inserter'      => 'Inserter',
     1867            'categories'    => 'Categories',
     1868            'keywords'      => 'Keywords',
     1869            'blockTypes'    => 'Block Types',
     1870            'postTypes'     => 'Post Types',
     1871            'templateTypes' => 'Template Types',
     1872        );
     1873
     1874        $properties_to_parse = array(
     1875            'categories',
     1876            'keywords',
     1877            'blockTypes',
     1878            'postTypes',
     1879            'templateTypes',
     1880        );
     1881
     1882        foreach ( $files as $file ) {
     1883            $pattern = get_file_data( $file, $default_headers );
     1884
     1885            if ( empty( $pattern['slug'] ) ) {
     1886                _doing_it_wrong(
     1887                    __FUNCTION__,
     1888                    sprintf(
     1889                        /* translators: 1: file name. */
     1890                        __( 'Could not register file "%s" as a block pattern ("Slug" field missing)' ),
     1891                        $file
     1892                    ),
     1893                    '6.0.0'
     1894                );
     1895                continue;
     1896            }
     1897
     1898            if ( ! preg_match( '/^[A-z0-9\/_-]+$/', $pattern['slug'] ) ) {
     1899                _doing_it_wrong(
     1900                    __FUNCTION__,
     1901                    sprintf(
     1902                        /* translators: 1: file name; 2: slug value found. */
     1903                        __( 'Could not register file "%1$s" as a block pattern (invalid slug "%2$s")' ),
     1904                        $file,
     1905                        $pattern['slug']
     1906                    ),
     1907                    '6.0.0'
     1908                );
     1909            }
     1910
     1911            // Title is a required property.
     1912            if ( ! $pattern['title'] ) {
     1913                _doing_it_wrong(
     1914                    __FUNCTION__,
     1915                    sprintf(
     1916                        /* translators: 1: file name. */
     1917                        __( 'Could not register file "%s" as a block pattern ("Title" field missing)' ),
     1918                        $file
     1919                    ),
     1920                    '6.0.0'
     1921                );
     1922                continue;
     1923            }
     1924
     1925            // For properties of type array, parse data as comma-separated.
     1926            foreach ( $properties_to_parse as $property ) {
     1927                if ( ! empty( $pattern[ $property ] ) ) {
     1928                    $pattern[ $property ] = array_filter( wp_parse_list( (string) $pattern[ $property ] ) );
     1929                } else {
     1930                    unset( $pattern[ $property ] );
     1931                }
     1932            }
     1933
     1934            // Parse properties of type int.
     1935            $property = 'viewportWidth';
     1936            if ( ! empty( $pattern[ $property ] ) ) {
     1937                $pattern[ $property ] = (int) $pattern[ $property ];
     1938            } else {
     1939                unset( $pattern[ $property ] );
     1940            }
     1941
     1942            // Parse properties of type bool.
     1943            $property = 'inserter';
     1944            if ( ! empty( $pattern[ $property ] ) ) {
     1945                $pattern[ $property ] = in_array(
     1946                    strtolower( $pattern[ $property ] ),
     1947                    array( 'yes', 'true' ),
     1948                    true
     1949                );
     1950            } else {
     1951                unset( $pattern[ $property ] );
     1952            }
     1953
     1954            $key = str_replace( $dirpath, '', $file );
     1955
     1956            $pattern_data[ $key ] = $pattern;
     1957        }
     1958
     1959        if ( $can_use_cached ) {
     1960            $this->set_pattern_cache( $pattern_data );
     1961        }
     1962
     1963        return $pattern_data;
     1964    }
     1965
     1966    /**
     1967     * Gets block pattern cache.
     1968     *
     1969     * @since 6.4.0
     1970     *
     1971     * @return array|false Returns an array of patterns if cache is found, otherwise false.
     1972     */
     1973    private function get_pattern_cache() {
     1974        if ( ! $this->exists() ) {
     1975            return false;
     1976        }
     1977        $pattern_data = wp_cache_get( 'wp_theme_patterns_' . $this->stylesheet );
     1978        if ( is_array( $pattern_data ) && $pattern_data['version'] === $this->get( 'Version' ) ) {
     1979            return $pattern_data['patterns'];
     1980        }
     1981        return false;
     1982    }
     1983
     1984    /**
     1985     * Sets block pattern cache.
     1986     *
     1987     * @since 6.4.0
     1988     *
     1989     * @param array $patterns Block patterns data to set in cache.
     1990     */
     1991    private function set_pattern_cache( array $patterns ) {
     1992        $pattern_data = array(
     1993            'version'  => $this->get( 'Version' ),
     1994            'patterns' => $patterns,
     1995        );
     1996        wp_cache_set( 'wp_theme_patterns_' . $this->stylesheet, $pattern_data );
     1997    }
     1998
     1999    /**
     2000     * Clears block pattern cache.
     2001     *
     2002     * @since 6.4.0
     2003     */
     2004    public function delete_pattern_cache() {
     2005        wp_cache_delete( 'wp_theme_patterns_' . $this->stylesheet );
     2006    }
     2007
     2008    /**
    18442009     * Enables a theme for all sites on the current network.
    18452010     *
Note: See TracChangeset for help on using the changeset viewer.