1 | <?php |
||
45 | class CacheController extends Controller |
||
46 | { |
||
47 | /** |
||
48 | * Lists the caches that can be flushed. |
||
49 | */ |
||
50 | public function actionIndex() |
||
51 | { |
||
52 | $caches = $this->findCaches(); |
||
53 | |||
54 | if (!empty($caches)) { |
||
55 | $this->notifyCachesCanBeFlushed($caches); |
||
56 | } else { |
||
57 | $this->notifyNoCachesFound(); |
||
58 | } |
||
59 | } |
||
60 | |||
61 | /** |
||
62 | * Flushes given cache components. |
||
63 | * For example, |
||
64 | * |
||
65 | * ``` |
||
66 | * # flushes caches specified by their id: "first", "second", "third" |
||
67 | * yii cache/flush first second third |
||
68 | * ``` |
||
69 | * |
||
70 | */ |
||
71 | 4 | public function actionFlush() |
|
72 | { |
||
73 | 4 | $cachesInput = func_get_args(); |
|
74 | |||
75 | 4 | if (empty($cachesInput)) { |
|
76 | 1 | throw new Exception('You should specify cache components names'); |
|
77 | } |
||
78 | |||
79 | 3 | $caches = $this->findCaches($cachesInput); |
|
80 | 3 | $cachesInfo = []; |
|
81 | |||
82 | 3 | $foundCaches = array_keys($caches); |
|
83 | 3 | $notFoundCaches = array_diff($cachesInput, array_keys($caches)); |
|
84 | |||
85 | 3 | if ($notFoundCaches) { |
|
|
|||
86 | 1 | $this->notifyNotFoundCaches($notFoundCaches); |
|
87 | } |
||
88 | |||
89 | 3 | if (!$foundCaches) { |
|
90 | 1 | $this->notifyNoCachesFound(); |
|
91 | 1 | return static::EXIT_CODE_NORMAL; |
|
92 | } |
||
93 | |||
94 | 2 | if (!$this->confirmFlush($foundCaches)) { |
|
95 | return static::EXIT_CODE_NORMAL; |
||
96 | } |
||
97 | |||
98 | 2 | foreach ($caches as $name => $class) { |
|
99 | 2 | $cachesInfo[] = [ |
|
100 | 2 | 'name' => $name, |
|
101 | 2 | 'class' => $class, |
|
102 | 2 | 'is_flushed' => Yii::$app->get($name)->flush(), |
|
103 | ]; |
||
104 | } |
||
105 | |||
106 | 2 | $this->notifyFlushed($cachesInfo); |
|
107 | 2 | } |
|
108 | |||
109 | /** |
||
110 | * Flushes all caches registered in the system. |
||
111 | */ |
||
112 | 1 | public function actionFlushAll() |
|
113 | { |
||
114 | 1 | $caches = $this->findCaches(); |
|
115 | 1 | $cachesInfo = []; |
|
116 | |||
117 | 1 | if (empty($caches)) { |
|
118 | $this->notifyNoCachesFound(); |
||
119 | return static::EXIT_CODE_NORMAL; |
||
120 | } |
||
121 | |||
122 | 1 | foreach ($caches as $name => $class) { |
|
123 | 1 | $cachesInfo[] = [ |
|
124 | 1 | 'name' => $name, |
|
125 | 1 | 'class' => $class, |
|
126 | 1 | 'is_flushed' => Yii::$app->get($name)->flush(), |
|
127 | ]; |
||
128 | } |
||
129 | |||
130 | 1 | $this->notifyFlushed($cachesInfo); |
|
131 | 1 | } |
|
132 | |||
133 | /** |
||
134 | * Clears DB schema cache for a given connection component. |
||
135 | * |
||
136 | * ``` |
||
137 | * # clears cache schema specified by component id: "db" |
||
138 | * yii cache/flush-schema db |
||
139 | * ``` |
||
140 | * |
||
141 | * @param string $db id connection component |
||
142 | * @return int exit code |
||
143 | * @throws Exception |
||
144 | * @throws \yii\base\InvalidConfigException |
||
145 | * |
||
146 | * @since 2.0.1 |
||
147 | */ |
||
148 | 1 | public function actionFlushSchema($db = 'db') |
|
149 | { |
||
150 | 1 | $connection = Yii::$app->get($db, false); |
|
151 | 1 | if ($connection === null) { |
|
152 | $this->stdout("Unknown component \"$db\".\n", Console::FG_RED); |
||
153 | return self::EXIT_CODE_ERROR; |
||
154 | } |
||
155 | |||
156 | 1 | if (!$connection instanceof \yii\db\Connection) { |
|
157 | $this->stdout("\"$db\" component doesn't inherit \\yii\\db\\Connection.\n", Console::FG_RED); |
||
158 | return self::EXIT_CODE_ERROR; |
||
159 | 1 | } elseif (!$this->confirm("Flush cache schema for \"$db\" connection?")) { |
|
160 | return static::EXIT_CODE_NORMAL; |
||
161 | } |
||
162 | |||
163 | try { |
||
164 | 1 | $schema = $connection->getSchema(); |
|
165 | 1 | $schema->refresh(); |
|
166 | 1 | $this->stdout("Schema cache for component \"$db\", was flushed.\n\n", Console::FG_GREEN); |
|
167 | } catch (\Exception $e) { |
||
168 | $this->stdout($e->getMessage() . "\n\n", Console::FG_RED); |
||
169 | } |
||
170 | 1 | } |
|
171 | |||
172 | /** |
||
173 | * Notifies user that given caches are found and can be flushed. |
||
174 | * @param array $caches array of cache component classes |
||
175 | */ |
||
176 | private function notifyCachesCanBeFlushed($caches) |
||
177 | { |
||
178 | $this->stdout("The following caches were found in the system:\n\n", Console::FG_YELLOW); |
||
179 | |||
180 | foreach ($caches as $name => $class) { |
||
181 | $this->stdout("\t* $name ($class)\n", Console::FG_GREEN); |
||
182 | } |
||
183 | |||
184 | $this->stdout("\n"); |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Notifies user that there was not found any cache in the system. |
||
189 | */ |
||
190 | 1 | private function notifyNoCachesFound() |
|
194 | |||
195 | /** |
||
196 | * Notifies user that given cache components were not found in the system. |
||
197 | * @param array $cachesNames |
||
198 | */ |
||
199 | 1 | private function notifyNotFoundCaches($cachesNames) |
|
200 | { |
||
201 | 1 | $this->stdout("The following cache components were NOT found:\n\n", Console::FG_RED); |
|
202 | |||
203 | 1 | foreach ($cachesNames as $name) { |
|
204 | 1 | $this->stdout("\t* $name \n", Console::FG_GREEN); |
|
205 | } |
||
206 | |||
207 | 1 | $this->stdout("\n"); |
|
208 | 1 | } |
|
209 | |||
210 | /** |
||
211 | * |
||
212 | * @param array $caches |
||
213 | */ |
||
214 | 3 | private function notifyFlushed($caches) |
|
215 | { |
||
216 | 3 | $this->stdout("The following cache components were processed:\n\n", Console::FG_YELLOW); |
|
217 | |||
218 | 3 | foreach ($caches as $cache) { |
|
219 | 3 | $this->stdout("\t* " . $cache['name'] .' (' . $cache['class'] . ')', Console::FG_GREEN); |
|
220 | |||
221 | 3 | if (!$cache['is_flushed']) { |
|
222 | $this->stdout(" - not flushed\n", Console::FG_RED); |
||
223 | } else { |
||
224 | 3 | $this->stdout("\n"); |
|
225 | } |
||
226 | } |
||
227 | |||
228 | 3 | $this->stdout("\n"); |
|
229 | 3 | } |
|
230 | |||
231 | /** |
||
232 | * Prompts user with confirmation if caches should be flushed. |
||
233 | * @param array $cachesNames |
||
234 | * @return bool |
||
235 | */ |
||
236 | 2 | private function confirmFlush($cachesNames) |
|
237 | { |
||
238 | 2 | $this->stdout("The following cache components will be flushed:\n\n", Console::FG_YELLOW); |
|
239 | |||
240 | 2 | foreach ($cachesNames as $name) { |
|
241 | 2 | $this->stdout("\t* $name \n", Console::FG_GREEN); |
|
242 | } |
||
243 | |||
244 | 2 | return $this->confirm("\nFlush above cache components?"); |
|
245 | } |
||
246 | |||
247 | /** |
||
248 | * Returns array of caches in the system, keys are cache components names, values are class names. |
||
249 | * @param array $cachesNames caches to be found |
||
250 | * @return array |
||
251 | */ |
||
252 | 4 | private function findCaches(array $cachesNames = []) |
|
253 | { |
||
254 | 4 | $caches = []; |
|
255 | 4 | $components = Yii::$app->getComponents(); |
|
256 | 4 | $findAll = ($cachesNames === []); |
|
257 | |||
258 | 4 | foreach ($components as $name => $component) { |
|
259 | 4 | if (!$findAll && !in_array($name, $cachesNames)) { |
|
260 | 3 | continue; |
|
261 | } |
||
262 | |||
263 | 3 | if ($component instanceof Cache) { |
|
264 | $caches[$name] = get_class($component); |
||
265 | 3 | } elseif (is_array($component) && isset($component['class']) && $this->isCacheClass($component['class'])) { |
|
266 | $caches[$name] = $component['class']; |
||
267 | 3 | } elseif (is_string($component) && $this->isCacheClass($component)) { |
|
268 | 3 | $caches[$name] = $component; |
|
269 | } |
||
270 | } |
||
271 | |||
272 | 4 | return $caches; |
|
273 | } |
||
274 | |||
275 | /** |
||
276 | * Checks if given class is a Cache class. |
||
277 | * @param string $className class name. |
||
278 | * @return bool |
||
279 | */ |
||
280 | 3 | private function isCacheClass($className) |
|
284 | } |
||
285 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)
or! empty(...)
instead.