3 * @copyright Copyright (C) 2020, Friendica
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Model\Post;
24 use Friendica\Core\Logger;
25 use Friendica\Core\System;
26 use Friendica\Database\DBA;
27 use Friendica\Util\Images;
32 * This Model class handles media interactions.
33 * This tables stores medias (images, videos, audio files) related to posts.
44 * Insert a post-media record
49 public static function insert(array $media)
51 if (empty($media['url']) || empty($media['uri-id'])) {
55 if (DBA::exists('post-media', ['uri-id' => $media['uri-id'], 'url' => $media['url']])) {
56 Logger::info('Media already exists', ['uri-id' => $media['uri-id'], 'url' => $media['url'], 'callstack' => System::callstack()]);
60 $fields = ['type', 'mimetype', 'height', 'width', 'size', 'preview', 'preview-height', 'preview-width', 'description'];
61 foreach ($fields as $field) {
62 if (empty($media[$field])) {
63 unset($media[$field]);
67 if ($media['type'] == self::IMAGE) {
68 $imagedata = Images::getInfoFromURLCached($media['url']);
69 if (!empty($imagedata)) {
70 $media['mimetype'] = $imagedata['mime'];
71 $media['size'] = $imagedata['size'];
72 $media['width'] = $imagedata[0];
73 $media['height'] = $imagedata[1];
75 if (!empty($media['preview'])) {
76 $imagedata = Images::getInfoFromURLCached($media['preview']);
77 if (!empty($imagedata)) {
78 $media['preview-width'] = $imagedata[0];
79 $media['preview-height'] = $imagedata[1];
84 $result = DBA::insert('post-media', $media, true);
85 Logger::info('Stored media', ['result' => $result, 'media' => $media, 'callstack' => System::callstack()]);
89 * Tests for path patterns that are usef for picture links in Friendica
91 * @param string $page Link to the image page
92 * @param string $preview Preview picture
95 private static function isPictureLink(string $page, string $preview)
97 return preg_match('#/photos/.*/image/#ism', $page) && preg_match('#/photo/.*-1\.#ism', $preview);
101 * Add media links and remove them from the body
103 * @param integer $uriid
104 * @param string $body
105 * @return string Body without media links
107 public static function addAttachmentsFromBody(int $uriid, string $body)
109 // Simplify image codes
110 $body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body);
113 if (preg_match_all("#\[url=([^\]]+?)\]\s*\[img=([^\[\]]*)\]([^\[\]]*)\[\/img\]\s*\[/url\]#ism", $body, $pictures, PREG_SET_ORDER)) {
114 foreach ($pictures as $picture) {
115 if (!self::isPictureLink($picture[1], $picture[2])) {
118 $body = str_replace($picture[0], '', $body);
119 $image = str_replace('-1.', '-0.', $picture[2]);
120 $attachments[] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $image,
121 'preview' => $picture[2], 'description' => $picture[3]];
125 if (preg_match_all("/\[img=([^\[\]]*)\]([^\[\]]*)\[\/img\]/Usi", $body, $pictures, PREG_SET_ORDER)) {
126 foreach ($pictures as $picture) {
127 $body = str_replace($picture[0], '', $body);
128 $attachments[] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $picture[1], 'description' => $picture[2]];
132 if (preg_match_all("#\[url=([^\]]+?)\]\s*\[img\]([^\[]+?)\[/img\]\s*\[/url\]#ism", $body, $pictures, PREG_SET_ORDER)) {
133 foreach ($pictures as $picture) {
134 if (!self::isPictureLink($picture[1], $picture[2])) {
137 $body = str_replace($picture[0], '', $body);
138 $image = str_replace('-1.', '-0.', $picture[2]);
139 $attachments[] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $image,
140 'preview' => $picture[2], 'description' => null];
144 if (preg_match_all("/\[img\]([^\[\]]*)\[\/img\]/ism", $body, $pictures, PREG_SET_ORDER)) {
145 foreach ($pictures as $picture) {
146 $body = str_replace($picture[0], '', $body);
147 $attachments[] = ['uri-id' => $uriid, 'type' => self::IMAGE, 'url' => $picture[1]];
151 /// @todo audio + video
152 if (preg_match_all("/\[audio\]([^\[\]]*)\[\/audio\]/ism", $body, $audios, PREG_SET_ORDER)) {
153 foreach ($audios as $audio) {
154 $body = str_replace($audio[0], '', $body);
155 $attachments[] = ['uri-id' => $uriid, 'type' => self::AUDIO, 'url' => $audio[1]];
159 if (preg_match_all("/\[video\]([^\[\]]*)\[\/video\]/ism", $body, $videos, PREG_SET_ORDER)) {
160 foreach ($videos as $video) {
161 $body = str_replace($video[0], '', $body);
162 $attachments[] = ['uri-id' => $uriid, 'type' => self::VIDEO, 'url' => $video[1]];
166 foreach ($attachments as $attachment) {
167 self::insert($attachment);