Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
39 / 39
100.00% covered (success)
100.00%
6 / 6
CRAP
100.00% covered (success)
100.00%
1 / 1
Memoize
100.00% covered (success)
100.00%
39 / 39
100.00% covered (success)
100.00%
6 / 6
23
100.00% covered (success)
100.00%
1 / 1
 owner
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 enable
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 disable
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 isMemoized
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
6
 memoize
100.00% covered (success)
100.00%
12 / 12
100.00% covered (success)
100.00%
1 / 1
5
 unmemoize
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
1 / 1
6
1<?php
2
3namespace TonyBogdanov\Memoize;
4
5use SplObjectStorage;
6use TonyBogdanov\Memoize\Exceptions\UnknownOwnerException;
7use WeakReference;
8
9/**
10 * Class Memoize
11 *
12 * @package TonyBogdanov\Memoize
13 */
14final class Memoize {
15
16    /** @var bool */
17    private static bool $enabled = true;
18
19    /** @var SplObjectStorage[] */
20    private static array $storage = [];
21
22    /**
23     * @param $owner
24     *
25     * @return array
26     */
27    private static function owner( $owner ): array {
28        if ( is_object( $owner ) ) {
29            return [ get_class( $owner ), WeakReference::create( $owner ) ];
30        }
31
32        if ( is_string( $owner ) && class_exists( $owner ) ) {
33            return [ $owner, VoidMarker::get() ];
34        }
35
36        throw new UnknownOwnerException( $owner );
37    }
38
39    public static function enable(): void {
40        self::$enabled = true;
41    }
42
43    public static function disable(): void {
44        self::$enabled = false;
45    }
46
47    /**
48     * @param $owner
49     * @param string|null $key
50     * @return bool
51     */
52    public static function isMemoized( $owner = null, string $key = null ): bool {
53        if ( ! self::$enabled || ! isset( $owner ) ) {
54            return false;
55        }
56
57        [ $group, $ref ] = self::owner( $owner );
58        if ( ! isset( self::$storage[ $group ] ) || ! isset( self::$storage[ $group ][ $ref ] ) ) {
59            return false;
60        }
61
62        return ! isset( $key ) || array_key_exists( $key, self::$storage[ $group ][ $ref ] );
63    }
64
65    /**
66     * @param $owner
67     * @param string $key
68     * @param callable $provider
69     *
70     * @return mixed
71     */
72    public static function memoize( $owner, string $key, callable $provider ) {
73        if ( ! self::$enabled ) {
74            return call_user_func( $provider );
75        }
76
77        [ $group, $ref ] = self::owner( $owner );
78        if ( ! isset( self::$storage[ $group ] ) ) {
79            self::$storage[ $group ] = new SplObjectStorage();
80        }
81
82        if ( ! isset( self::$storage[ $group ][ $ref ] ) ) {
83            self::$storage[ $group ][ $ref ] = [];
84        }
85
86        $data = self::$storage[ $group ][ $ref ];
87        if ( ! array_key_exists( $key, $data ) ) {
88            $data[ $key ] = call_user_func( $provider );
89            self::$storage[ $group ][ $ref ] = $data;
90        }
91
92        return $data[ $key ];
93    }
94
95    /**
96     * @param null $owner
97     * @param string|null $key
98     */
99    public static function unmemoize( $owner = null, string $key = null ): void {
100        if ( ! isset( $owner ) ) {
101            self::$storage = [];
102            return;
103        }
104
105        [ $group, $ref ] = self::owner( $owner );
106        if ( ! isset( self::$storage[ $group ] ) || ! isset( self::$storage[ $group ][ $ref ] ) ) {
107            return;
108        }
109
110        if ( ! isset( $key ) ) {
111            unset( self::$storage[ $group ][ $ref ] );
112            return;
113        }
114
115        if ( ! array_key_exists( $key, self::$storage[ $group ][ $ref ] ) ) {
116            return;
117        }
118
119        $data = self::$storage[ $group ][ $ref ];
120        unset( $data[ $key ] );
121
122        self::$storage[ $group ][ $ref ] = $data;
123    }
124
125}