* * This source file is subject to the GPL-3.0 license that is bundled * with this source code in the file LICENSE. */ namespace controllers\internals; class Media extends StandardController { const DEFAULT_CHMOD = 0660; protected $model; /** * Create a media. * * @param int $id_user : Id of the user * @param string $tmpfile_path : Path of the temporary local copy of the media * @param ?string $extension : Extension to use for the media * * @return int : Exception on error, new media id else */ public function create(int $id_user, string $tmpfile_path, ?string $extension = null) { $user_path = \controllers\internals\Tool::create_user_public_path($id_user); if (!file_exists($tmpfile_path)) { throw new \Exception('File ' . $tmpfile_path . ' does not exists.'); } if (!is_readable($tmpfile_path)) { throw new \Exception('File ' . $tmpfile_path . ' is not readable.'); } $mimey = new \Mimey\MimeTypes(); $extension = $extension ?? $mimey->getExtension(mime_content_type($tmpfile_path)); $new_file_name = \controllers\internals\Tool::random_uuid() . '.' . $extension; $new_file_path = $user_path . '/' . $new_file_name; $new_file_relpath = $id_user . '/' . $new_file_name; if (!file_put_contents($new_file_path, 'a')) { throw new \Exception('Cannot write file ' . $new_file_path); } if (!rename($tmpfile_path, $new_file_path)) { throw new \Exception('Cannot create file ' . $new_file_path); } if (!chmod($new_file_path, self::DEFAULT_CHMOD)) { throw new \Exception('Cannot give file ' . $new_file_path . ' rights : ' . self::DEFAULT_CHMOD); } $data = [ 'path' => $new_file_relpath, 'id_user' => $id_user, ]; $new_media_id = $this->get_model()->insert($data); if (!$new_media_id) { throw new \Exception('Cannot insert media in database.'); } return $new_media_id; } /** * Upload and create a media. * * @param int $id_user : Id of the user * @param array $file : array representing uploaded file, extracted from $_FILES['yourfile'] * * @return int : Raise exception on error or return new media id on success */ public function create_from_uploaded_file_for_user(int $id_user, array $file) { $upload_result = \controllers\internals\Tool::read_uploaded_file($file); if (true !== $upload_result['success']) { throw new \Exception($upload_result['content']); } //Move uploaded file to a tmp file if (!$tmp_file = tempnam('/tmp', 'raspisms-media-')) { throw new \Exception('Cannot create tmp file in /tmp to store the uploaded file.'); } if (!move_uploaded_file($upload_result['tmp_name'], $tmp_file)) { throw new \Exception('Cannot move uploaded file to : ' . $tmp_file); } return $this->create($id_user, $tmp_file, $upload_result['extension']); } /** * Link a media to a scheduled, a received or a sended message. * * @param int $id_media : Id of the media * @param string $resource_type : Type of resource to link the media to ('scheduled', 'received' or 'sended') * @param int $resource_id : Id of the resource to link the media to * * @return mixed bool|int : false on error, the new link id else */ public function link_to(int $id_media, string $resource_type, int $resource_id) { switch ($resource_type) { case 'scheduled': return $this->get_model()->insert_media_scheduled($id_media, $resource_id); break; case 'received': return $this->get_model()->insert_media_received($id_media, $resource_id); break; case 'sended': return $this->get_model()->insert_media_sended($id_media, $resource_id); break; default: return false; } } /** * Unlink a media of a scheduled, a received or a sended message. * * @param int $id_media : Id of the media * @param string $resource_type : Type of resource to unlink the media of ('scheduled', 'received' or 'sended') * @param int $resource_id : Id of the resource to unlink the media of * * @return mixed bool : false on error, true on success */ public function unlink_of(int $id_media, int $resource_type, int $resource_id) { switch ($resource_type) { case 'scheduled': return $this->get_model()->delete_media_scheduled($id_media, $resource_id); break; case 'received': return $this->get_model()->delete_media_received($id_media, $resource_id); break; case 'sended': return $this->get_model()->delete_media_sended($id_media, $resource_id); break; default: return false; } } /** * Unlink all medias of a scheduled, a received or a sended message. * * @param string $resource_type : Type of resource to unlink the media of ('scheduled', 'received' or 'sended') * @param int $resource_id : Id of the resource to unlink the media of * * @return mixed bool : false on error, true on success */ public function unlink_all_of(string $resource_type, int $resource_id) { switch ($resource_type) { case 'scheduled': return $this->get_model()->delete_all_for_scheduled($resource_id); break; case 'received': return $this->get_model()->delete_all_for_received($resource_id); break; case 'sended': return $this->get_model()->delete_all_for_sended($resource_id); break; default: return false; } } /** * Update a media for a user. * * @param int $id_user : user id * @param int $id_media : Media id * @param string $path : Path of the file * * @return bool : false on error, true on success */ public function update_for_user(int $id_user, int $id_media, string $path): bool { $media = [ 'path' => $path, ]; return (bool) $this->get_model()->update_for_user($id_user, $id_media, $media); } /** * Delete a media for a user. * * @param int $id_user : User id * @param int $id : Entry id * * @return mixed bool|int : False on error, else number of removed rows */ public function delete_for_user(int $id_user, int $id_media): bool { $media = $this->get_model()->get_for_user($id_user, $id_media); if (!$media) { return false; } //Delete file try { $filepath = PWD_DATA_PUBLIC . '/' . $media['path']; if (file_exists($filepath)) { unlink($filepath); } } catch (\Throwable $t) { return false; } return $this->get_model()->delete_for_user($id_user, $id_media); } /** * Find medias for a scheduled. * * @param int $id_scheduled : Scheduled id to fin medias for * * @return mixed : Medias || false */ public function gets_for_scheduled(int $id_scheduled) { return $this->get_model()->gets_for_scheduled($id_scheduled); } /** * Find medias for a sended and a user. * * @param int $id_sended : Scheduled id to fin medias for * * @return mixed : Medias || false */ public function gets_for_sended(int $id_sended) { return $this->get_model()->gets_for_sended($id_sended); } /** * Find medias for a received and a user. * * @param int $id_received : Scheduled id to fin medias for * * @return mixed : Medias || false */ public function gets_for_received(int $id_received) { return $this->get_model()->gets_for_received($id_received); } /** * Find medias that are not used. * * @return array */ public function gets_unused() { return $this->get_model()->gets_unused(); } /** * Get the model for the Controller. */ protected function get_model(): \models\Media { $this->model = $this->model ?? new \models\Media($this->bdd); return $this->model; } }