1<?php
2/**
3 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
4 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
5 *
6 * Licensed under The MIT License
7 * For full copyright and license information, please see the LICENSE.txt
8 * Redistributions of files must retain the above copyright notice.
9 *
10 * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
11 * @link          https://cakephp.org CakePHP(tm) Project
12 * @since         3.0.0
13 * @license       https://opensource.org/licenses/mit-license.php MIT License
14 */
15namespace Cake\Database\Schema;
16
17use Cake\Cache\Cache;
18use Cake\Datasource\ConnectionInterface;
19
20/**
21 * Extends the schema collection class to provide caching
22 */
23class CachedCollection extends Collection
24{
25    /**
26     * The name of the cache config key to use for caching table metadata,
27     * of false if disabled.
28     *
29     * @var string|bool
30     */
31    protected $_cache = false;
32
33    /**
34     * Constructor.
35     *
36     * @param \Cake\Datasource\ConnectionInterface $connection The connection instance.
37     * @param string|bool $cacheKey The cache key or boolean false to disable caching.
38     */
39    public function __construct(ConnectionInterface $connection, $cacheKey = true)
40    {
41        parent::__construct($connection);
42        $this->setCacheMetadata($cacheKey);
43    }
44
45    /**
46     * {@inheritDoc}
47     */
48    public function describe($name, array $options = [])
49    {
50        $options += ['forceRefresh' => false];
51        $cacheConfig = $this->getCacheMetadata();
52        $cacheKey = $this->cacheKey($name);
53
54        if (!empty($cacheConfig) && !$options['forceRefresh']) {
55            $cached = Cache::read($cacheKey, $cacheConfig);
56            if ($cached !== false) {
57                return $cached;
58            }
59        }
60
61        $table = parent::describe($name, $options);
62
63        if (!empty($cacheConfig)) {
64            Cache::write($cacheKey, $table, $cacheConfig);
65        }
66
67        return $table;
68    }
69
70    /**
71     * Get the cache key for a given name.
72     *
73     * @param string $name The name to get a cache key for.
74     * @return string The cache key.
75     */
76    public function cacheKey($name)
77    {
78        $cachePrefix = $this->_connection->configName();
79        $config = $this->_connection->config();
80        if (isset($config['cacheKeyPrefix'])) {
81            $cachePrefix = $config['cacheKeyPrefix'];
82        }
83
84        return $cachePrefix . '_' . $name;
85    }
86
87    /**
88     * Sets the cache config name to use for caching table metadata, or
89     * disables it if false is passed.
90     *
91     * @param bool $enable Whether or not to enable caching
92     * @return $this
93     */
94    public function setCacheMetadata($enable)
95    {
96        if ($enable === true) {
97            $enable = '_cake_model_';
98        }
99
100        $this->_cache = $enable;
101
102        return $this;
103    }
104
105    /**
106     * Gets the cache config name to use for caching table metadata, false means disabled.
107     *
108     * @return string|bool
109     */
110    public function getCacheMetadata()
111    {
112        return $this->_cache;
113    }
114
115    /**
116     * Sets the cache config name to use for caching table metadata, or
117     * disables it if false is passed.
118     * If called with no arguments it returns the current configuration name.
119     *
120     * @deprecated 3.4.0 Use setCacheMetadata()/getCacheMetadata()
121     * @param bool|null $enable Whether or not to enable caching
122     * @return string|bool
123     */
124    public function cacheMetadata($enable = null)
125    {
126        deprecationWarning(
127            'CachedCollection::cacheMetadata() is deprecated. ' .
128            'Use CachedCollection::setCacheMetadata()/getCacheMetadata() instead.'
129        );
130        if ($enable !== null) {
131            $this->setCacheMetadata($enable);
132        }
133
134        return $this->getCacheMetadata();
135    }
136}
137