]> git.mxchange.org Git - friendica.git/blob - src/App/Mode.php
Merge pull request #9963 from mexon/mat/support-cid-scheme
[friendica.git] / src / App / Mode.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\App;
23
24 use Detection\MobileDetect;
25 use Friendica\Core\Config\Cache;
26 use Friendica\Database\Database;
27 use Friendica\Util\BasePath;
28
29 /**
30  * Mode of the current Friendica Node
31  *
32  * @package Friendica\App
33  */
34 class Mode
35 {
36         const LOCALCONFIGPRESENT  = 1;
37         const DBAVAILABLE         = 2;
38         const DBCONFIGAVAILABLE   = 4;
39         const MAINTENANCEDISABLED = 8;
40
41         const UNDEFINED = 0;
42         const INDEX = 1;
43         const DAEMON = 2;
44         const WORKER = 3;
45
46         const BACKEND_CONTENT_TYPES = ['application/jrd+json', 'text/xml',
47                 'application/rss+xml', 'application/atom+xml', 'application/activity+json'];
48
49         /***
50          * @var int The mode of this Application
51          *
52          */
53         private $mode;
54
55         /***
56          * @var int Who executes this Application
57          *
58          */
59         private $executor = self::UNDEFINED;
60
61         /**
62          * @var bool True, if the call is a backend call
63          */
64         private $isBackend;
65
66         /**
67          * @var bool True, if the call is a ajax call
68          */
69         private $isAjax;
70
71         /**
72          * @var bool True, if the call is from a mobile device
73          */
74         private $isMobile;
75
76         /**
77          * @var bool True, if the call is from a tablet device
78          */
79         private $isTablet;
80
81         public function __construct(int $mode = 0, bool $isBackend = false, bool $isAjax = false, bool $isMobile = false, bool $isTablet = false)
82         {
83                 $this->mode      = $mode;
84                 $this->isBackend = $isBackend;
85                 $this->isAjax    = $isAjax;
86                 $this->isMobile  = $isMobile;
87                 $this->isTablet  = $isTablet;
88         }
89
90         /**
91          * Sets the App mode
92          *
93          * - App::MODE_INSTALL    : Either the database connection can't be established or the config table doesn't exist
94          * - App::MODE_MAINTENANCE: The maintenance mode has been set
95          * - App::MODE_NORMAL     : Normal run with all features enabled
96          *
97          * @return Mode returns the determined mode
98          *
99          * @throws \Exception
100          */
101         public function determine(BasePath $basepath, Database $database, Cache $configCache)
102         {
103                 $mode = 0;
104
105                 $basepathName = $basepath->getPath();
106
107                 if (!file_exists($basepathName . '/config/local.config.php')
108                     && !file_exists($basepathName . '/config/local.ini.php')
109                     && !file_exists($basepathName . '/.htconfig.php')) {
110                         return new Mode($mode);
111                 }
112
113                 $mode |= Mode::LOCALCONFIGPRESENT;
114
115                 if (!$database->connected()) {
116                         return new Mode($mode);
117                 }
118
119                 $mode |= Mode::DBAVAILABLE;
120
121                 if ($database->fetchFirst("SHOW TABLES LIKE 'config'") === false) {
122                         return new Mode($mode);
123                 }
124
125                 $mode |= Mode::DBCONFIGAVAILABLE;
126
127                 if (!empty($configCache->get('system', 'maintenance')) ||
128                     // Don't use Config or Configuration here because we're possibly BEFORE initializing the Configuration,
129                     // so this could lead to a dependency circle
130                     !empty($database->selectFirst('config', ['v'], ['cat' => 'system', 'k' => 'maintenance'])['v'])) {
131                         return new Mode($mode);
132                 }
133
134                 $mode |= Mode::MAINTENANCEDISABLED;
135
136                 return new Mode($mode, $this->isBackend, $this->isAjax, $this->isMobile, $this->isTablet);
137         }
138
139         /**
140          * Checks if the site is called via a backend process
141          *
142          * @param bool         $isBackend    True, if the call is from a backend script (daemon, worker, ...)
143          * @param Module       $module       The pre-loaded module (just name, not class!)
144          * @param array        $server       The $_SERVER variable
145          * @param MobileDetect $mobileDetect The mobile detection library
146          *
147          * @return Mode returns the determined mode
148          */
149         public function determineRunMode(bool $isBackend, Module $module, array $server, MobileDetect $mobileDetect)
150         {
151                 foreach (self::BACKEND_CONTENT_TYPES as $type) {
152                         if (strpos(strtolower($server['HTTP_ACCEPT'] ?? ''), $type) !== false) {
153                                 $isBackend = true;
154                         }
155                 }
156
157                 $isBackend = $isBackend || $module->isBackend();
158                 $isMobile  = $mobileDetect->isMobile();
159                 $isTablet  = $mobileDetect->isTablet();
160                 $isAjax    = strtolower($server['HTTP_X_REQUESTED_WITH'] ?? '') == 'xmlhttprequest';
161
162                 return new Mode($this->mode, $isBackend, $isAjax, $isMobile, $isTablet);
163         }
164
165         /**
166          * Checks, if the Friendica Node has the given mode
167          *
168          * @param int $mode A mode to test
169          *
170          * @return bool returns true, if the mode is set
171          */
172         public function has($mode)
173         {
174                 return ($this->mode & $mode) > 0;
175         }
176
177         /**
178          * Set the execution mode
179          *
180          * @param integer $executor Execution Mode
181          * @return void
182          */
183         public function setExecutor(int $executor)
184         {
185                 $this->executor = $executor;
186
187                 // Daemon and worker are always backend
188                 if (in_array($executor, [self::DAEMON, self::WORKER])) {
189                         $this->isBackend = true;
190                 }
191         }
192
193         /*isBackend = true;*
194          * get the execution mode
195          *
196          * @return int Execution Mode
197          */
198         public function getExecutor()
199         {
200                 return $this->executor;
201         }
202
203         /**
204          * Install mode is when the local config file is missing or the DB schema hasn't been installed yet.
205          *
206          * @return bool
207          */
208         public function isInstall()
209         {
210                 return !$this->has(Mode::LOCALCONFIGPRESENT) ||
211                        !$this->has(MODE::DBCONFIGAVAILABLE);
212         }
213
214         /**
215          * Normal mode is when the local config file is set, the DB schema is installed and the maintenance mode is off.
216          *
217          * @return bool
218          */
219         public function isNormal()
220         {
221                 return $this->has(Mode::LOCALCONFIGPRESENT) &&
222                        $this->has(Mode::DBAVAILABLE) &&
223                        $this->has(Mode::DBCONFIGAVAILABLE) &&
224                        $this->has(Mode::MAINTENANCEDISABLED);
225         }
226
227         /**
228          * Returns true, if the call is from a backend node (f.e. from a worker)
229          *
230          * @return bool Is it a backend call
231          */
232         public function isBackend()
233         {
234                 return $this->isBackend;
235         }
236
237         /**
238          * Check if request was an AJAX (xmlhttprequest) request.
239          *
240          * @return bool true if it was an AJAX request
241          */
242         public function isAjax()
243         {
244                 return $this->isAjax;
245         }
246
247         /**
248          * Check if request was a mobile request.
249          *
250          * @return bool true if it was an mobile request
251          */
252         public function isMobile()
253         {
254                 return $this->isMobile;
255         }
256
257         /**
258          * Check if request was a tablet request.
259          *
260          * @return bool true if it was an tablet request
261          */
262         public function isTablet()
263         {
264                 return $this->isTablet;
265         }
266 }