]> git.mxchange.org Git - friendica.git/blob - src/Model/Storage/Filesystem.php
Merge pull request #7372 from nupplaphil/task/simplify_config
[friendica.git] / src / Model / Storage / Filesystem.php
1 <?php
2 /**
3  * @file src/Model/Storage/Filesystem.php
4  * @brief Storage backend system
5  */
6
7 namespace Friendica\Model\Storage;
8
9 use Friendica\Core\Config;
10 use Friendica\Core\L10n;
11 use Friendica\Core\Logger;
12 use Friendica\Util\Strings;
13
14 /**
15  * @brief Filesystem based storage backend
16  *
17  * This class manage data on filesystem.
18  * Base folder for storage is set in storage.filesystem_path.
19  * Best would be for storage folder to be outside webserver folder, we are using a
20  * folder relative to code tree root as default to ease things for users in shared hostings.
21  * Each new resource gets a value as reference and is saved in a
22  * folder tree stucture created from that value.
23  */
24 class Filesystem implements IStorage
25 {
26         // Default base folder
27         const DEFAULT_BASE_FOLDER = 'storage';
28
29         private static function getBasePath()
30         {
31                 $path = Config::get('storage', 'filesystem_path', self::DEFAULT_BASE_FOLDER);
32                 return rtrim($path, '/');
33         }
34
35         /**
36          * @brief Split data ref and return file path
37          * @param string  $ref  Data reference
38          * @return string
39          */
40         private static function pathForRef($ref)
41         {
42                 $base = self::getBasePath();
43                 $fold1 = substr($ref, 0, 2);
44                 $fold2 = substr($ref, 2, 2);
45                 $file = substr($ref, 4);
46
47                 return implode('/', [$base, $fold1, $fold2, $file]);
48         }
49
50
51         /**
52          * @brief Create dirctory tree to store file, with .htaccess and index.html files
53          * @param string $file Path and filename
54          * @throws StorageException
55          */
56         private static function createFoldersForFile($file)
57         {
58                 $path = dirname($file);
59
60                 if (!is_dir($path)) {
61                         if (!mkdir($path, 0770, true)) {
62                                 Logger::log('Failed to create dirs ' . $path);
63                                 throw new StorageException(L10n::t('Filesystem storage failed to create "%s". Check you write permissions.', $path));
64                         }
65                 }
66
67                 $base = self::getBasePath();
68
69                 while ($path !== $base) {
70                         if (!is_file($path . '/index.html')) {
71                                 file_put_contents($path . '/index.html', '');
72                         }
73                         chmod($path . '/index.html', 0660);
74                         chmod($path, 0770);
75                         $path = dirname($path);
76                 }
77                 if (!is_file($path . '/index.html')) {
78                         file_put_contents($path . '/index.html', '');
79                         chmod($path . '/index.html', 0660);
80                 }
81         }
82
83         public static function get($ref)
84         {
85                 $file = self::pathForRef($ref);
86                 if (!is_file($file)) {
87                         return '';
88                 }
89
90                 return file_get_contents($file);
91         }
92
93         public static function put($data, $ref = '')
94         {
95                 if ($ref === '') {
96                         $ref = Strings::getRandomHex();
97                 }
98                 $file = self::pathForRef($ref);
99
100                 self::createFoldersForFile($file);
101
102                 $r = file_put_contents($file, $data);
103                 if ($r === FALSE) {
104                         Logger::log('Failed to write data to ' . $file);
105                         throw new StorageException(L10n::t('Filesystem storage failed to save data to "%s". Check your write permissions', $file));
106                 }
107                 chmod($file, 0660);
108                 return $ref;
109         }
110
111         public static function delete($ref)
112         {
113                 $file = self::pathForRef($ref);
114                 // return true if file doesn't exists. we want to delete it: success with zero work!
115                 if (!is_file($file)) {
116                         return true;
117                 }
118                 return unlink($file);
119         }
120
121         public static function getOptions()
122         {
123                 return [
124                         'storagepath' => [
125                                 'input',
126                                 L10n::t('Storage base path'),
127                                 self::getBasePath(),
128                                 L10n::t('Folder where uploaded files are saved. For maximum security, This should be a path outside web server folder tree')
129                         ]
130                 ];
131         }
132         
133         public static function saveOptions($data)
134         {
135                 $storagepath = defaults($data, 'storagepath', '');
136                 if ($storagepath === '' || !is_dir($storagepath)) {
137                         return [
138                                 'storagepath' => L10n::t('Enter a valid existing folder')
139                         ];
140                 };
141                 Config::set('storage', 'filesystem_path', $storagepath);
142                 return [];
143         }
144
145 }