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