Friendica Communications Platform (please note that this is a clone of the repository at github, issues are handled there) https://friendi.ca
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
8.3KB

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