MediaWiki master
MemoizedCallable.php
Go to the documentation of this file.
1<?php
8
9use Closure;
10use InvalidArgumentException;
11
36
38 private $callable;
39
41 private $callableName;
42
44 private $ttl;
45
53 public function __construct( $callable, $ttl = 3600 ) {
54 if ( !is_callable( $callable, false, $this->callableName ) ) {
55 throw new InvalidArgumentException(
56 'Argument 1 passed to MemoizedCallable::__construct() must ' .
57 'be a callable; ' . get_debug_type( $callable ) . ' given'
58 );
59 }
60
61 if ( $callable instanceof Closure ) {
62 throw new InvalidArgumentException( 'Cannot memoize unnamed closure' );
63 }
64
65 if ( is_object( $callable ) || is_object( $callable[ 0 ] ) ) {
66 throw new InvalidArgumentException( 'Cannot memoize object-bound callable' );
67 }
68
69 $this->callable = $callable;
70 $this->ttl = min( max( $ttl, 1 ), 86400 );
71 }
72
80 protected function fetchResult( $key, &$success ) {
81 $success = false;
82 if ( function_exists( 'apcu_fetch' ) ) {
83 return apcu_fetch( $key, $success );
84 }
85 return false;
86 }
87
94 protected function storeResult( $key, $result ) {
95 if ( function_exists( 'apcu_store' ) ) {
96 apcu_store( $key, $result, $this->ttl );
97 }
98 }
99
107 public function invokeArgs( array $args = [] ) {
108 foreach ( $args as $arg ) {
109 if ( $arg !== null && !is_scalar( $arg ) ) {
110 throw new InvalidArgumentException(
111 'MemoizedCallable::invoke() called with non-scalar ' .
112 'argument'
113 );
114 }
115 }
116
117 $hash = md5( serialize( $args ) );
118 $key = __CLASS__ . ':' . $this->callableName . ':' . $hash;
119 $success = false;
120 $result = $this->fetchResult( $key, $success );
121 if ( !$success ) {
122 $result = ( $this->callable )( ...$args );
123 $this->storeResult( $key, $result );
124 }
125
126 return $result;
127 }
128
137 public function invoke( ...$params ) {
138 return $this->invokeArgs( $params );
139 }
140
150 public static function call( $callable, array $args = [], $ttl = 3600 ) {
151 $instance = new self( $callable, $ttl );
152 return $instance->invokeArgs( $args );
153 }
154}
155
157class_alias( MemoizedCallable::class, 'MemoizedCallable' );
APCu-backed function memoization.
storeResult( $key, $result)
Store the result of an invocation.
invoke(... $params)
Invoke the memoized function or method.
invokeArgs(array $args=[])
Invoke the memoized function or method.
fetchResult( $key, &$success)
Fetch the result of a previous invocation.
static call( $callable, array $args=[], $ttl=3600)
Shortcut method for creating a MemoizedCallable and invoking it with the specified arguments.