]> git.mxchange.org Git - friendica.git/blob - src/Model/Attach.php
Merge pull request #6598 from annando/worker-index
[friendica.git] / src / Model / Attach.php
1 <?php
2
3 /**
4  * @file src/Model/Attach.php
5  * @brief This file contains the Attach class for database interface
6  */
7 namespace Friendica\Model;
8
9 use Friendica\BaseObject;
10 use Friendica\Core\StorageManager;
11 use Friendica\Core\System;
12 use Friendica\Database\DBA;
13 use Friendica\Database\DBStructure;
14 use Friendica\Model\Storage\IStorage;
15 use Friendica\Object\Image;
16 use Friendica\Util\DateTimeFormat;
17 use Friendica\Util\Mimetype;
18 use Friendica\Util\Security;
19
20 /**
21  * Class to handle attach dabatase table
22  */
23 class Attach extends BaseObject
24 {
25
26         /**
27          * @brief Return a list of fields that are associated with the attach table
28          *
29          * @return array field list
30          * @throws \Exception
31          */
32         private static function getFields()
33         {
34                 $allfields = DBStructure::definition(self::getApp()->getBasePath(), false);
35                 $fields = array_keys($allfields['attach']['fields']);
36                 array_splice($fields, array_search('data', $fields), 1);
37                 return $fields;
38         }
39
40         /**
41          * @brief Select rows from the attach table
42          *
43          * @param array $fields     Array of selected fields, empty for all
44          * @param array $conditions Array of fields for conditions
45          * @param array $params     Array of several parameters
46          *
47          * @return boolean|array
48          *
49          * @throws \Exception
50          * @see   \Friendica\Database\DBA::select
51          */
52         public static function select(array $fields = [], array $conditions = [], array $params = [])
53         {
54                 if (empty($fields)) {
55                         $fields = self::getFields();
56                 }
57
58                 $r = DBA::select('attach', $fields, $conditions, $params);
59                 return DBA::toArray($r);
60         }
61
62         /**
63          * @brief Retrieve a single record from the attach table
64          *
65          * @param array $fields     Array of selected fields, empty for all
66          * @param array $conditions Array of fields for conditions
67          * @param array $params     Array of several parameters
68          *
69          * @return bool|array
70          *
71          * @throws \Exception
72          * @see   \Friendica\Database\DBA::select
73          */
74         public static function selectFirst(array $fields = [], array $conditions = [], array $params = [])
75         {
76                 if (empty($fields)) {
77                         $fields = self::getFields();
78                 }
79
80                 return DBA::selectFirst('attach', $fields, $conditions, $params);
81         }
82
83         /**
84          * @brief Check if attachment with given conditions exists
85          *
86          * @param array $conditions Array of extra conditions
87          *
88          * @return boolean
89          * @throws \Exception
90          */
91         public static function exists(array $conditions)
92         {
93                 return DBA::exists('attach', $conditions);
94         }
95
96         /**
97          * @brief Retrive a single record given the ID
98          *
99          * @param int $id Row id of the record
100          *
101          * @return bool|array
102          *
103          * @throws \Exception
104          * @see   \Friendica\Database\DBA::select
105          */
106         public static function getById($id)
107         {
108                 return self::selectFirst([], ['id' => $id]);
109         }
110
111         /**
112          * @brief Retrive a single record given the ID
113          *
114          * @param int $id Row id of the record
115          *
116          * @return bool|array
117          *
118          * @throws \Exception
119          * @see   \Friendica\Database\DBA::select
120          */
121         public static function getByIdWithPermission($id)
122         {
123                 $r = self::selectFirst(['uid'], ['id' => $id]);
124                 if ($r === false) {
125                         return false;
126                 }
127
128                 $sql_acl = Security::getPermissionsSQLByUserId($r['uid']);
129
130                 $conditions = [
131                         '`id` = ?' . $sql_acl,
132                         $id
133                 ];
134
135                 $item = self::selectFirst([], $conditions);
136
137                 return $item;
138         }
139
140         /**
141          * @brief Get file data for given row id. null if row id does not exist
142          *
143          * @param array $item Attachment data. Needs at least 'id', 'backend-class', 'backend-ref'
144          *
145          * @return string  file data
146          * @throws \Exception
147          */
148         public static function getData($item)
149         {
150                 if ($item['backend-class'] == '') {
151                         // legacy data storage in 'data' column
152                         $i = self::selectFirst(['data'], ['id' => $item['id']]);
153                         if ($i === false) {
154                                 return null;
155                         }
156                         return $i['data'];
157                 } else {
158                         $backendClass = $item['backend-class'];
159                         $backendRef = $item['backend-ref'];
160                         return $backendClass::get($backendRef);
161                 }
162         }
163
164         /**
165          * @brief Store new file metadata in db and binary in default backend
166          *
167          * @param string  $data      Binary data
168          * @param integer $uid       User ID
169          * @param string  $filename  Filename
170          * @param string  $filetype  Mimetype. optional, default = ''
171          * @param integer $filesize  File size in bytes. optional, default = null
172          * @param string  $allow_cid Permissions, allowed contacts. optional, default = ''
173          * @param string  $allow_gid Permissions, allowed groups. optional, default = ''
174          * @param string  $deny_cid  Permissions, denied contacts.optional, default = ''
175          * @param string  $deny_gid  Permissions, denied greoup.optional, default = ''
176          *
177          * @return boolean/integer Row id on success, False on errors
178          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
179          */
180         public static function store($data, $uid, $filename, $filetype = '' , $filesize = null, $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '')
181         {
182                 if ($filetype === '') {
183                         $filetype = Mimetype::getContentType($filename);
184                 }
185
186                 if (is_null($filesize)) {
187                         $filesize = strlen($data);
188                 }
189
190                 /** @var IStorage $backend_class */
191                 $backend_class = StorageManager::getBackend();
192                 $backend_ref = '';
193                 if ($backend_class !== '') {
194                         $backend_ref = $backend_class::put($data);
195                         $data = '';
196                 }
197
198                 $hash = System::createGUID(64);
199                 $created = DateTimeFormat::utcNow();
200
201                 $fields = [
202                         'uid' => $uid,
203                         'hash' => $hash,
204                         'filename' => $filename,
205                         'filetype' => $filetype,
206                         'filesize' => $filesize,
207                         'data' => $data,
208                         'created' => $created,
209                         'edited' => $created,
210                         'allow_cid' => $allow_cid,
211                         'allow_gid' => $allow_gid,
212                         'deny_cid' => $deny_cid,
213                         'deny_gid' => $deny_gid,
214                         'backend-class' => $backend_class,
215                         'backend-ref' => $backend_ref
216                 ];
217
218                 $r = DBA::insert('attach', $fields);
219                 if ($r === true) {
220                         return DBA::lastInsertId();
221                 }
222                 return $r;
223         }
224
225         /**
226          * @brief Store new file metadata in db and binary in default backend from existing file
227          *
228          * @param        $src
229          * @param        $uid
230          * @param string $filename
231          * @param string $allow_cid
232          * @param string $allow_gid
233          * @param string $deny_cid
234          * @param string $deny_gid
235          * @return boolean True on success
236          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
237          */
238         public static function storeFile($src, $uid, $filename = '', $allow_cid = '', $allow_gid = '', $deny_cid = '', $deny_gid = '')
239         {
240                 if ($filename === '') {
241                         $filename = basename($src);
242                 }
243
244                 $data = @file_get_contents($src);
245
246                 return self::store($data, $uid, $filename, '', null, $allow_cid, $allow_gid,  $deny_cid, $deny_gid);
247         }
248
249
250         /**
251          * @brief Update an attached file
252          *
253          * @param array         $fields     Contains the fields that are updated
254          * @param array         $conditions Condition array with the key values
255          * @param Image         $img        Image data to update. Optional, default null.
256          * @param array|boolean $old_fields Array with the old field values that are about to be replaced (true = update on duplicate)
257          *
258          * @return boolean  Was the update successful?
259          *
260          * @throws \Friendica\Network\HTTPException\InternalServerErrorException
261          * @see   \Friendica\Database\DBA::update
262          */
263         public static function update($fields, $conditions, Image $img = null, array $old_fields = [])
264         {
265                 if (!is_null($img)) {
266                         // get items to update
267                         $items = self::select(['backend-class','backend-ref'], $conditions);
268
269                         foreach($items as $item) {
270                                 /** @var IStorage $backend_class */
271                                 $backend_class = (string)$item['backend-class'];
272                                 if ($backend_class !== '') {
273                                         $fields['backend-ref'] = $backend_class::put($img->asString(), $item['backend-ref']);
274                                 } else {
275                                         $fields['data'] = $img->asString();
276                                 }
277                         }
278                 }
279
280                 $fields['edited'] = DateTimeFormat::utcNow();
281
282                 return DBA::update('attach', $fields, $conditions, $old_fields);
283         }
284
285
286         /**
287          * @brief Delete info from table and data from storage
288          *
289          * @param array $conditions Field condition(s)
290          * @param array $options    Options array, Optional
291          *
292          * @return boolean
293          *
294          * @throws \Exception
295          * @see   \Friendica\Database\DBA::delete
296          */
297         public static function delete(array $conditions, array $options = [])
298         {
299                 // get items to delete data info
300                 $items = self::select(['backend-class','backend-ref'], $conditions);
301
302                 foreach($items as $item) {
303                         /** @var IStorage $backend_class */
304                         $backend_class = (string)$item['backend-class'];
305                         if ($backend_class !== '') {
306                                 $backend_class::delete($item['backend-ref']);
307                         }
308                 }
309
310                 return DBA::delete('attach', $conditions, $options);
311         }
312 }