Update copyright
[friendica.git/.git] / src / Object / Thread.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2021, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
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.
11  *
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.
16  *
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/>.
19  *
20  */
21
22 namespace Friendica\Object;
23
24 use Friendica\Core\Logger;
25 use Friendica\Core\Protocol;
26 use Friendica\DI;
27 use Friendica\Protocol\Activity;
28 use Friendica\Security\Security;
29
30 /**
31  * A list of threads
32  *
33  * We should think about making this a SPL Iterator
34  */
35 class Thread
36 {
37         /** @var Post[] */
38         private $parents = [];
39         private $mode = null;
40         private $writable = false;
41         private $profile_owner = 0;
42         private $preview = false;
43
44         /**
45          * Constructor
46          *
47          * @param string  $mode     The mode
48          * @param boolean $preview  Are we in the preview mode?
49          * @param boolean $writable Override the writable check
50          * @throws \Exception
51          */
52         public function __construct($mode, $preview, $writable = false)
53         {
54                 $this->setMode($mode, $writable);
55                 $this->preview = $preview;
56         }
57
58         /**
59          * Set the mode we'll be displayed on
60          *
61          * @param string  $mode     The mode to set
62          * @param boolean $writable Override the writable check
63          *
64          * @return void
65          * @throws \Exception
66          */
67         private function setMode($mode, $writable)
68         {
69                 if ($this->getMode() == $mode) {
70                         return;
71                 }
72
73                 $a = DI::app();
74
75                 switch ($mode) {
76                         case 'network':
77                         case 'notes':
78                                 $this->profile_owner = local_user();
79                                 $this->writable = true;
80                                 break;
81                         case 'profile':
82                                 $this->profile_owner = $a->profile['uid'];
83                                 $this->writable = Security::canWriteToUserWall($this->profile_owner);
84                                 break;
85                         case 'display':
86                                 $this->profile_owner = $a->profile['uid'];
87                                 $this->writable = Security::canWriteToUserWall($this->profile_owner) || $writable;
88                                 break;
89                         case 'community':
90                                 $this->profile_owner = 0;
91                                 $this->writable = $writable;
92                                 break;
93                         case 'contacts':
94                                 $this->profile_owner = 0;
95                                 $this->writable = $writable;
96                                 break;
97                         default:
98                                 Logger::log('[ERROR] Conversation::setMode : Unhandled mode ('. $mode .').', Logger::DEBUG);
99                                 return false;
100                                 break;
101                 }
102                 $this->mode = $mode;
103         }
104
105         /**
106          * Get mode
107          *
108          * @return string
109          */
110         public function getMode()
111         {
112                 return $this->mode;
113         }
114
115         /**
116          * Check if page is writable
117          *
118          * @return boolean
119          */
120         public function isWritable()
121         {
122                 return $this->writable;
123         }
124
125         /**
126          * Check if page is a preview
127          *
128          * @return boolean
129          */
130         public function isPreview()
131         {
132                 return $this->preview;
133         }
134
135         /**
136          * Get profile owner
137          *
138          * @return integer
139          */
140         public function getProfileOwner()
141         {
142                 return $this->profile_owner;
143         }
144
145         /**
146          * Add a thread to the conversation
147          *
148          * @param Post $item The item to insert
149          *
150          * @return mixed The inserted item on success
151          *               false on failure
152          * @throws \Exception
153          */
154         public function addParent(Post $item)
155         {
156                 $item_id = $item->getId();
157
158                 if (!$item_id) {
159                         Logger::log('[ERROR] Conversation::addThread : Item has no ID!!', Logger::DEBUG);
160                         return false;
161                 }
162
163                 if ($this->getParent($item->getId())) {
164                         Logger::log('[WARN] Conversation::addThread : Thread already exists ('. $item->getId() .').', Logger::DEBUG);
165                         return false;
166                 }
167
168                 /*
169                  * Only add will be displayed
170                  */
171                 if ($item->getDataValue('network') === Protocol::MAIL && local_user() != $item->getDataValue('uid')) {
172                         Logger::log('[WARN] Conversation::addThread : Thread is a mail ('. $item->getId() .').', Logger::DEBUG);
173                         return false;
174                 }
175
176                 if ($item->getDataValue('verb') === Activity::LIKE || $item->getDataValue('verb') === Activity::DISLIKE) {
177                         Logger::log('[WARN] Conversation::addThread : Thread is a (dis)like ('. $item->getId() .').', Logger::DEBUG);
178                         return false;
179                 }
180
181                 $item->setThread($this);
182                 $this->parents[] = $item;
183
184                 return end($this->parents);
185         }
186
187         /**
188          * Get data in a form usable by a conversation template
189          *
190          * We should find a way to avoid using those arguments (at least most of them)
191          *
192          * @param array $conv_responses data
193          *
194          * @return mixed The data requested on success
195          *               false on failure
196          * @throws \Exception
197          */
198         public function getTemplateData($conv_responses)
199         {
200                 $result = [];
201
202                 foreach ($this->parents as $item) {
203                         if ($item->getDataValue('network') === Protocol::MAIL && local_user() != $item->getDataValue('uid')) {
204                                 continue;
205                         }
206
207                         $item_data = $item->getTemplateData($conv_responses);
208
209                         if (!$item_data) {
210                                 Logger::log('[ERROR] Conversation::getTemplateData : Failed to get item template data ('. $item->getId() .').', Logger::DEBUG);
211                                 return false;
212                         }
213                         $result[] = $item_data;
214                 }
215
216                 return $result;
217         }
218
219         /**
220          * Get a thread based on its item id
221          *
222          * @param integer $id Item id
223          *
224          * @return mixed The found item on success
225          *               false on failure
226          */
227         private function getParent($id)
228         {
229                 foreach ($this->parents as $item) {
230                         if ($item->getId() == $id) {
231                                 return $item;
232                         }
233                 }
234
235                 return false;
236         }
237 }