1 <?php
  2 
  3 /**
  4  * REX base class for core properties etc.
  5  *
  6  * @author gharlan
  7  *
  8  * @package redaxo\core
  9  */
 10 class rex
 11 {
 12     const CONFIG_NAMESPACE = 'core';
 13 
 14     /**
 15      * Array of properties.
 16      *
 17      * @var array
 18      */
 19     protected static $properties = [];
 20 
 21     /**
 22      * @see rex_config::set()
 23      */
 24     public static function setConfig($key, $value = null)
 25     {
 26         return rex_config::set(self::CONFIG_NAMESPACE, $key, $value);
 27     }
 28 
 29     /**
 30      * @see rex_config::get()
 31      */
 32     public static function getConfig($key = null, $default = null)
 33     {
 34         return rex_config::get(self::CONFIG_NAMESPACE, $key, $default);
 35     }
 36 
 37     /**
 38      * @see rex_config::has()
 39      */
 40     public static function hasConfig($key)
 41     {
 42         return rex_config::has(self::CONFIG_NAMESPACE, $key);
 43     }
 44 
 45     /**
 46      * @see rex_config::remove()
 47      */
 48     public static function removeConfig($key)
 49     {
 50         return rex_config::remove(self::CONFIG_NAMESPACE, $key);
 51     }
 52 
 53     /**
 54      * Sets a property. Changes will not be persisted accross http request boundaries.
 55      *
 56      * @param string $key   Key of the property
 57      * @param mixed  $value Value for the property
 58      *
 59      * @return bool TRUE when an existing value was overridden, otherwise FALSE
 60      *
 61      * @throws InvalidArgumentException on invalid parameters
 62      */
 63     public static function setProperty($key, $value)
 64     {
 65         if (!is_string($key)) {
 66             throw new InvalidArgumentException('Expecting $key to be string, but ' . gettype($key) . ' given!');
 67         }
 68         switch ($key) {
 69             case 'debug':
 70                 // bc for boolean "debug" property
 71                 if (!is_array($value)) {
 72                     $debug = self::getDebugFlags();
 73                     $debug['enabled'] = (bool) $value;
 74                     $value = $debug;
 75                 }
 76                 $value['enabled'] = isset($value['enabled']) && $value['enabled'];
 77                 if (!isset($value['throw_always_exception']) || !$value['throw_always_exception']) {
 78                     $value['throw_always_exception'] = false;
 79                 } elseif (is_array($value['throw_always_exception'])) {
 80                     $value['throw_always_exception'] = array_reduce($value['throw_always_exception'], function ($result, $item) {
 81                         if (is_string($item)) {
 82                             // $item is string, e.g. "E_WARNING"
 83                             $item = constant($item);
 84                         }
 85 
 86                         return $result | $item;
 87                     }, 0);
 88                 }
 89                 break;
 90             case 'server':
 91                 if (!rex_validator::factory()->url($value)) {
 92                     throw new InvalidArgumentException('"' . $key . '" property: expecting $value to be a full URL!');
 93                 }
 94                 $value = rtrim($value, '/') . '/';
 95                 break;
 96             case 'error_email':
 97                 if (null !== $value && !rex_validator::factory()->email($value)) {
 98                     throw new InvalidArgumentException('"' . $key . '" property: expecting $value to be an email address!');
 99                 }
100                 break;
101             case 'console':
102                 if (null !== $value && !$value instanceof rex_console_application) {
103                     throw new InvalidArgumentException(sprintf('"%s" property: expecting $value to be an instance of rex_console_application, "%s" found!', $key, is_object($value) ? get_class($value) : gettype($value)));
104                 }
105         }
106         $exists = isset(self::$properties[$key]);
107         self::$properties[$key] = $value;
108         return $exists;
109     }
110 
111     /**
112      * Returns a property.
113      *
114      * @param string $key     Key of the property
115      * @param mixed  $default Default value, will be returned if the property isn't set
116      *
117      * @return mixed The value for $key or $default if $key cannot be found
118      *
119      * @throws InvalidArgumentException on invalid parameters
120      */
121     public static function getProperty($key, $default = null)
122     {
123         if (!is_string($key)) {
124             throw new InvalidArgumentException('Expecting $key to be string, but ' . gettype($key) . ' given!');
125         }
126         if (isset(self::$properties[$key])) {
127             return self::$properties[$key];
128         }
129         return $default;
130     }
131 
132     /**
133      * Returns if a property is set.
134      *
135      * @param string $key Key of the property
136      *
137      * @return bool TRUE if the key is set, otherwise FALSE
138      */
139     public static function hasProperty($key)
140     {
141         return is_string($key) && isset(self::$properties[$key]);
142     }
143 
144     /**
145      * Removes a property.
146      *
147      * @param string $key Key of the property
148      *
149      * @return bool TRUE if the value was found and removed, otherwise FALSE
150      *
151      * @throws InvalidArgumentException on invalid parameters
152      */
153     public static function removeProperty($key)
154     {
155         if (!is_string($key)) {
156             throw new InvalidArgumentException('Expecting $key to be string, but ' . gettype($key) . ' given!');
157         }
158         $exists = isset(self::$properties[$key]);
159         unset(self::$properties[$key]);
160         return $exists;
161     }
162 
163     /**
164      * Returns if the setup is active.
165      *
166      * @return bool
167      */
168     public static function isSetup()
169     {
170         return (bool) self::getProperty('setup', false);
171     }
172 
173     /**
174      * Returns if the environment is the backend.
175      *
176      * @return bool
177      */
178     public static function isBackend()
179     {
180         return (bool) self::getProperty('redaxo', false);
181     }
182 
183     /**
184      * Returns if the environment is the frontend.
185      *
186      * @return bool
187      */
188     public static function isFrontend()
189     {
190         if (self::getConsole()) {
191             return false;
192         }
193         return !self::getProperty('redaxo', false);
194     }
195 
196     /**
197      * Returns the environment.
198      *
199      * @return string
200      */
201     public static function getEnvironment()
202     {
203         if (self::getConsole()) {
204             return 'console';
205         }
206 
207         return self::isBackend() ? 'backend' : 'frontend';
208     }
209 
210     /**
211      * Returns if the debug mode is active.
212      *
213      * @return bool
214      */
215     public static function isDebugMode()
216     {
217         $debug = self::getDebugFlags();
218 
219         return isset($debug['enabled']) && $debug['enabled'];
220     }
221 
222     /**
223      * Returns the debug flags.
224      *
225      * @return array
226      */
227     public static function getDebugFlags()
228     {
229         return self::getProperty('debug');
230     }
231 
232     /**
233      * Returns if the safe mode is active.
234      *
235      * @return bool
236      */
237     public static function isSafeMode()
238     {
239         return self::isBackend() && PHP_SESSION_ACTIVE == session_status() && rex_session('safemode', 'boolean', false);
240     }
241 
242     /**
243      * Returns the table prefix.
244      *
245      * @return string
246      */
247     public static function getTablePrefix()
248     {
249         return self::getProperty('table_prefix');
250     }
251 
252     /**
253      * Adds the table prefix to the table name.
254      *
255      * @param string $table Table name
256      *
257      * @return string
258      */
259     public static function getTable($table)
260     {
261         return self::getTablePrefix() . $table;
262     }
263 
264     /**
265      * Returns the temp prefix.
266      *
267      * @return string
268      */
269     public static function getTempPrefix()
270     {
271         return self::getProperty('temp_prefix');
272     }
273 
274     /**
275      * Returns the current user.
276      *
277      * @return null|rex_user
278      */
279     public static function getUser()
280     {
281         return self::getProperty('user');
282     }
283 
284     /**
285      * Returns the current impersonator user.
286      *
287      * @return null|rex_user
288      */
289     public static function getImpersonator()
290     {
291         $login = self::getProperty('login');
292 
293         return $login ? $login->getImpersonator() : null;
294     }
295 
296     /**
297      * Returns the console application.
298      *
299      * @return null|rex_console_application
300      */
301     public static function getConsole()
302     {
303         return self::getProperty('console', null);
304     }
305 
306     /**
307      * Returns the server URL.
308      *
309      * @param null|string $protocol
310      *
311      * @return string
312      */
313     public static function getServer($protocol = null)
314     {
315         if (null === $protocol) {
316             return self::getProperty('server');
317         }
318         list(, $server) = explode('://', self::getProperty('server'), 2);
319         return $protocol ? $protocol . '://' . $server : $server;
320     }
321 
322     /**
323      * Returns the server name.
324      *
325      * @return string
326      */
327     public static function getServerName()
328     {
329         return self::getProperty('servername');
330     }
331 
332     /**
333      * Returns the error email.
334      *
335      * @return string
336      */
337     public static function getErrorEmail()
338     {
339         return self::getProperty('error_email');
340     }
341 
342     /**
343      * Returns the redaxo version.
344      *
345      * @param string $format See {@link rex_formatter::version()}
346      *
347      * @return string
348      */
349     public static function getVersion($format = null)
350     {
351         $version = self::getProperty('version');
352 
353         if ($format) {
354             return rex_formatter::version($version, $format);
355         }
356         return $version;
357     }
358 
359     /**
360      * Returns the current git version hash for the given path.
361      *
362      * @param string $path A local filesystem path
363      *
364      * @return false|string
365      */
366     public static function getVersionHash($path)
367     {
368         static $gitHash = [];
369 
370         if (!isset($gitHash[$path])) {
371             $gitHash[$path] = false; // exec only once
372             $output = '';
373             $exitCode = null;
374 
375             if (strcasecmp(substr(PHP_OS, 0, 3), 'WIN') == 0) {
376                 $command = 'where git 2>&1 1>/dev/null && cd '. escapeshellarg($path) .' && git show --oneline -s';
377             } else {
378                 $command = 'which git 2>&1 1>/dev/null && cd '. escapeshellarg($path) .' && git show --oneline -s';
379             }
380 
381             @exec($command, $output, $exitCode);
382             if ($exitCode === 0) {
383                 $output = implode('', $output);
384                 if (preg_match('{^[0-9a-f]+}', $output, $matches)) {
385                     $gitHash[$path] = $matches[0];
386                 }
387             }
388         }
389 
390         return $gitHash[$path];
391     }
392 
393     /**
394      * Returns the title tag and if the property "use_accesskeys" is true, the accesskey tag.
395      *
396      * @param string $title Title
397      * @param string $key   Key for the accesskey
398      *
399      * @return string
400      */
401     public static function getAccesskey($title, $key)
402     {
403         if (self::getProperty('use_accesskeys')) {
404             $accesskeys = (array) self::getProperty('accesskeys', []);
405             if (isset($accesskeys[$key])) {
406                 return ' accesskey="' . $accesskeys[$key] . '" title="' . $title . ' [' . $accesskeys[$key] . ']"';
407             }
408         }
409 
410         return ' title="' . $title . '"';
411     }
412 
413     /**
414      * Returns the file perm.
415      *
416      * @return int
417      */
418     public static function getFilePerm()
419     {
420         return (int) self::getProperty('fileperm', 0664);
421     }
422 
423     /**
424      * Returns the dir perm.
425      *
426      * @return int
427      */
428     public static function getDirPerm()
429     {
430         return (int) self::getProperty('dirperm', 0775);
431     }
432 }
433