--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2022, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Moderation\Entity;
+
+/**
+ * @property-read int $id
+ * @property-read int $uid
+ * @property-read int $cid
+ * @property-read string $comment
+ * @property-read bool $forward
+ * @property-read array $postUriIds
+ * @property-read \DateTime|null $created
+ */
+class Report extends \Friendica\BaseEntity
+{
+ /** @var int|null */
+ protected $id;
+ /** @var int ID of the user making a moderation report*/
+ protected $uid;
+ /** @var int ID of the contact being reported*/
+ protected $cid;
+ /** @var string Optional comment */
+ protected $comment;
+ /** @var bool Whether this report should be forwarded to the remote server */
+ protected $forward;
+ /** @var \DateTime|null When the report was created */
+ protected $created;
+ /** @var array Optional list of URI IDs of posts supporting the report*/
+ protected $postUriIds;
+
+ public function __construct(int $uid, int $cid, \DateTime $created, string $comment = '', bool $forward = false, array $postUriIds = [], int $id = null)
+ {
+ $this->uid = $uid;
+ $this->cid = $cid;
+ $this->created = $created;
+ $this->comment = $comment;
+ $this->forward = $forward;
+ $this->postUriIds = $postUriIds;
+ $this->id = $id;
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2022, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Moderation\Factory;
+
+use Friendica\Capabilities\ICanCreateFromTableRow;
+use Friendica\Moderation\Entity;
+
+class Report extends \Friendica\BaseFactory implements ICanCreateFromTableRow
+{
+ /**
+ * @param array $row `report` table row
+ * @param array $postUriIds List of post URI ids from the `report-post` table
+ * @return Entity\Report
+ * @throws \Exception
+ */
+ public function createFromTableRow(array $row, array $postUriIds = []): Entity\Report
+ {
+ return new Entity\Report(
+ $row['uid'],
+ $row['cid'],
+ new \DateTime($row['created'] ?? 'now', new \DateTimeZone('UTC')),
+ $row['comment'],
+ $row['forward'],
+ $postUriIds,
+ $row['id'],
+ );
+ }
+
+ /**
+ * Creates a Report entity from a Mastodon API /reports request
+ *
+ * @see \Friendica\Module\Api\Mastodon\Reports::post()
+ *
+ * @param int $uid
+ * @param int $cid
+ * @param string $comment
+ * @param bool $forward
+ * @param array $postUriIds
+ * @return Entity\Report
+ * @throws \Exception
+ */
+ public function createFromReportsRequest(int $uid, int $cid, string $comment = '', bool $forward = false, array $postUriIds = []): Entity\Report
+ {
+ return new Entity\Report(
+ $uid,
+ $cid,
+ new \DateTime('now', new \DateTimeZone('UTC')),
+ $comment,
+ $forward,
+ $postUriIds,
+ );
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2022, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Moderation\Repository;
+
+use Friendica\BaseEntity;
+use Friendica\Core\Logger;
+use Friendica\Database\Database;
+use Friendica\Model\Post;
+use Friendica\Network\HTTPException\NotFoundException;
+use Friendica\Util\DateTimeFormat;
+use Psr\Log\LoggerInterface;
+
+class Report extends \Friendica\BaseRepository
+{
+ protected static $table_name = 'report';
+
+ /**
+ * @var \Friendica\Moderation\Factory\Report
+ */
+ protected $factory;
+
+ public function __construct(Database $database, LoggerInterface $logger, \Friendica\Moderation\Factory\Report $factory)
+ {
+ parent::__construct($database, $logger, $factory);
+
+ $this->factory = $factory;
+ }
+
+ public function selectOneById(int $lastInsertId): \Friendica\Moderation\Factory\Report
+ {
+ return $this->_selectOne(['id' => $lastInsertId]);
+ }
+
+ public function save(\Friendica\Moderation\Entity\Report $Report)
+ {
+ $fields = [
+ 'uid' => $Report->uid,
+ 'cid' => $Report->cid,
+ 'comment' => $Report->comment,
+ 'forward' => $Report->forward,
+ ];
+
+ if ($Report->id) {
+ $this->db->update(self::$table_name, $fields, ['id' => $Report->id]);
+ } else {
+ $fields['created'] = DateTimeFormat::utcNow();
+ $this->db->insert(self::$table_name, $fields, Database::INSERT_IGNORE);
+
+ $Report = $this->selectOneById($this->db->lastInsertId());
+ }
+
+ $this->db->delete('report-post', ['rid' => $Report->id]);
+
+ foreach ($Report->postUriIds as $uriId) {
+ if (Post::exists(['uri-id' => $uriId])) {
+ $this->db->insert('report-post', ['rid' => $Report->id, 'uri-id' => $uriId]);
+ } else {
+ Logger::notice('Post does not exist', ['uri-id' => $uriId, 'report' => $Report]);
+ }
+ }
+
+ return $Report;
+ }
+
+ protected function _selectOne(array $condition, array $params = []): BaseEntity
+ {
+ $fields = $this->db->selectFirst(static::$table_name, [], $condition, $params);
+ if (!$this->db->isResult($fields)) {
+ throw new NotFoundException();
+ }
+
+ $postUriIds = array_column($this->db->selectToArray('report-post', ['uri-id'], ['rid' => $condition['id'] ?? 0]), 'uri-id');
+
+ return $this->factory->createFromTableRow($fields, $postUriIds);
+ }
+}
--- /dev/null
+<?php
+/**
+ * @copyright Copyright (C) 2010-2022, the Friendica project
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace Friendica\Test\src\Moderation\Factory;
+
+use Friendica\Moderation\Factory;
+use Friendica\Moderation\Entity;
+use Friendica\Test\MockedTest;
+use Psr\Log\NullLogger;
+
+class ReportTest extends MockedTest
+{
+ public function dataCreateFromTableRow(): array
+ {
+ return [
+ 'default' => [
+ 'row' => [
+ 'id' => 11,
+ 'uid' => 12,
+ 'cid' => 13,
+ 'comment' => '',
+ 'forward' => false,
+ 'created' => null
+ ],
+ 'postUriIds' => [],
+ 'assertion' => new Entity\Report(
+ 12,
+ 13,
+ new \DateTime('now', new \DateTimeZone('UTC')),
+ '',
+ false,
+ [],
+ 11,
+ ),
+ ],
+ 'full' => [
+ 'row' => [
+ 'id' => 11,
+ 'uid' => 12,
+ 'cid' => 13,
+ 'comment' => 'Report',
+ 'forward' => true,
+ 'created' => '2021-10-12 12:23:00'
+ ],
+ 'postUriIds' => [89, 90],
+ 'assertion' => new Entity\Report(
+ 12,
+ 13,
+ new \DateTime('2021-10-12 12:23:00', new \DateTimeZone('UTC')),
+ 'Report',
+ true,
+ [89, 90],
+ 11
+ ),
+ ],
+ ];
+ }
+
+ public function assertReport(Entity\Report $assertion, Entity\Report $report)
+ {
+ self::assertEquals(
+ $assertion->id,
+ $report->id
+ );
+ self::assertEquals($assertion->uid, $report->uid);
+ self::assertEquals($assertion->cid, $report->cid);
+ self::assertEquals($assertion->comment, $report->comment);
+ self::assertEquals($assertion->forward, $report->forward);
+ // No way to test "now" at the moment
+ //self::assertEquals($assertion->created, $report->created);
+ self::assertEquals($assertion->postUriIds, $report->postUriIds);
+ }
+
+ /**
+ * @dataProvider dataCreateFromTableRow
+ */
+ public function testCreateFromTableRow(array $row, array $postUriIds, Entity\Report $assertion)
+ {
+ $factory = new Factory\Report(new NullLogger());
+
+ $this->assertReport($factory->createFromTableRow($row, $postUriIds), $assertion);
+ }
+
+ public function dataCreateFromReportsRequest(): array
+ {
+ return [
+ 'default' => [
+ 'uid' => 12,
+ 'cid' => 13,
+ 'comment' => '',
+ 'forward' => false,
+ 'postUriIds' => [],
+ 'assertion' => new Entity\Report(
+ 12,
+ 13,
+ new \DateTime('now', new \DateTimeZone('UTC')),
+ '',
+ false,
+ [],
+ null
+ ),
+ ],
+ 'full' => [
+ 'uid' => 12,
+ 'cid' => 13,
+ 'comment' => 'Report',
+ 'forward' => true,
+ 'postUriIds' => [89, 90],
+ 'assertion' => new Entity\Report(
+ 12,
+ 13,
+ new \DateTime('now', new \DateTimeZone('UTC')),
+ 'Report',
+ true,
+ [89, 90],
+ null
+ ),
+ ],
+ ];
+ }
+
+ /**
+ * @dataProvider dataCreateFromReportsRequest
+ */
+ public function testCreateFromReportsRequest(int $uid, int $cid, string $comment, bool $forward, array $postUriIds, Entity\Report $assertion)
+ {
+ $factory = new Factory\Report(new NullLogger());
+
+ $this->assertReport($factory->createFromReportsRequest($uid, $cid, $comment, $forward, $postUriIds), $assertion);
+ }
+}