Issues (91)

src/Reflection/CachedDocBlockFactory.php (2 issues)

1
<?php
2
3
4
namespace TheCodingMachine\GraphQL\Controllers\Reflection;
5
6
use function filemtime;
7
use phpDocumentor\Reflection\DocBlock;
8
use phpDocumentor\Reflection\DocBlockFactory;
9
use phpDocumentor\Reflection\Types\Context;
10
use phpDocumentor\Reflection\Types\ContextFactory;
11
use Psr\SimpleCache\CacheInterface;
12
use ReflectionMethod;
13
14
/**
15
 * Creates DocBlocks and puts these in cache.
16
 */
17
class CachedDocBlockFactory
18
{
19
    /**
20
     * @var CacheInterface
21
     */
22
    private $cache;
23
    /**
24
     * @var DocBlockFactory|null
25
     */
26
    private $docBlockFactory;
27
    /**
28
     * @var array<string, DocBlock>
29
     */
30
    private $docBlockArrayCache = [];
31
    /**
32
     * @var array<string, Context>
33
     */
34
    private $contextArrayCache = [];
35
    /**
36
     * @var ContextFactory
37
     */
38
    private $contextFactory;
39
40
    /**
41
     * @param CacheInterface $cache The cache we fetch data from. Note this is a SAFE cache. It does not need to be purged.
42
     * @param DocBlockFactory|null $docBlockFactory
43
     */
44
    public function __construct(CacheInterface $cache, ?DocBlockFactory $docBlockFactory = null)
45
    {
46
        $this->cache = $cache;
47
        $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance();
48
        $this->contextFactory = new ContextFactory();
49
    }
50
51
    /**
52
     * Fetches a DocBlock object from a ReflectionMethod
53
     *
54
     * @param ReflectionMethod $refMethod
55
     * @return DocBlock
56
     */
57
    public function getDocBlock(ReflectionMethod $refMethod): DocBlock
58
    {
59
        $key = 'docblock_'.md5($refMethod->getDeclaringClass()->getName().'::'.$refMethod->getName());
60
        if (isset($this->docBlockArrayCache[$key])) {
61
            return $this->docBlockArrayCache[$key];
62
        }
63
64
        if ($cacheItem = $this->cache->get($key)) {
65
            [
66
                'time' => $time,
67
                'docblock' => $docBlock
68
            ] = $cacheItem;
69
70
            if (filemtime($refMethod->getFileName()) === $time) {
71
                $this->docBlockArrayCache[$key] = $docBlock;
72
                return $docBlock;
73
            }
74
        }
75
76
        $docBlock = $this->doGetDocBlock($refMethod);
77
78
        $this->cache->set($key, [
79
            'time' => filemtime($refMethod->getFileName()),
80
            'docblock' => $docBlock
81
        ]);
82
        $this->docBlockArrayCache[$key] = $docBlock;
83
84
        return $docBlock;
85
    }
86
87
    private function doGetDocBlock(ReflectionMethod $refMethod): DocBlock
88
    {
89
        $docComment = $refMethod->getDocComment() ?: '/** */';
90
91
        $refClass = $refMethod->getDeclaringClass();
92
        $refClassName = $refClass->getName();
93
94
        if (!isset($this->contextArrayCache[$refClassName])) {
95
            $this->contextArrayCache[$refClassName] = $this->contextFactory->createFromReflector($refMethod);
96
        }
97
98
        return $this->docBlockFactory->create($docComment, $this->contextArrayCache[$refClassName]);
0 ignored issues
show
It seems like $docComment can also be of type true; however, parameter $docblock of phpDocumentor\Reflection\DocBlockFactory::create() does only seem to accept object|string, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

98
        return $this->docBlockFactory->create(/** @scrutinizer ignore-type */ $docComment, $this->contextArrayCache[$refClassName]);
Loading history...
The method create() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

98
        return $this->docBlockFactory->/** @scrutinizer ignore-call */ create($docComment, $this->contextArrayCache[$refClassName]);

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
99
    }
100
}
101