Completed
Push — master ( 10bb60...177540 )
by Sébastien
03:45
created

AbstractMetadataReader::addCapability()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 6
ccs 4
cts 4
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 3
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Soluble\Metadata\Reader;
6
7
use Soluble\Metadata\ColumnsMetadata;
8
use Soluble\Metadata\Exception;
9
10
abstract class AbstractMetadataReader implements MetadataReaderInterface
11
{
12
    /**
13
     * Keep static cache in memory.
14
     *
15
     * @var bool
16
     */
17
    protected $cache_active = true;
18
19
    /**
20
     * @var array
21
     */
22
    protected static $metadata_cache = [];
23
24
    /**
25
     * @var string[]
26
     */
27
    protected $capabilities = [];
28
29
    /**
30
     * @param bool $active
31
     *
32
     * @return AbstractMetadataReader
33
     */
34 1
    public function setStaticCache(bool $active = true)
35
    {
36 1
        $this->cache_active = $active;
37
38 1
        return $this;
39
    }
40
41
    /**
42
     * Return columns metadata from query.
43
     *
44
     * @throws Exception\UnsupportedTypeException
45
     * @throws Exception\AmbiguousColumnException
46
     * @throws Exception\InvalidQueryException
47
     */
48 17
    public function getColumnsMetadata(string $sql): ColumnsMetadata
49
    {
50 17
        if ($this->cache_active) {
51 16
            $cache_key = md5($sql);
52 16
            if (!array_key_exists($cache_key, static::$metadata_cache)) {
53 10
                $md = $this->readColumnsMetadata($sql);
54 3
                static::$metadata_cache[$cache_key] = $md;
55
            }
56
57 9
            return static::$metadata_cache[$cache_key];
58
        }
59
60 1
        return $this->readColumnsMetadata($sql);
61
    }
62
63
    /**
64
     * Return columns metadata from a table.
65
     *
66
     * @throws Exception\UnsupportedTypeException
67
     * @throws Exception\AmbiguousColumnException
68
     * @throws Exception\TableNotFoundException
69
     */
70 2
    public function getTableMetadata(string $table): ColumnsMetadata
71
    {
72
        try {
73 2
            $metadata = $this->getColumnsMetadata(sprintf('select * from %s', $table));
74 1
        } catch (Exception\InvalidQueryException $e) {
75 1
            throw new Exception\TableNotFoundException(sprintf(
76 1
                'Table "%s" does not exists (%s).',
77 1
                $table,
78 1
                $e->getMessage()
79
            ));
80
        }
81
82 1
        return $metadata;
83
    }
84
85
    /**
86
     * Read metadata information from source.
87
     *
88
     * @throws Exception\UnsupportedTypeException
89
     * @throws Exception\AmbiguousColumnException
90
     * @throws \Soluble\Metadata\Exception\InvalidQueryException
91
     */
92
    abstract protected function readColumnsMetadata(string $sql): ColumnsMetadata;
93
94
    /**
95
     * Optimization, will add false condition to the query
96
     * so the metadata loading will be faster.
97
     */
98 10
    protected function getEmptiedQuery(string $sql): string
99
    {
100
        // see the reason why in Vision_Store_Adapter_ZendDbSelect::getMetaData
101
        //$sql = str_replace("('__innerselect'='__innerselect')", '(1=0)', $sql);
102
103 10
        $sql = preg_replace('/(\r\n|\r|\n|\t)+/', ' ', strtolower($sql));
104 10
        $sql = trim($sql);
105 10
        $sql = preg_replace('/\s+/', ' ', $sql);
106
107 10
        $replace_regexp = "LIMIT[\s]+[\d]+((\s*,\s*\d+)|(\s+OFFSET\s+\d+)){0,1}";
108
109 10
        $search_regexp = "$replace_regexp";
110 10
        if (!preg_match("/$search_regexp/i", $sql)) {
111
            // Limit is not already present
112 10
            $sql .= ' LIMIT 0';
113
        } else {
114
            // replace first if offset exists, then if not
115
            //preg_match_all("/($search_regexp)/i", $sql, $matches, PREG_PATTERN_ORDER);
116
            //var_dump($matches);
117
118 1
            $sql = preg_replace("/($replace_regexp)/i", 'LIMIT 0', $sql);
119
        }
120
121 10
        return $sql;
122
    }
123
124 19
    public function addCapability(string $name): void
125
    {
126 19
        if (!in_array($name, $this->capabilities, true)) {
127 19
            $this->capabilities[] = $name;
128
        }
129 19
    }
130
131
    public function hasCapability(string $name): bool
132
    {
133
        return in_array($name, $this->capabilities, true);
134
    }
135
}
136