/
var
/
www
/
barefootlaw.org
/
wp-content
/
plugins
/
autodescription
/
inc
/
functions
/
Upload File
HOME
<?php /** * @package The_SEO_Framework\API */ namespace { defined( 'THE_SEO_FRAMEWORK_PRESENT' ) or die; } /** * The SEO Framework plugin * Copyright (C) 2018 - 2023 Sybre Waaijer, CyberWire B.V. (https://cyberwire.nl/) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 3 as published * by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ namespace { /** * Returns the class from cache. * * This is the recommended way of calling the class, if needed. * Call this after action 'plugins_loaded' priority 5 otherwise you'll cause * unforeseen issues. * * @since 4.2.0 * @see `the_seo_framework()` alias. * @api * * @return null|object The plugin class object. */ function tsf() { return The_SEO_Framework\_init_tsf(); } /** * Returns the class from cache. * * This is the recommended way of calling the class, if needed. * Call this after action 'plugins_loaded' priority 5 otherwise you'll cause * unforeseen issues. * * @since 2.2.5 * @see `tsf()` alias. * @api * * @return null|object The plugin class object. */ function the_seo_framework() { return The_SEO_Framework\_init_tsf(); } /** * Returns the database version of TSF. * * @since 3.1.0 * @since 3.1.2 Now casts to string. * @api * * @return string The database version. '0' if version isn't found. */ function the_seo_framework_db_version() { return (string) get_option( 'the_seo_framework_upgraded_db_version', '0' ); } /** * Returns the facade class name from cache. * * @since 2.7.0 * @since 2.8.0 Added `did_action()` check. * @since 4.2.0 Removed memoization. * @api * * @return string|bool The SEO Framework class name. False if The SEO Framework isn't loaded (yet). */ function the_seo_framework_class() { // did_action() returns true for current action match, too. if ( ! did_action( 'plugins_loaded' ) ) return false; return get_class( tsf() ); } } namespace The_SEO_Framework { /** * Determines if the method or function has already run. * * @since 4.2.3 * @api * @todo make $caller optional and use debug_backtrace()? * * @param string $caller The method or function that calls this. * @return bool True if already called, false otherwise. */ function has_run( $caller ) { static $ran = []; return $ran[ $caller ] ?? ! ( $ran[ $caller ] = true ); } /** * Stores and returns memoized values for the caller. * * This method is not forward-compatible with PHP: It expects values it doesn't want populated, * instead of filtering what's actually useful for memoization. For example, it expects `file` * and `line` from debug_backtrace() -- those are expected to be dynamic from the caller, and * we set them to `0` to prevent a few opcode calls, rather than telling which array indexes * we want exactly. The chance this failing in a future update is slim, for all useful data of * the callee is given already via debug_backtrace(). * We also populate the `args` value "manually" for it's faster than using debug_backtrace()'s * `DEBUG_BACKTRACE_PROVIDE_OBJECT` option. * * We should keep a tap on debug_backtrace changes. Hopefully, they allow us to ignore * more than just args. * * This method does not memoize the object via debug_backtrace. This means that the * objects will have values memoized cross-instantiations. * * Example usage: * ``` * function expensive_call( $arg ) { * print( "expensive $arg!" ); * return $arg * 2; * } * function my_function( $arg ) { * return memo( null, $arg ); * ?? memo( expensive_call( $arg ), $arg ); * } * my_function( 1 ); // prints "expensive 1!", returns 2. * my_function( 1 ); // returns 2. * my_function( 2 ); // prints "expensive 2!", returns 4. * * function test() { * return memo() ?? memo( expensive_call( 42 ) ); * } * test(); // prints "expensive 42", returns 84. * test(); // returns 84. * ``` * * @since 4.2.0 * @see umemo() -- sacrifices cleanliness for performance. * @see fmemo() -- sacrifices everything for readability. * @api * * @param mixed $value_to_set The value to set. * @param mixed ...$args Extra arguments, that are used to differentiaty callbacks. * Arguments may not contain \Closure()s. * @return mixed : { * mixed The cached value if set and $value_to_set is null. * null When no value has been set. * If $value_to_set is set, the new value. * } */ function memo( $value_to_set = null, ...$args ) { static $memo = []; // phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- No objects inserted, nor ever unserialized. $hash = serialize( [ 'args' => $args, 'file' => 0, 'line' => 0, ] // phpcs:ignore, WordPress.PHP.DevelopmentFunctions -- This is the only efficient way. + debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 )[1] ); if ( isset( $value_to_set ) ) return $memo[ $hash ] = $value_to_set; return $memo[ $hash ] ?? null; } /** * Stores and returns memoized values for the caller. * This is 10 times faster than memo(), but requires from you a $key. * * We're talking milliseconds over thousands of iterations, though. * * Example usage: * ``` * function expensive_call( $arg ) { * print( "expensive $arg!" ); * return $arg * 2; * } * function my_function( $arg ) { * return umemo( __METHOD__, null, $arg ); * ?? umemo( __METHOD__, expensive_call( $arg ), $arg ); * } * my_function( 1 ); // prints "expensive 1!", returns 2. * my_function( 1 ); // returns 2. * my_function( 2 ); // prints "expensive 2!", returns 4. * ``` * * @since 4.2.0 * @see memo() -- sacrifices performance for cleanliness. * @see fmemo() -- sacrifices everything for readability. * @api * * @param string $key The key you want to use to memoize. It's best to use the method name. * You can share a unique key between various functions. * @param mixed $value_to_set The value to set. * @param mixed ...$args Extra arguments, that are used to differentiate callbacks. * Arguments may not contain \Closure()s. * @return mixed : { * mixed The cached value if set and $value_to_set is null. * null When no value has been set. * If $value_to_set is set, the new value. * } */ function umemo( $key, $value_to_set = null, ...$args ) { static $memo = []; // phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- No objects are inserted, nor is this ever unserialized. $hash = serialize( [ $key, $args ] ); if ( isset( $value_to_set ) ) return $memo[ $hash ] = $value_to_set; return $memo[ $hash ] ?? null; } /** * Stores and returns memoized values for the Closure caller. This helps wrap * a whole function inside a single memoization call. * * This method does not memoize the object via debug_backtrace. This means that the * objects will have values memoized cross-instantiations. * * Example usage, PHP7.4+: * ``` * function my_function( $arg ) { return fmemo( fn() => print( $arg ) + 5 ); } * my_function( 1 ); // prints '1', returns 6. * my_function( 1 ); // does not print, returns 6. * ``` * Arrow functions are neat with this for they automatically register only necessary arguments to fmemo(). * This way, callers of my_function() won't bust the cache by sending unregistered superfluous arguments. * * ``` * function printer() { print( 69 ); } * function print_once() { fmemo( 'printer' ); } * print_once(); // 69 * print_once(); // *cricket noises* * ``` * * @since 4.2.0 * @see memo() -- sacrifices performance for cleanliness. * @see umemo() -- sacrifices cleanliness for performance. * @ignore We couldn't find a use for this... yet. Probably once we support only PHP7.4+ * @api * TODO Can we use callables as $fn? If so, adjust docs and apply internally. * * @param \Closure $fn The Closure or function to memoize. * @return mixed : { * mixed The cached value if set and $value_to_set is null. * null When no value has been set. * If $value_to_set is set, the new value. * } */ function fmemo( $fn ) { static $memo = []; // phpcs:ignore, WordPress.PHP.DiscouragedPHPFunctions -- This is never unserialized. $hash = serialize( [ 'file' => '', 'line' => 0, ] // phpcs:ignore, WordPress.PHP.DevelopmentFunctions -- This is the only efficient way. + debug_backtrace( 0, 2 )[1] ); // Normally, I try to avoid NOTs for they add (tiny) overhead. Here, I chose readability over performance. if ( ! isset( $memo[ $hash ] ) ) { // Store the result of the function. If that's null/void, store hash. $memo[ $hash ] = \call_user_func( $fn ) ?? $hash; } return $memo[ $hash ] === $hash ? null : $memo[ $hash ]; } }