]> git.mxchange.org Git - friendica.git/blob - src/Database/View.php
Merge remote-tracking branch 'upstream/develop' into item-view
[friendica.git] / src / Database / View.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2020, Friendica
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\Database;
23
24 use Exception;
25 use Friendica\Core\Hook;
26 use Friendica\DI;
27
28 class View
29 {
30         /**
31          * view definition loaded from static/dbview.config.php
32          *
33          * @var array
34          */
35         private static $definition = [];
36
37         /**
38          * Loads the database structure definition from the static/dbview.config.php file.
39          * On first pass, defines DB_UPDATE_VERSION constant.
40          *
41          * @see static/dbview.config.php
42          * @param boolean $with_addons_structure Whether to tack on addons additional tables
43          * @param string  $basePath              The base path of this application
44          * @return array
45          * @throws Exception
46          */
47         public static function definition($basePath = '', $with_addons_structure = true)
48         {
49                 if (!self::$definition) {
50                         if (empty($basePath)) {
51                                 $basePath = DI::app()->getBasePath();
52                         }
53
54                         $filename = $basePath . '/static/dbview.config.php';
55
56                         if (!is_readable($filename)) {
57                                 throw new Exception('Missing database view config file static/dbview.config.php');
58                         }
59
60                         $definition = require $filename;
61
62                         if (!$definition) {
63                                 throw new Exception('Corrupted database view config file static/dbview.config.php');
64                         }
65
66                         self::$definition = $definition;
67                 } else {
68                         $definition = self::$definition;
69                 }
70
71                 if ($with_addons_structure) {
72                         Hook::callAll('dbview_definition', $definition);
73                 }
74
75                 return $definition;
76         }
77
78         public static function create(bool $verbose, bool $action)
79         {
80                 $definition = self::definition();
81
82                 foreach ($definition as $name => $structure) {
83                         self::createview($name, $structure, $verbose, $action);
84                 }
85         }
86
87         public static function printStructure($basePath)
88         {
89                 $database = self::definition($basePath, false);
90
91                 foreach ($database AS $name => $structure) {
92                         echo "--\n";
93                         echo "-- VIEW $name\n";
94                         echo "--\n";
95                         self::createView($name, $structure, true, false);
96
97                         echo "\n";
98                 }
99         }
100
101         private static function createview($name, $structure, $verbose, $action)
102         {
103                 $r = true;
104
105                 $sql_rows = [];
106                 foreach ($structure["fields"] AS $fieldname => $origin) {
107                         if (is_string($origin)) {
108                                 $sql_rows[] = $origin . " AS `" . DBA::escape($fieldname) . "`";
109                         } elseif (is_array($origin) && (sizeof($origin) == 2)) {
110                                 $sql_rows[] = "`" . DBA::escape($origin[0]) . "`.`" . DBA::escape($origin[1]) . "` AS `" . DBA::escape($fieldname) . "`";
111                         }
112                 }
113
114                 if (self::isView($name)) {
115                         $sql = sprintf("DROP VIEW IF EXISTS `%s`", DBA::escape($name));
116                 } elseif (self::isTable($name)) {
117                         $sql = sprintf("DROP TABLE IF EXISTS `%s`", DBA::escape($name));
118                 }
119
120                 if (!empty($sql) && $verbose) {
121                         echo $sql . ";\n";
122                 }
123
124                 if (!empty($sql) && $action) {
125                         DBA::e($sql);
126                 }
127
128                 $sql = sprintf("CREATE VIEW `%s` AS SELECT \n\t", DBA::escape($name)) .
129                         implode(",\n\t", $sql_rows) . "\n\t" . $structure['query'];
130         
131                 if ($verbose) {
132                         echo $sql . ";\n";
133                 }
134
135                 if ($action) {
136                         $r = DBA::e($sql);
137                 }
138
139                 return $r;
140         }
141
142         /**
143          * Check if the given table/view is a view
144          *
145          * @param string $view
146          * @return boolean "true" if it's a view
147          */
148         private static function isView(string $view)
149         {
150                 $status = DBA::selectFirst(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_TYPE'],
151                         ['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_NAME' => $view]);
152
153                 if (empty($status['TABLE_TYPE'])) {
154                         return false;
155                 }
156
157                 return $status['TABLE_TYPE'] == 'VIEW';
158         }
159
160         /**
161          * Check if the given table/view is a table
162          *
163          * @param string $table
164          * @return boolean "true" if it's a table
165          */
166         private static function isTable(string $table)
167         {
168                 $status = DBA::selectFirst(['INFORMATION_SCHEMA' => 'TABLES'], ['TABLE_TYPE'],
169                         ['TABLE_SCHEMA' => DBA::databaseName(), 'TABLE_NAME' => $table]);
170
171                 if (empty($status['TABLE_TYPE'])) {
172                         return false;
173                 }
174
175                 return $status['TABLE_TYPE'] == 'BASE TABLE';
176         }
177 }