Update copyright
[friendica.git/.git] / src / Console / Storage.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU Affero General Public License as
9  * published by the Free Software Foundation, either version 3 of the
10  * License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU Affero General Public License for more details.
16  *
17  * You should have received a copy of the GNU Affero General Public License
18  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
19  *
20  */
21
22 namespace Friendica\Console;
23
24 use Asika\SimpleConsole\CommandArgsException;
25 use Friendica\Core\StorageManager;
26 use Friendica\Model\Storage\StorageException;
27
28 /**
29  * tool to manage storage backend and stored data from CLI
30  */
31 class Storage extends \Asika\SimpleConsole\Console
32 {
33         protected $helpOptions = ['h', 'help', '?'];
34
35         /** @var StorageManager */
36         private $storageManager;
37
38         /**
39          * @param StorageManager $storageManager
40          */
41         public function __construct(StorageManager $storageManager, array $argv = [])
42         {
43                 parent::__construct($argv);
44
45                 $this->storageManager = $storageManager;
46         }
47
48         protected function getHelp()
49         {
50                 $help = <<<HELP
51 console storage - manage storage backend and stored data
52 Synopsis
53     bin/console storage [-h|--help|-?] [-v]
54         Show this help
55     
56     bin/console storage list
57         List available storage backends
58     
59     bin/console storage set <name>
60         Set current storage backend
61             name        storage backend to use. see "list".
62     
63     bin/console storage move [table] [-n 5000]
64         Move stored data to current storage backend.
65             table       one of "photo" or "attach". default to both
66             -n          limit of processed entry batch size
67 HELP;
68                 return $help;
69         }
70
71         protected function doExecute()
72         {
73                 if ($this->getOption('v')) {
74                         $this->out('Executable: ' . $this->executable);
75                         $this->out('Class: ' . __CLASS__);
76                         $this->out('Arguments: ' . var_export($this->args, true));
77                         $this->out('Options: ' . var_export($this->options, true));
78                 }
79
80                 if (count($this->args) == 0) {
81                         $this->out($this->getHelp());
82                         return -1;
83                 }
84
85                 switch ($this->args[0]) {
86                         case 'list':
87                                 return $this->doList();
88                                 break;
89                         case 'set':
90                                 return $this->doSet();
91                                 break;
92                         case 'move':
93                                 return $this->doMove();
94                                 break;
95                 }
96
97                 $this->out(sprintf('Invalid action "%s"', $this->args[0]));
98                 return -1;
99         }
100
101         protected function doList()
102         {
103                 $rowfmt = ' %-3s | %-20s';
104                 $current = $this->storageManager->getBackend();
105                 $this->out(sprintf($rowfmt, 'Sel', 'Name'));
106                 $this->out('-----------------------');
107                 $isregisterd = false;
108                 foreach ($this->storageManager->listBackends() as $name => $class) {
109                         $issel = ' ';
110                         if ($current && $current::getName() == $name) {
111                                 $issel = '*';
112                                 $isregisterd = true;
113                         };
114                         $this->out(sprintf($rowfmt, $issel, $name));
115                 }
116
117                 if ($current === '') {
118                         $this->out();
119                         $this->out('This system is using legacy storage system');
120                 }
121                 if ($current !== '' && !$isregisterd) {
122                         $this->out();
123                         $this->out('The current storage class (' . $current . ') is not registered!');
124                 }
125                 return 0;
126         }
127
128         protected function doSet()
129         {
130                 if (count($this->args) !== 2) {
131                         throw new CommandArgsException('Invalid arguments');
132                 }
133
134                 $name = $this->args[1];
135                 $class = $this->storageManager->getByName($name);
136
137                 if ($class === '') {
138                         $this->out($name . ' is not a registered backend.');
139                         return -1;
140                 }
141
142                 if (!$this->storageManager->setBackend($class)) {
143                         $this->out($class . ' is not a valid backend storage class.');
144                         return -1;
145                 }
146
147                 return 0;
148         }
149
150         protected function doMove()
151         {
152                 if (count($this->args) < 1 || count($this->args) > 2) {
153                         throw new CommandArgsException('Invalid arguments');
154                 }
155
156                 if (count($this->args) == 2) {
157                         $table = strtolower($this->args[1]);
158                         if (!in_array($table, ['photo', 'attach'])) {
159                                 throw new CommandArgsException('Invalid table');
160                         }
161                         $tables = [$table];
162                 } else {
163                         $tables = StorageManager::TABLES;
164                 }
165
166                 $current = $this->storageManager->getBackend();
167                 $total = 0;
168
169                 if (is_null($current)) {
170                         throw new StorageException(sprintf("Cannot move to legacy storage. Please select a storage backend."));
171                 }
172
173                 do {
174                         $moved = $this->storageManager->move($current, $tables, $this->getOption('n', 5000));
175                         if ($moved) {
176                                 $this->out(date('[Y-m-d H:i:s] ') . sprintf('Moved %d files', $moved));
177                         }
178
179                         $total += $moved;
180                 } while ($moved);
181
182                 $this->out(sprintf(date('[Y-m-d H:i:s] ') . 'Moved %d files total', $total));
183         }
184 }