From 4546a4af512fb4df12de005ed2c2d97e6be5fbec Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 24 Feb 2025 13:17:34 +0000 Subject: [PATCH 01/91] Run PHPStan with level 3 --- .phpstan.neon | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/.phpstan.neon b/.phpstan.neon index 8dfd10deae..bf01c3cc07 100644 --- a/.phpstan.neon +++ b/.phpstan.neon @@ -3,10 +3,10 @@ # SPDX-License-Identifier: CC0-1.0 parameters: - level: 2 + level: 3 paths: - - addon/ + # - addon/ - bin/auth_ejabberd.php - bin/console.php - bin/daemon.php @@ -47,26 +47,26 @@ parameters: message: '(^Parameter .+ has invalid type IMAP\\Connection\.$)' path: src - - + # - # Ignore missing SMTP class in PHPMailer 5.2.21 # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php - message: '(^.+ an unknown class SMTP\.$)' - path: addon/mailstream/phpmailer + # message: '(^.+ an unknown class SMTP\.$)' + # path: addon/mailstream/phpmailer - - + # - # Ignore missing SMTP class in PHPMailer 5.2.21 # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php - message: '(^Property .+ has unknown class SMTP as its type\.$)' - path: addon/mailstream/phpmailer + # message: '(^Property .+ has unknown class SMTP as its type\.$)' + # path: addon/mailstream/phpmailer - - + # - # Ignore missing SMTP class in PHPMailer 5.2.21 # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php - message: '(^Method .+ has invalid return type SMTP\.$)' - path: addon/mailstream/phpmailer + # message: '(^Method .+ has invalid return type SMTP\.$)' + # path: addon/mailstream/phpmailer - - + # - # Ignore missing SMTP class in PHPMailer 5.2.21 # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php - message: '(^Instantiated class SMTP not found\.$)' - path: addon/mailstream/phpmailer + # message: '(^Instantiated class SMTP not found\.$)' + # path: addon/mailstream/phpmailer From ca3d98b9f5047e650f5a025836df687c266fb3a7 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 24 Feb 2025 15:15:26 +0000 Subject: [PATCH 02/91] Fix 11 errors --- src/Util/HTTPSignature.php | 13 ++++++------- src/Util/JsonLD.php | 7 ++----- src/Util/ReversedFileReader.php | 5 +++-- src/Util/Strings.php | 4 ++-- src/Util/Temporal.php | 2 +- src/Util/XML.php | 2 +- 6 files changed, 15 insertions(+), 18 deletions(-) diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index bb5d8c6b5a..058d83d62a 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -7,6 +7,7 @@ namespace Friendica\Util; +use Exception; use Friendica\Core\Protocol; use Friendica\Database\Database; use Friendica\Database\DBA; @@ -213,7 +214,7 @@ class HTTPSignature $headers = []; foreach ($matches as $match) { - $headers[$match[1]] = trim($match[2] ?: $match[3], '"'); + $headers[$match[1]] = trim((string) $match[2], '"'); } // if the header is encrypted, decrypt with (default) site private key and continue @@ -537,14 +538,12 @@ class HTTPSignature if (!empty($uid)) { $owner = User::getOwnerDataById($uid); - if (!$owner) { - return; - } } else { $owner = User::getSystemAccount(); - if (!$owner) { - return; - } + } + + if (!$owner) { + throw new Exception('Could not find owner for uid ' . $uid); } if (!empty($owner['uprvkey'])) { diff --git a/src/Util/JsonLD.php b/src/Util/JsonLD.php index 3301ca1b40..afca8d79ba 100644 --- a/src/Util/JsonLD.php +++ b/src/Util/JsonLD.php @@ -243,14 +243,11 @@ class JsonLD return json_decode(json_encode($json, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)); } + /** * Fetches an element array from a JSON array * - * @param $array - * @param $element - * @param $key - * - * @return array fetched element + * @return array|null fetched element or null */ public static function fetchElementArray($array, $element, $key = null, $type = null, $type_value = null) { diff --git a/src/Util/ReversedFileReader.php b/src/Util/ReversedFileReader.php index 779933cbc6..57800ab561 100644 --- a/src/Util/ReversedFileReader.php +++ b/src/Util/ReversedFileReader.php @@ -26,13 +26,13 @@ class ReversedFileReader implements \Iterator /** @var int */ private $pos = -1; - /** @var array */ + /** @var array|null */ private $buffer = null; /** @var int */ private $key = -1; - /** @var string */ + /** @var string|null */ private $value = null; /** @@ -53,6 +53,7 @@ class ReversedFileReader implements \Iterator $this->buffer = null; $this->key = -1; $this->value = null; + return $this; } diff --git a/src/Util/Strings.php b/src/Util/Strings.php index efa0994ec3..9dbf361761 100644 --- a/src/Util/Strings.php +++ b/src/Util/Strings.php @@ -209,7 +209,7 @@ class Strings { // If this method is called for an infinite (== unlimited) amount of bytes: if ($bytes == INF) { - return INF; + return 'INF'; } $units = ['B', 'KiB', 'MiB', 'GiB', 'TiB']; @@ -509,7 +509,7 @@ class Strings function ($matches) use ($blocks) { $return = $matches[0]; if (isset($blocks[intval($matches[1])])) { - $return = $blocks[$matches[1]]; + $return = $blocks[intval($matches[1])]; } return $return; }, diff --git a/src/Util/Temporal.php b/src/Util/Temporal.php index 3e9ea157d5..cc9baa53a9 100644 --- a/src/Util/Temporal.php +++ b/src/Util/Temporal.php @@ -405,7 +405,7 @@ class Temporal */ public static function getDaysInMonth(int $y, int $m): int { - return date('t', mktime(0, 0, 0, $m, 1, $y)); + return (int) date('t', mktime(0, 0, 0, $m, 1, $y)); } /** diff --git a/src/Util/XML.php b/src/Util/XML.php index cf5689c361..4c099fb78e 100644 --- a/src/Util/XML.php +++ b/src/Util/XML.php @@ -184,7 +184,7 @@ class XML * @param integer $recursion_depth recursion counter for internal use - default 0 * internal use, recursion counter * - * @return array | string The array from the xml element or the string + * @return array|string|null The array from the xml element or the string */ public static function elementToArray($xml_element, int &$recursion_depth = 0) { From f6d5cd039e70f6368a8da32416056e9996b8607c Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 07:48:38 +0000 Subject: [PATCH 03/91] Fix 2 PHPStan errors --- src/User/Settings/Repository/UserGServer.php | 46 ++++++++------------ src/Util/Crypto.php | 5 +-- src/Util/HTTPSignature.php | 2 +- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/src/User/Settings/Repository/UserGServer.php b/src/User/Settings/Repository/UserGServer.php index dd097c7af2..016f2ea70d 100644 --- a/src/User/Settings/Repository/UserGServer.php +++ b/src/User/Settings/Repository/UserGServer.php @@ -8,28 +8,27 @@ namespace Friendica\User\Settings\Repository; use Exception; -use Friendica\BaseCollection; -use Friendica\BaseEntity; +use Friendica\BaseRepository; use Friendica\Content\Pager; use Friendica\Database\Database; use Friendica\Federation\Repository\GServer; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Network\HTTPException\NotFoundException; -use Friendica\User\Settings\Collection; -use Friendica\User\Settings\Entity; -use Friendica\User\Settings\Factory; +use Friendica\User\Settings\Collection\UserGServers as UserGServersCollection; +use Friendica\User\Settings\Entity\UserGServer as UserGServerEntity; +use Friendica\User\Settings\Factory\UserGServer as UserGServerFactory; use Psr\Log\LoggerInterface; -class UserGServer extends \Friendica\BaseRepository +class UserGServer extends BaseRepository { protected static $table_name = 'user-gserver'; - /** @var Factory\UserGServer */ + /** @var UserGServerFactory */ protected $factory; /** @var GServer */ protected $gserverRepository; - public function __construct(GServer $gserverRepository, Database $database, LoggerInterface $logger, Factory\UserGServer $factory) + public function __construct(GServer $gserverRepository, Database $database, LoggerInterface $logger, UserGServerFactory $factory) { parent::__construct($database, $logger, $factory); @@ -39,12 +38,9 @@ class UserGServer extends \Friendica\BaseRepository /** * Returns an existing UserGServer entity or create one on the fly * - * @param int $uid - * @param int $gsid * @param bool $hydrate Populate the related GServer entity - * @return Entity\UserGServer */ - public function getOneByUserAndServer(int $uid, int $gsid, bool $hydrate = true): Entity\UserGServer + public function getOneByUserAndServer(int $uid, int $gsid, bool $hydrate = true): UserGServerEntity { try { return $this->selectOneByUserAndServer($uid, $gsid, $hydrate); @@ -54,18 +50,15 @@ class UserGServer extends \Friendica\BaseRepository } /** - * @param int $uid - * @param int $gsid * @param bool $hydrate Populate the related GServer entity - * @return Entity\UserGServer * @throws NotFoundException */ - public function selectOneByUserAndServer(int $uid, int $gsid, bool $hydrate = true): Entity\UserGServer + public function selectOneByUserAndServer(int $uid, int $gsid, bool $hydrate = true): UserGServerEntity { return $this->_selectOne(['uid' => $uid, 'gsid' => $gsid], [], $hydrate); } - public function save(Entity\UserGServer $userGServer): Entity\UserGServer + public function save(UserGServerEntity $userGServer): UserGServerEntity { $fields = [ 'uid' => $userGServer->uid, @@ -78,7 +71,7 @@ class UserGServer extends \Friendica\BaseRepository return $userGServer; } - public function selectByUserWithPagination(int $uid, Pager $pager): Collection\UserGServers + public function selectByUserWithPagination(int $uid, Pager $pager): UserGServersCollection { return $this->_select(['uid' => $uid], ['limit' => [$pager->getStart(), $pager->getItemsPerPage()]]); } @@ -94,20 +87,18 @@ class UserGServer extends \Friendica\BaseRepository } /** - * @param Entity\UserGServer $userGServer - * @return bool * @throws InternalServerErrorException in case the underlying storage cannot delete the record */ - public function delete(Entity\UserGServer $userGServer): bool + public function delete(UserGServerEntity $userGServer): bool { try { return $this->db->delete(self::$table_name, ['uid' => $userGServer->uid, 'gsid' => $userGServer->gsid]); - } catch (\Exception $exception) { + } catch (Exception $exception) { throw new InternalServerErrorException('Cannot delete the UserGServer', $exception); } } - protected function _selectOne(array $condition, array $params = [], bool $hydrate = true): BaseEntity + protected function _selectOne(array $condition, array $params = [], bool $hydrate = true): UserGServerEntity { $fields = $this->db->selectFirst(static::$table_name, [], $condition, $params); if (!$this->db->isResult($fields)) { @@ -118,16 +109,13 @@ class UserGServer extends \Friendica\BaseRepository } /** - * @param array $condition - * @param array $params - * @return Collection\UserGServers * @throws Exception */ - protected function _select(array $condition, array $params = [], bool $hydrate = true): BaseCollection + protected function _select(array $condition, array $params = [], bool $hydrate = true): UserGServersCollection { $rows = $this->db->selectToArray(static::$table_name, [], $condition, $params); - $Entities = new Collection\UserGServers(); + $Entities = new UserGServersCollection(); foreach ($rows as $fields) { $Entities[] = $this->factory->createFromTableRow($fields, $hydrate ? $this->gserverRepository->selectOneById($fields['gsid']) : null); } @@ -135,7 +123,7 @@ class UserGServer extends \Friendica\BaseRepository return $Entities; } - public function listIgnoredByUser(int $uid): Collection\UserGServers + public function listIgnoredByUser(int $uid): UserGServersCollection { return $this->_select(['uid' => $uid, 'ignored' => 1], [], false); } diff --git a/src/Util/Crypto.php b/src/Util/Crypto.php index 084ae567ea..084bd21808 100644 --- a/src/Util/Crypto.php +++ b/src/Util/Crypto.php @@ -225,19 +225,18 @@ class Crypto } /** - * * Ported from Hubzilla: https://framagit.org/hubzilla/core/blob/master/include/crypto.php * * @param array $data ['iv' => $iv, 'key' => $key, 'alg' => $alg, 'data' => $data] * @param string $prvkey The private key used for decryption. * - * @return string|boolean The decrypted string or false on failure. + * @return string|false The decrypted string or false on failure. * @throws \Exception */ public static function unencapsulate(array $data, $prvkey) { if (!$data) { - return; + return false; } $alg = $data['alg'] ?? 'aes256cbc'; diff --git a/src/Util/HTTPSignature.php b/src/Util/HTTPSignature.php index 058d83d62a..a779a59a86 100644 --- a/src/Util/HTTPSignature.php +++ b/src/Util/HTTPSignature.php @@ -248,7 +248,7 @@ class HTTPSignature private static function decryptSigheader(array $headers, string $prvkey): string { if (!empty($headers['iv']) && !empty($headers['key']) && !empty($headers['data'])) { - return Crypto::unencapsulate($headers, $prvkey); + return (string) Crypto::unencapsulate($headers, $prvkey); } return ''; From 83f64b49312051030f1ae50f78916d26fa1dc9af Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 07:59:39 +0000 Subject: [PATCH 04/91] Fix PHPStan error in Security class --- src/Security/Security.php | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/Security/Security.php b/src/Security/Security.php index 6b0deb75ec..9056596f27 100644 --- a/src/Security/Security.php +++ b/src/Security/Security.php @@ -45,25 +45,25 @@ class Security return true; } elseif ($verified === 1) { return false; + } + + $user = User::getById($owner); + if (!$user || $user['blockwall']) { + $verified = 1; + return false; + } + + $contact = Contact::getById($cid); + if (!is_array($contact) || $contact['blocked'] || $contact['readonly'] || $contact['pending']) { + $verified = 1; + return false; + } + + if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND]) || ($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)) { + $verified = 2; + return true; } else { - $user = User::getById($owner); - if (!$user || $user['blockwall']) { - $verified = 1; - return false; - } - - $contact = Contact::getById($cid); - if ($contact || $contact['blocked'] || $contact['readonly'] || $contact['pending']) { - $verified = 1; - return false; - } - - if (in_array($contact['rel'], [Contact::SHARING, Contact::FRIEND]) || ($user['page-flags'] == User::PAGE_FLAGS_COMMUNITY)) { - $verified = 2; - return true; - } else { - $verified = 1; - } + $verified = 1; } } From 2254bee74d071e9c0717e219ab2cf3faa8efbca2 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 08:30:27 +0000 Subject: [PATCH 05/91] Refactory PermissionSet Repository, add BaseRepository::_selectFirstRowAsArray() --- src/BaseRepository.php | 19 ++++++ .../Repository/PermissionSet.php | 59 ++++++------------- 2 files changed, 38 insertions(+), 40 deletions(-) diff --git a/src/BaseRepository.php b/src/BaseRepository.php index 068a9f4b63..afbb688bd9 100644 --- a/src/BaseRepository.php +++ b/src/BaseRepository.php @@ -129,6 +129,24 @@ abstract class BaseRepository return $Entities; } + /** + * Selects the fields of the first row as array + * + * @throws NotFoundException + * + * @return array The resulted fields as array + */ + protected function _selectFirstRowAsArray(array $condition, array $params = []): array + { + $fields = $this->db->selectFirst(static::$table_name, [], $condition, $params); + + if (!$this->db->isResult($fields)) { + throw new NotFoundException(); + } + + return $fields; + } + /** * @param array $condition * @param array $params @@ -138,6 +156,7 @@ abstract class BaseRepository 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(); } diff --git a/src/Security/PermissionSet/Repository/PermissionSet.php b/src/Security/PermissionSet/Repository/PermissionSet.php index ec3e2745ec..c77baf0f2e 100644 --- a/src/Security/PermissionSet/Repository/PermissionSet.php +++ b/src/Security/PermissionSet/Repository/PermissionSet.php @@ -15,9 +15,9 @@ use Friendica\Model\Circle; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Security\PermissionSet\Exception\PermissionSetNotFoundException; use Friendica\Security\PermissionSet\Exception\PermissionSetPersistenceException; -use Friendica\Security\PermissionSet\Factory; -use Friendica\Security\PermissionSet\Collection; -use Friendica\Security\PermissionSet\Entity; +use Friendica\Security\PermissionSet\Factory\PermissionSet as PermissionSetFactory; +use Friendica\Security\PermissionSet\Collection\PermissionSets as PermissionSetsCollection; +use Friendica\Security\PermissionSet\Entity\PermissionSet as PermissionSetEntity; use Friendica\Util\ACLFormatter; use Psr\Log\LoggerInterface; @@ -26,7 +26,7 @@ class PermissionSet extends BaseRepository /** @var int Virtual permission set id for public permission */ const PUBLIC = 0; - /** @var Factory\PermissionSet */ + /** @var PermissionSetFactory */ protected $factory; protected static $table_name = 'permissionset'; @@ -34,7 +34,7 @@ class PermissionSet extends BaseRepository /** @var ACLFormatter */ private $aclFormatter; - public function __construct(Database $database, LoggerInterface $logger, Factory\PermissionSet $factory, ACLFormatter $aclFormatter) + public function __construct(Database $database, LoggerInterface $logger, PermissionSetFactory $factory, ACLFormatter $aclFormatter) { parent::__construct($database, $logger, $factory); @@ -42,34 +42,28 @@ class PermissionSet extends BaseRepository } /** - * @param array $condition - * @param array $params - * - * @return Entity\PermissionSet * @throws NotFoundException * @throws Exception */ - private function selectOne(array $condition, array $params = []): Entity\PermissionSet + private function selectOne(array $condition, array $params = []): PermissionSetEntity { - return parent::_selectOne($condition, $params); + $fields = parent::_selectFirstRowAsArray($condition, $params); + + return $this->factory->createFromTableRow($fields); } /** * @throws Exception */ - private function select(array $condition, array $params = []): Collection\PermissionSets + private function select(array $condition, array $params = []): PermissionSetsCollection { - return new Collection\PermissionSets(parent::_select($condition, $params)->getArrayCopy()); + return new PermissionSetsCollection(parent::_select($condition, $params)->getArrayCopy()); } /** * Converts a given PermissionSet into a DB compatible row array - * - * @param Entity\PermissionSet $permissionSet - * - * @return array */ - protected function convertToTableRow(Entity\PermissionSet $permissionSet): array + protected function convertToTableRow(PermissionSetEntity $permissionSet): array { return [ 'uid' => $permissionSet->uid, @@ -83,12 +77,11 @@ class PermissionSet extends BaseRepository /** * @param int $id A PermissionSet table row id or self::PUBLIC * @param int $uid The owner of the PermissionSet - * @return Entity\PermissionSet * * @throws PermissionSetNotFoundException * @throws PermissionSetPersistenceException */ - public function selectOneById(int $id, int $uid): Entity\PermissionSet + public function selectOneById(int $id, int $uid): PermissionSetEntity { if ($id === self::PUBLIC) { return $this->factory->createFromString($uid); @@ -109,11 +102,9 @@ class PermissionSet extends BaseRepository * @param int $cid Contact id of the visitor * @param int $uid User id whom the items belong, used for ownership check. * - * @return Collection\PermissionSets - * * @throws PermissionSetPersistenceException */ - public function selectByContactId(int $cid, int $uid): Collection\PermissionSets + public function selectByContactId(int $cid, int $uid): PermissionSetsCollection { try { $cdata = Contact::getPublicAndUserContactID($cid, $uid); @@ -162,16 +153,14 @@ class PermissionSet extends BaseRepository * * @param int $uid * - * @return Entity\PermissionSet - * * @throws PermissionSetPersistenceException */ - public function selectDefaultForUser(int $uid): Entity\PermissionSet + public function selectDefaultForUser(int $uid): PermissionSetEntity { try { $self_contact = Contact::selectFirst(['id'], ['uid' => $uid, 'self' => true]); } catch (Exception $exception) { - throw new PermissionSetPersistenceException(sprintf('Cannot select Contact for user %d', $uid)); + throw new PermissionSetPersistenceException(sprintf('Cannot select Contact for user %d', $uid), $exception); } if (!$this->db->isResult($self_contact)) { @@ -188,10 +177,8 @@ class PermissionSet extends BaseRepository * Fetch the public PermissionSet * * @param int $uid - * - * @return Entity\PermissionSet */ - public function selectPublicForUser(int $uid): Entity\PermissionSet + public function selectPublicForUser(int $uid): PermissionSetEntity { return $this->factory->createFromString($uid, '', '', '', '', self::PUBLIC); } @@ -199,13 +186,9 @@ class PermissionSet extends BaseRepository /** * Selects or creates a PermissionSet based on its fields * - * @param Entity\PermissionSet $permissionSet - * - * @return Entity\PermissionSet - * * @throws PermissionSetPersistenceException */ - public function selectOrCreate(Entity\PermissionSet $permissionSet): Entity\PermissionSet + public function selectOrCreate(PermissionSetEntity $permissionSet): PermissionSetEntity { if ($permissionSet->id) { return $permissionSet; @@ -226,13 +209,9 @@ class PermissionSet extends BaseRepository } /** - * @param Entity\PermissionSet $permissionSet - * - * @return Entity\PermissionSet - * * @throws PermissionSetPersistenceException */ - public function save(Entity\PermissionSet $permissionSet): Entity\PermissionSet + public function save(PermissionSetEntity $permissionSet): PermissionSetEntity { // Don't save/update the common public PermissionSet if ($permissionSet->isPublic()) { From 16cbaf890a6d3c7e6365cc423a8fbd6c08fa141f Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 08:39:31 +0000 Subject: [PATCH 06/91] Deprecate BaseRepository::_selectOne() --- src/BaseRepository.php | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/BaseRepository.php b/src/BaseRepository.php index afbb688bd9..ead4bf73bf 100644 --- a/src/BaseRepository.php +++ b/src/BaseRepository.php @@ -148,18 +148,13 @@ abstract class BaseRepository } /** - * @param array $condition - * @param array $params - * @return BaseEntity + * @deprecated 2025.05 Use `\Friendica\BaseRepository::_selectFirstRowAsArray()` instead + * * @throws NotFoundException */ 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(); - } + $fields = $this->_selectFirstRowAsArray( $condition, $params); return $this->factory->createFromTableRow($fields); } From 459ad05137c68dddbd10e7610709a9cbbc02e644 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 09:26:08 +0000 Subject: [PATCH 07/91] Refactor DisporaContact Repository, fix PHPStan error --- .../Diaspora/Repository/DiasporaContact.php | 87 +++++++++---------- 1 file changed, 40 insertions(+), 47 deletions(-) diff --git a/src/Protocol/Diaspora/Repository/DiasporaContact.php b/src/Protocol/Diaspora/Repository/DiasporaContact.php index b680fedea1..6d92b066f8 100644 --- a/src/Protocol/Diaspora/Repository/DiasporaContact.php +++ b/src/Protocol/Diaspora/Repository/DiasporaContact.php @@ -7,6 +7,9 @@ namespace Friendica\Protocol\Diaspora\Repository; +use DateTime; +use DateTimeZone; +use Exception; use Friendica\BaseRepository; use Friendica\Database\Database; use Friendica\Database\Definition\DbaDefinition; @@ -14,11 +17,12 @@ use Friendica\Model\APContact; use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Model\ItemURI; -use Friendica\Network\HTTPException; -use Friendica\Protocol\Diaspora\Entity; -use Friendica\Protocol\Diaspora\Factory; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\Protocol\Diaspora\Entity\DiasporaContact as DiasporaContactEntity; +use Friendica\Protocol\Diaspora\Factory\DiasporaContact as DiasporaContactFactory; use Friendica\Protocol\WebFingerUri; use Friendica\Util\DateTimeFormat; +use InvalidArgumentException; use Psr\Http\Message\UriInterface; use Psr\Log\LoggerInterface; @@ -30,12 +34,12 @@ class DiasporaContact extends BaseRepository protected static $table_name = 'diaspora-contact-view'; - /** @var Factory\DiasporaContact */ + /** @var DiasporaContactFactory */ protected $factory; /** @var DbaDefinition */ private $definition; - public function __construct(DbaDefinition $definition, Database $database, LoggerInterface $logger, Factory\DiasporaContact $factory) + public function __construct(DbaDefinition $definition, Database $database, LoggerInterface $logger, DiasporaContactFactory $factory) { parent::__construct($database, $logger, $factory); @@ -43,67 +47,58 @@ class DiasporaContact extends BaseRepository } /** - * @param array $condition - * @param array $params - * @return Entity\DiasporaContact - * @throws HTTPException\NotFoundException + * @throws NotFoundException */ - public function selectOne(array $condition, array $params = []): Entity\DiasporaContact + public function selectOne(array $condition, array $params = []): DiasporaContactEntity { - return parent::_selectOne($condition, $params); + $fields = $this->_selectFirstRowAsArray( $condition, $params); + + return $this->factory->createFromTableRow($fields); } /** - * @param int $uriId - * @return Entity\DiasporaContact - * @throws HTTPException\NotFoundException + * @throws NotFoundException */ - public function selectOneByUriId(int $uriId): Entity\DiasporaContact + public function selectOneByUriId(int $uriId): DiasporaContactEntity { return $this->selectOne(['uri-id' => $uriId]); } /** - * @param UriInterface $uri - * @return Entity\DiasporaContact - * @throws HTTPException\NotFoundException + * @throws NotFoundException */ - public function selectOneByUri(UriInterface $uri): Entity\DiasporaContact + public function selectOneByUri(UriInterface $uri): DiasporaContactEntity { try { return $this->selectOne(['url' => (string) $uri]); - } catch (HTTPException\NotFoundException $e) { + } catch (NotFoundException $e) { } try { return $this->selectOne(['addr' => (string) $uri]); - } catch (HTTPException\NotFoundException $e) { + } catch (NotFoundException $e) { } return $this->selectOne(['alias' => (string) $uri]); } /** - * @param WebFingerUri $uri - * @return Entity\DiasporaContact - * @throws HTTPException\NotFoundException + * @throws NotFoundException */ - public function selectOneByAddr(WebFingerUri $uri): Entity\DiasporaContact + public function selectOneByAddr(WebFingerUri $uri): DiasporaContactEntity { return $this->selectOne(['addr' => $uri->getAddr()]); } /** - * @param int $uriId - * @return bool - * @throws \Exception + * @throws Exception */ public function existsByUriId(int $uriId): bool { return $this->db->exists(self::$table_name, ['uri-id' => $uriId]); } - public function save(Entity\DiasporaContact $DiasporaContact): Entity\DiasporaContact + public function save(DiasporaContactEntity $DiasporaContact): DiasporaContactEntity { $uriId = $DiasporaContact->uriId ?? ItemURI::insert(['uri' => $DiasporaContact->url, 'guid' => $DiasporaContact->guid]); @@ -145,10 +140,9 @@ class DiasporaContact extends BaseRepository * * @param WebFingerUri $uri Profile address * @param boolean $update true = always update, false = never update, null = update when not found or outdated - * @return Entity\DiasporaContact - * @throws HTTPException\NotFoundException + * @throws NotFoundException */ - public function getByAddr(WebFingerUri $uri, ?bool $update = self::UPDATE_IF_MISSING_OR_OUTDATED): Entity\DiasporaContact + public function getByAddr(WebFingerUri $uri, ?bool $update = self::UPDATE_IF_MISSING_OR_OUTDATED): DiasporaContactEntity { if ($update !== self::ALWAYS_UPDATE) { try { @@ -156,7 +150,7 @@ class DiasporaContact extends BaseRepository if ($update === self::NEVER_UPDATE) { return $dcontact; } - } catch (HTTPException\NotFoundException $e) { + } catch (NotFoundException $e) { if ($update === self::NEVER_UPDATE) { throw $e; } @@ -169,7 +163,7 @@ class DiasporaContact extends BaseRepository $contact = Contact::getByURL($uri, $update, ['uri-id']); if (empty($contact['uri-id'])) { - throw new HTTPException\NotFoundException('Diaspora profile with URI ' . $uri . ' not found'); + throw new NotFoundException('Diaspora profile with URI ' . $uri . ' not found'); } return self::selectOneByUriId($contact['uri-id']); @@ -180,10 +174,9 @@ class DiasporaContact extends BaseRepository * * @param UriInterface $uri Profile URL * @param boolean $update true = always update, false = never update, null = update when not found or outdated - * @return Entity\DiasporaContact - * @throws HTTPException\NotFoundException + * @throws NotFoundException */ - public function getByUrl(UriInterface $uri, ?bool $update = self::UPDATE_IF_MISSING_OR_OUTDATED): Entity\DiasporaContact + public function getByUrl(UriInterface $uri, ?bool $update = self::UPDATE_IF_MISSING_OR_OUTDATED): DiasporaContactEntity { if ($update !== self::ALWAYS_UPDATE) { try { @@ -191,7 +184,7 @@ class DiasporaContact extends BaseRepository if ($update === self::NEVER_UPDATE) { return $dcontact; } - } catch (HTTPException\NotFoundException $e) { + } catch (NotFoundException $e) { if ($update === self::NEVER_UPDATE) { throw $e; } @@ -204,7 +197,7 @@ class DiasporaContact extends BaseRepository $contact = Contact::getByURL($uri, $update, ['uri-id']); if (empty($contact['uri-id'])) { - throw new HTTPException\NotFoundException('Diaspora profile with URI ' . $uri . ' not found'); + throw new NotFoundException('Diaspora profile with URI ' . $uri . ' not found'); } return self::selectOneByUriId($contact['uri-id']); @@ -214,27 +207,27 @@ class DiasporaContact extends BaseRepository * Update or create a diaspora-contact entry via a probe array * * @param array $data Probe array - * @return Entity\DiasporaContact - * @throws \Exception + * @throws Exception */ - public function updateFromProbeArray(array $data): Entity\DiasporaContact + public function updateFromProbeArray(array $data): DiasporaContactEntity { if (empty($data['url'])) { - throw new \InvalidArgumentException('Missing url key in Diaspora probe data array'); + throw new InvalidArgumentException('Missing url key in Diaspora probe data array'); } if (empty($data['guid'])) { - throw new \InvalidArgumentException('Missing guid key in Diaspora probe data array'); + throw new InvalidArgumentException('Missing guid key in Diaspora probe data array'); } if (empty($data['pubkey'])) { - throw new \InvalidArgumentException('Missing pubkey key in Diaspora probe data array'); + throw new InvalidArgumentException('Missing pubkey key in Diaspora probe data array'); } $uriId = ItemURI::insert(['uri' => $data['url'], 'guid' => $data['guid']]); $contact = Contact::getByUriId($uriId, ['id', 'created']); $apcontact = APContact::getByURL($data['url'], false); + if (!empty($apcontact)) { $interacting_count = $apcontact['followers_count']; $interacted_count = $apcontact['following_count']; @@ -250,7 +243,7 @@ class DiasporaContact extends BaseRepository $DiasporaContact = $this->factory->createfromProbeData( $data, $uriId, - new \DateTime($contact['created'] ?? 'now', new \DateTimeZone('UTC')), + new DateTime($contact['created'] ?? 'now', new DateTimeZone('UTC')), $interacting_count ?? 0, $interacted_count ?? 0, $post_count ?? 0 @@ -269,7 +262,7 @@ class DiasporaContact extends BaseRepository * @param string $guid Hexadecimal string guid * * @return string the contact url or null - * @throws \Exception + * @throws Exception */ public function getUrlByGuid(string $guid): ?string { From c1653877fb4d4c9ca44d5cd47830960b8f5b0572 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 11:36:32 +0000 Subject: [PATCH 08/91] fix 17 PHPStan errors --- src/Protocol/ATProtocol/Processor.php | 6 +- src/Protocol/ActivityPub/Receiver.php | 2 +- src/Protocol/DFRN.php | 108 +++++++++++++------------- src/Protocol/Diaspora.php | 8 +- 4 files changed, 62 insertions(+), 62 deletions(-) diff --git a/src/Protocol/ATProtocol/Processor.php b/src/Protocol/ATProtocol/Processor.php index f551f6a273..3a21ff3dd4 100755 --- a/src/Protocol/ATProtocol/Processor.php +++ b/src/Protocol/ATProtocol/Processor.php @@ -279,7 +279,7 @@ class Processor $uri = $this->getUri($post); if ($uri_id = $this->fetchUriId($uri, $uid)) { - return $uri_id; + return (int) $uri_id; } if (empty($post->record)) { @@ -322,7 +322,7 @@ class Processor $this->logger->warning('Fetched post was not inserted', ['guid' => $item['guid'], 'uri' => $item['uri']]); } - return $this->fetchUriId($uri, $uid); + return (int) $this->fetchUriId($uri, $uid); } private function getHeaderFromJetstream(stdClass $data, int $uid, int $protocol = Conversation::PARCEL_JETSTREAM): array @@ -860,7 +860,7 @@ class Processor $this->logger->debug('Post with extid exists', ['uri' => $uri]); return $reply['uri-id']; } - return 0; + return '0'; } private function getPostUids(string $uri, bool $with_public_user): array diff --git a/src/Protocol/ActivityPub/Receiver.php b/src/Protocol/ActivityPub/Receiver.php index 34732022b5..76f4d31d3d 100644 --- a/src/Protocol/ActivityPub/Receiver.php +++ b/src/Protocol/ActivityPub/Receiver.php @@ -250,7 +250,7 @@ class Receiver * @param string $object_id Object ID of the provided object * @param integer $uid User ID * - * @return string with object type or NULL + * @return string|null string with object type or NULL * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ diff --git a/src/Protocol/DFRN.php b/src/Protocol/DFRN.php index be6dfc206d..56cafc1a97 100644 --- a/src/Protocol/DFRN.php +++ b/src/Protocol/DFRN.php @@ -607,64 +607,64 @@ class DFRN * @param string $element Element name for the activity * @param string $activity activity value * @param int $uriid Uri-Id of the post - * @return DOMElement XML activity object + * @return DOMElement|false XML activity object or false on error * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @todo Find proper type-hints */ private static function createActivity(DOMDocument $doc, string $element, string $activity, int $uriid) { - if ($activity) { - $entry = $doc->createElement($element); - - $r = XML::parseString($activity); - if (!$r) { - return false; - } - - if ($r->type) { - XML::addElement($doc, $entry, "activity:object-type", $r->type); - } - - if ($r->id) { - XML::addElement($doc, $entry, "id", $r->id); - } - - if ($r->title) { - XML::addElement($doc, $entry, "title", $r->title); - } - - if ($r->link) { - if (substr($r->link, 0, 1) == '<') { - if (strstr($r->link, '&') && (! strstr($r->link, '&'))) { - $r->link = str_replace('&', '&', $r->link); - } - - $r->link = preg_replace('/\/', '', $r->link); - - // XML does need a single element as root element so we add a dummy element here - $data = XML::parseString("" . $r->link . ""); - if (is_object($data)) { - foreach ($data->link as $link) { - $attributes = []; - foreach ($link->attributes() as $parameter => $value) { - $attributes[$parameter] = $value; - } - XML::addElement($doc, $entry, "link", "", $attributes); - } - } - } else { - $attributes = ["rel" => "alternate", "type" => "text/html", "href" => $r->link]; - XML::addElement($doc, $entry, "link", "", $attributes); - } - } - if ($r->content) { - XML::addElement($doc, $entry, "content", BBCode::convertForUriId($uriid, $r->content, BBCode::EXTERNAL), ["type" => "html"]); - } - - return $entry; + if (!$activity) { + return false; } - return false; + $entry = $doc->createElement($element); + + $r = XML::parseString($activity); + if (!$r) { + return false; + } + + if ($r->type) { + XML::addElement($doc, $entry, "activity:object-type", $r->type); + } + + if ($r->id) { + XML::addElement($doc, $entry, "id", $r->id); + } + + if ($r->title) { + XML::addElement($doc, $entry, "title", $r->title); + } + + if ($r->link) { + if (substr($r->link, 0, 1) == '<') { + if (strstr($r->link, '&') && (! strstr($r->link, '&'))) { + $r->link = str_replace('&', '&', $r->link); + } + + $r->link = preg_replace('/\/', '', $r->link); + + // XML does need a single element as root element so we add a dummy element here + $data = XML::parseString("" . $r->link . ""); + if (is_object($data)) { + foreach ($data->link as $link) { + $attributes = []; + foreach ($link->attributes() as $parameter => $value) { + $attributes[$parameter] = $value; + } + XML::addElement($doc, $entry, "link", "", $attributes); + } + } + } else { + $attributes = ["rel" => "alternate", "type" => "text/html", "href" => $r->link]; + XML::addElement($doc, $entry, "link", "", $attributes); + } + } + if ($r->content) { + XML::addElement($doc, $entry, "content", BBCode::convertForUriId($uriid, $r->content, BBCode::EXTERNAL), ["type" => "html"]); + } + + return $entry; } /** @@ -1925,7 +1925,7 @@ class DFRN // Check if the message is wanted if (!self::isSolicitedMessage($item, $importer)) { DBA::delete('item-uri', ['uri' => $item['uri']]); - return 403; + return; } // Get the type of the item (Top level post, reply or remote reply) @@ -2051,7 +2051,7 @@ class DFRN Item::distribute($posted_id); } - return true; + return; } } else { // $entrytype == self::TOP_LEVEL if (($item['uid'] != 0) && !Contact::isSharing($item['owner-id'], $item['uid']) && !Contact::isSharing($item['author-id'], $item['uid'])) { @@ -2099,7 +2099,7 @@ class DFRN } if (!$uri || !$importer['id']) { - return false; + return; } $condition = ['uri' => $uri, 'uid' => $importer['importer_uid']]; diff --git a/src/Protocol/Diaspora.php b/src/Protocol/Diaspora.php index a8db02f045..0166e65f9d 100644 --- a/src/Protocol/Diaspora.php +++ b/src/Protocol/Diaspora.php @@ -337,7 +337,7 @@ class Diaspora * @param string $xml urldecoded Diaspora salmon * @param string $privKey The private key of the importer * - * @return array + * @return array|false array with decoded data or false on error * 'message' -> decoded Diaspora XML message * 'author' -> author diaspora handle * 'key' -> author public key (converted to pkcs#8) @@ -1051,7 +1051,7 @@ class Diaspora * @param string $server The url of the server * @param int $level Endless loop prevention * - * @return array + * @return array|false The message as array or false on error * 'message' => The message XML * 'author' => The author handle * 'key' => The public key of the author @@ -2795,7 +2795,7 @@ class Diaspora // without a public key nothing will work if (!$pubkey) { DI::logger()->notice('pubkey missing: contact id: ' . $contact['id']); - return false; + return ''; } $aes_key = random_bytes(32); @@ -2809,7 +2809,7 @@ class Diaspora $encrypted_key_bundle = ''; if (!@openssl_public_encrypt($json, $encrypted_key_bundle, $pubkey)) { - return false; + return ''; } $json_object = json_encode( From cea8cf1f6c5aaea5b99eae799719930f28ab409d Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 13:51:13 +0000 Subject: [PATCH 09/91] Fix 27 PHPStan errors --- .../Notifications/Entity/Notify.php | 3 ++- src/Object/Api/Mastodon/Status.php | 18 ++++++------- src/Object/Api/Twitter/DirectMessage.php | 4 +-- src/Object/Api/Twitter/Media.php | 2 +- src/Object/Api/Twitter/Mention.php | 3 +-- src/Object/Api/Twitter/Status.php | 10 ++++---- src/Object/Log/ParsedLogLine.php | 2 +- src/Object/Post.php | 4 +-- src/Object/Thread.php | 3 +-- .../ProfileField/Collection/ProfileFields.php | 25 ++++++++----------- 10 files changed, 34 insertions(+), 40 deletions(-) diff --git a/src/Navigation/Notifications/Entity/Notify.php b/src/Navigation/Notifications/Entity/Notify.php index 3ff478633e..297ecbdd98 100644 --- a/src/Navigation/Notifications/Entity/Notify.php +++ b/src/Navigation/Notifications/Entity/Notify.php @@ -33,7 +33,8 @@ use Psr\Http\Message\UriInterface; * @property-read int|null $parentUriId * @property-read int|null $id * - * @deprecated since 2022.05 Use \Friendica\Navigation\Notifications\Entity\Notification instead + * @deprecated 2022.05 Use \Friendica\Navigation\Notifications\Entity\Notification instead + * @see \Friendica\Navigation\Notifications\Entity\Notification */ class Notify extends BaseEntity { diff --git a/src/Object/Api/Mastodon/Status.php b/src/Object/Api/Mastodon/Status.php index 0e487a989c..474db28dc0 100644 --- a/src/Object/Api/Mastodon/Status.php +++ b/src/Object/Api/Mastodon/Status.php @@ -30,7 +30,7 @@ class Status extends BaseDataTransferObject protected $edited_at; /** @var string|null */ protected $in_reply_to_id = null; - /** @var Status|null - Fedilab extension, see issue https://github.com/friendica/friendica/issues/12672 */ + /** @var Status[]|null - Fedilab extension, see issue https://github.com/friendica/friendica/issues/12672 */ protected $in_reply_to_status = null; /** @var string|null */ protected $in_reply_to_account_id = null; @@ -64,25 +64,25 @@ class Status extends BaseDataTransferObject protected $pinned = false; /** @var string */ protected $content; - /** @var Status|null */ + /** @var Status[]|null */ protected $reblog = null; - /** @var Status|null - Akkoma extension, see issue https://github.com/friendica/friendica/issues/12603 */ + /** @var Status[]|null - Akkoma extension, see issue https://github.com/friendica/friendica/issues/12603 */ protected $quote = null; /** @var Application */ protected $application = null; - /** @var Account */ + /** @var array */ protected $account; - /** @var Attachment */ + /** @var Attachment[] */ protected $media_attachments = []; - /** @var Mention */ + /** @var Mention[] */ protected $mentions = []; - /** @var Tag */ + /** @var Tag[] */ protected $tags = []; /** @var Emoji[] */ protected $emojis = []; - /** @var Card|null */ + /** @var array|null */ protected $card = null; - /** @var Poll|null */ + /** @var array|null */ protected $poll = null; /** @var FriendicaExtension */ protected $friendica; diff --git a/src/Object/Api/Twitter/DirectMessage.php b/src/Object/Api/Twitter/DirectMessage.php index 10bea34290..199d9462ed 100644 --- a/src/Object/Api/Twitter/DirectMessage.php +++ b/src/Object/Api/Twitter/DirectMessage.php @@ -29,9 +29,9 @@ class DirectMessage extends BaseDataTransferObject protected $sender_screen_name = null; /** @var string */ protected $recipient_screen_name = null; - /** @var User */ + /** @var array */ protected $sender; - /** @var User */ + /** @var array */ protected $recipient; /** @var string|null */ protected $title; diff --git a/src/Object/Api/Twitter/Media.php b/src/Object/Api/Twitter/Media.php index 19f98f1a29..589aebcfc1 100644 --- a/src/Object/Api/Twitter/Media.php +++ b/src/Object/Api/Twitter/Media.php @@ -31,7 +31,7 @@ class Media extends BaseDataTransferObject protected $media_url; /** @var string */ protected $media_url_https; - /** @var string */ + /** @var array> */ protected $sizes; /** @var string */ protected $type; diff --git a/src/Object/Api/Twitter/Mention.php b/src/Object/Api/Twitter/Mention.php index e5d257e9d3..d2a4d5065f 100644 --- a/src/Object/Api/Twitter/Mention.php +++ b/src/Object/Api/Twitter/Mention.php @@ -7,7 +7,6 @@ namespace Friendica\Object\Api\Twitter; -use Friendica\App\BaseURL; use Friendica\BaseDataTransferObject; /** @@ -37,7 +36,7 @@ class Mention extends BaseDataTransferObject */ public function __construct(array $tag, array $contact, array $indices) { - $this->id = (string)($contact['id'] ?? 0); + $this->id = (int)($contact['id'] ?? 0); $this->id_str = (string)($contact['id'] ?? 0); $this->indices = $indices; $this->name = $tag['name']; diff --git a/src/Object/Api/Twitter/Status.php b/src/Object/Api/Twitter/Status.php index 793f32fb01..1c8a4ef7ae 100644 --- a/src/Object/Api/Twitter/Status.php +++ b/src/Object/Api/Twitter/Status.php @@ -45,11 +45,11 @@ class Status extends BaseDataTransferObject protected $geo; /** @var bool */ protected $favorited = false; - /** @var User */ + /** @var array */ protected $user; - /** @var User */ + /** @var array */ protected $friendica_author; - /** @var User */ + /** @var array */ protected $friendica_owner; /** @var bool */ protected $friendica_private; @@ -67,9 +67,9 @@ class Status extends BaseDataTransferObject protected $friendica_html; /** @var int */ protected $friendica_comments; - /** @var Status|null */ + /** @var array|null */ protected $retweeted_status = null; - /** @var Status|null */ + /** @var array|null */ protected $quoted_status = null; /** @var array */ protected $attachments; diff --git a/src/Object/Log/ParsedLogLine.php b/src/Object/Log/ParsedLogLine.php index 1d9802bb32..8e552008a4 100644 --- a/src/Object/Log/ParsedLogLine.php +++ b/src/Object/Log/ParsedLogLine.php @@ -29,7 +29,7 @@ class ParsedLogLine /** @var string */ public $message = null; - /** @var string */ + /** @var string|null */ public $data = null; /** @var string */ diff --git a/src/Object/Post.php b/src/Object/Post.php index b5ad33f56e..abf617e214 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -49,7 +49,7 @@ class Post private $parent = null; /** - * @var Thread + * @var Thread|null */ private $thread = null; private $redirect_url = null; @@ -816,7 +816,7 @@ class Post * Get a child by its ID * * @param integer $id The child id - * @return Thread|null Thread or NULL if not found + * @return Post|null Post or NULL if not found */ public function getChild(int $id) { diff --git a/src/Object/Thread.php b/src/Object/Thread.php index 453e4c3421..070d8c1281 100644 --- a/src/Object/Thread.php +++ b/src/Object/Thread.php @@ -77,8 +77,7 @@ class Thread break; default: DI::logger()->info('[ERROR] Conversation::setMode : Unhandled mode ('. $mode .').'); - return false; - break; + return; } $this->mode = $mode; } diff --git a/src/Profile/ProfileField/Collection/ProfileFields.php b/src/Profile/ProfileField/Collection/ProfileFields.php index fa39a6f355..dcf5498df3 100644 --- a/src/Profile/ProfileField/Collection/ProfileFields.php +++ b/src/Profile/ProfileField/Collection/ProfileFields.php @@ -8,31 +8,26 @@ namespace Friendica\Profile\ProfileField\Collection; use Friendica\BaseCollection; -use Friendica\Profile\ProfileField\Entity; +use Friendica\Profile\ProfileField\Entity\ProfileField as ProfileFieldEntity; class ProfileFields extends BaseCollection { - public function current(): Entity\ProfileField + public function current(): ProfileFieldEntity { return parent::current(); } - /** - * @param callable $callback - * @return ProfileFields (as an extended form of BaseCollection) - */ - public function map(callable $callback): BaseCollection + public function map(callable $callback): ProfileFields { - return parent::map($callback); + $class = get_class($this); + + return new $class(array_map($callback, $this->getArrayCopy()), $this->getTotalCount()); } - /** - * @param callable|null $callback - * @param int $flag - * @return ProfileFields as an extended version of BaseCollection - */ - public function filter(callable $callback = null, int $flag = 0): BaseCollection + public function filter(?callable $callback = null, int $flag = 0): ProfileFields { - return parent::filter($callback, $flag); + $class = get_class($this); + + return new $class(array_filter($this->getArrayCopy(), $callback, $flag)); } } From f6ac16d5139b4278565c75bd41787316e36b54f8 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 14:03:52 +0000 Subject: [PATCH 10/91] Fix 11 PHPStan errors --- .../Notifications/Entity/Notify.php | 2 +- src/Object/Api/Friendica/Notification.php | 38 +++++++++---------- src/Object/Api/Mastodon/Field.php | 2 +- src/Object/Api/Mastodon/Notification.php | 4 +- src/Object/Api/Mastodon/Poll.php | 2 +- src/Object/Api/Mastodon/Relationship.php | 4 +- src/Object/Api/Mastodon/ScheduledStatus.php | 2 +- src/Object/Api/Mastodon/Status.php | 2 +- 8 files changed, 27 insertions(+), 29 deletions(-) diff --git a/src/Navigation/Notifications/Entity/Notify.php b/src/Navigation/Notifications/Entity/Notify.php index 297ecbdd98..71308772a9 100644 --- a/src/Navigation/Notifications/Entity/Notify.php +++ b/src/Navigation/Notifications/Entity/Notify.php @@ -14,7 +14,7 @@ use Friendica\Core\Renderer; use Psr\Http\Message\UriInterface; /** - * @property-read string $type + * @property-read int $type * @property-read string $name * @property-read UriInterface $url * @property-read UriInterface $photo diff --git a/src/Object/Api/Friendica/Notification.php b/src/Object/Api/Friendica/Notification.php index bff10accae..f83cd9cc2c 100644 --- a/src/Object/Api/Friendica/Notification.php +++ b/src/Object/Api/Friendica/Notification.php @@ -62,29 +62,29 @@ class Notification extends BaseDataTransferObject /** @var string Message (Plaintext) */ protected $msg_plain; - public function __construct(Notify $Notify) + public function __construct(Notify $notify) { - $this->id = $Notify->id; - $this->type = $Notify->type; - $this->name = $Notify->name; - $this->url = $Notify->url->__toString(); - $this->photo = $Notify->photo->__toString(); - $this->date = DateTimeFormat::local($Notify->date->format(DateTimeFormat::MYSQL)); - $this->msg = $Notify->msg; - $this->uid = $Notify->uid; - $this->link = $Notify->link->__toString(); - $this->iid = $Notify->itemId; - $this->parent = $Notify->parent; - $this->seen = $Notify->seen; - $this->verb = $Notify->verb; - $this->otype = $Notify->otype; - $this->name_cache = $Notify->name_cache; - $this->msg_cache = $Notify->msg_cache; - $this->timestamp = $Notify->date->format('U'); + $this->id = $notify->id; + $this->type = $notify->type; + $this->name = $notify->name; + $this->url = $notify->url->__toString(); + $this->photo = $notify->photo->__toString(); + $this->date = DateTimeFormat::local($notify->date->format(DateTimeFormat::MYSQL)); + $this->msg = $notify->msg; + $this->uid = $notify->uid; + $this->link = $notify->link->__toString(); + $this->iid = $notify->itemId; + $this->parent = $notify->parent; + $this->seen = $notify->seen; + $this->verb = $notify->verb; + $this->otype = $notify->otype; + $this->name_cache = $notify->name_cache; + $this->msg_cache = $notify->msg_cache; + $this->timestamp = (int) $notify->date->format('U'); $this->date_rel = Temporal::getRelativeDate($this->date); try { - $this->msg_html = BBCode::convertForUriId($Notify->uriId, $this->msg, BBCode::EXTERNAL); + $this->msg_html = BBCode::convertForUriId($notify->uriId, $this->msg, BBCode::EXTERNAL); } catch (\Exception $e) { $this->msg_html = ''; } diff --git a/src/Object/Api/Mastodon/Field.php b/src/Object/Api/Mastodon/Field.php index cf1983f2fe..846aac4d0f 100644 --- a/src/Object/Api/Mastodon/Field.php +++ b/src/Object/Api/Mastodon/Field.php @@ -20,7 +20,7 @@ class Field extends BaseDataTransferObject protected $name; /** @var string (HTML) */ protected $value; - /** @var string (Datetime)*/ + /** @var string|null (Datetime)*/ protected $verified_at; public function __construct(string $name, string $value) diff --git a/src/Object/Api/Mastodon/Notification.php b/src/Object/Api/Mastodon/Notification.php index e5593bfc82..b18a7f1e9e 100644 --- a/src/Object/Api/Mastodon/Notification.php +++ b/src/Object/Api/Mastodon/Notification.php @@ -44,9 +44,9 @@ class Notification extends BaseDataTransferObject protected $created_at; /** @var bool */ protected $dismissed; - /** @var Account */ + /** @var array */ protected $account; - /** @var Status|null */ + /** @var array|null */ protected $status = null; /** diff --git a/src/Object/Api/Mastodon/Poll.php b/src/Object/Api/Mastodon/Poll.php index 3d2e6c8f25..a17e8c57b5 100644 --- a/src/Object/Api/Mastodon/Poll.php +++ b/src/Object/Api/Mastodon/Poll.php @@ -32,7 +32,7 @@ class Poll extends BaseDataTransferObject /** @var bool|null */ protected $voted = false; /** @var array|null */ - protected $own_votes = false; + protected $own_votes = null; /** @var array */ protected $options = []; /** @var Emoji[] */ diff --git a/src/Object/Api/Mastodon/Relationship.php b/src/Object/Api/Mastodon/Relationship.php index 1d708425cd..2e9faf4d0b 100644 --- a/src/Object/Api/Mastodon/Relationship.php +++ b/src/Object/Api/Mastodon/Relationship.php @@ -18,7 +18,7 @@ use Friendica\Util\Network; */ class Relationship extends BaseDataTransferObject { - /** @var int */ + /** @var string */ protected $id; /** @var bool */ protected $following = false; @@ -88,7 +88,5 @@ class Relationship extends BaseDataTransferObject $this->blocking = (bool)($contactRecord['blocked'] ?? false) || $blocked; $this->note = $contactRecord['info']; } - - return $this; } } diff --git a/src/Object/Api/Mastodon/ScheduledStatus.php b/src/Object/Api/Mastodon/ScheduledStatus.php index ac4bf029c2..630ebd7839 100644 --- a/src/Object/Api/Mastodon/ScheduledStatus.php +++ b/src/Object/Api/Mastodon/ScheduledStatus.php @@ -35,7 +35,7 @@ class ScheduledStatus extends BaseDataTransferObject 'in_reply_to_id' => null, 'application_id' => '' ]; - /** @var Attachment */ + /** @var array */ protected $media_attachments = []; /** diff --git a/src/Object/Api/Mastodon/Status.php b/src/Object/Api/Mastodon/Status.php index 474db28dc0..77b49f685d 100644 --- a/src/Object/Api/Mastodon/Status.php +++ b/src/Object/Api/Mastodon/Status.php @@ -68,7 +68,7 @@ class Status extends BaseDataTransferObject protected $reblog = null; /** @var Status[]|null - Akkoma extension, see issue https://github.com/friendica/friendica/issues/12603 */ protected $quote = null; - /** @var Application */ + /** @var array */ protected $application = null; /** @var array */ protected $account; From fead4466240f1b14842d0ec7309972e69336e9e6 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 14:29:57 +0000 Subject: [PATCH 11/91] Split phpstan.neon files for addon checks --- .phpstan-addons.neon | 52 ++++++++++++++++++++++++++++++++++++++++++++ .phpstan.neon | 32 --------------------------- composer.json | 1 + 3 files changed, 53 insertions(+), 32 deletions(-) create mode 100644 .phpstan-addons.neon diff --git a/.phpstan-addons.neon b/.phpstan-addons.neon new file mode 100644 index 0000000000..801db2ab6a --- /dev/null +++ b/.phpstan-addons.neon @@ -0,0 +1,52 @@ +# SPDX-FileCopyrightText: 2010 - 2024 the Friendica project +# +# SPDX-License-Identifier: CC0-1.0 + +parameters: + level: 2 + + paths: + - addon/ + + excludePaths: + analyse: + - addon/*/lang/* + - addon/*/vendor/* + - addon/convert/UnitConvertor.php + - addon/pumpio/oauth/* + + scanDirectories: + - mod + - src + - static + - vendor + - view + + dynamicConstantNames: + - DB_UPDATE_VERSION + + ignoreErrors: + + - + # Ignore missing SMTP class in PHPMailer 5.2.21 + # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php + message: '(^.+ an unknown class SMTP\.$)' + path: addon/mailstream/phpmailer + + - + # Ignore missing SMTP class in PHPMailer 5.2.21 + # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php + message: '(^Property .+ has unknown class SMTP as its type\.$)' + path: addon/mailstream/phpmailer + + - + # Ignore missing SMTP class in PHPMailer 5.2.21 + # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php + message: '(^Method .+ has invalid return type SMTP\.$)' + path: addon/mailstream/phpmailer + + - + # Ignore missing SMTP class in PHPMailer 5.2.21 + # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php + message: '(^Instantiated class SMTP not found\.$)' + path: addon/mailstream/phpmailer diff --git a/.phpstan.neon b/.phpstan.neon index bf01c3cc07..fb731728b8 100644 --- a/.phpstan.neon +++ b/.phpstan.neon @@ -6,7 +6,6 @@ parameters: level: 3 paths: - # - addon/ - bin/auth_ejabberd.php - bin/console.php - bin/daemon.php @@ -15,13 +14,6 @@ parameters: - index.php - src/ - excludePaths: - analyse: - - addon/*/lang/* - - addon/*/vendor/* - - addon/convert/UnitConvertor.php - - addon/pumpio/oauth/* - scanDirectories: - mod - static @@ -46,27 +38,3 @@ parameters: # Ignore missing IMAP\Connection class in PHP <= 8.0 message: '(^Parameter .+ has invalid type IMAP\\Connection\.$)' path: src - - # - - # Ignore missing SMTP class in PHPMailer 5.2.21 - # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php - # message: '(^.+ an unknown class SMTP\.$)' - # path: addon/mailstream/phpmailer - - # - - # Ignore missing SMTP class in PHPMailer 5.2.21 - # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php - # message: '(^Property .+ has unknown class SMTP as its type\.$)' - # path: addon/mailstream/phpmailer - - # - - # Ignore missing SMTP class in PHPMailer 5.2.21 - # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php - # message: '(^Method .+ has invalid return type SMTP\.$)' - # path: addon/mailstream/phpmailer - - # - - # Ignore missing SMTP class in PHPMailer 5.2.21 - # see https://github.com/PHPMailer/PHPMailer/blob/v5.2.21/class.smtp.php - # message: '(^Instantiated class SMTP not found\.$)' - # path: addon/mailstream/phpmailer diff --git a/composer.json b/composer.json index a2c9eea3c9..5e5344eeab 100644 --- a/composer.json +++ b/composer.json @@ -163,6 +163,7 @@ "test:unit": "phpunit -c tests/phpunit.xml --testsuite unit", "phpmd": "phpmd src/ text .phpmd-ruleset.xml --color --cache", "phpstan": "phpstan analyze --memory-limit 1024M --configuration .phpstan.neon", + "phpstan-addons": "phpstan analyze --memory-limit 1024M --configuration .phpstan-addons.neon", "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './view/asset/*' -print0 | xargs -0 -n1 php -l", "docker:translate": "docker run --rm -v $PWD:/data -w /data friendicaci/transifex bin/run_xgettext.sh", "lang:recreate": "bin/run_xgettext.sh", From 8e7676bfd8152271e120a46145bf8cf76639bed4 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 14:33:56 +0000 Subject: [PATCH 12/91] Add CI step for PHPStan in addons folder --- .github/workflows/code-quality.yml | 32 ++++++++++++++++++++++++++++++ .woodpecker/.phpunit.yml | 9 ++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 9c8e20ee5f..bcca97c908 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -76,6 +76,38 @@ jobs: - name: Run PHPStan run: composer run phpstan + phpstan-addons: + name: PHPStan in addons (PHP ${{ matrix.php }}) + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + operating-system: ['ubuntu-latest'] + php: ['8.4'] + + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 2 + + - name: Setup PHP with composer and extensions + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + with: + php-version: ${{ matrix.php }} + coverage: xdebug + tools: none + + - name: Clone addon repository + run: git clone -b develop --single-branch https://git.friendi.ca/friendica/friendica-addons.git addon + + - name: Install Composer dependencies + uses: "ramsey/composer-install@v2" + + - name: Run PHPStan in addons + run: composer run phpstan-addons + phpmd: name: PHPMD (PHP ${{ matrix.php }}) runs-on: ubuntu-latest diff --git a/.woodpecker/.phpunit.yml b/.woodpecker/.phpunit.yml index 04c66bcb97..3b8f466d13 100644 --- a/.woodpecker/.phpunit.yml +++ b/.woodpecker/.phpunit.yml @@ -64,9 +64,16 @@ steps: image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION} when: matrix: - PHP_MAJOR_VERSION: 8.2 + PHP_MAJOR_VERSION: 8.3 commands: - bin/composer.phar run phpstan; + phpstan-addons: + image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION} + when: + matrix: + PHP_MAJOR_VERSION: 8.3 + commands: + - bin/composer.phar run phpstan-addons; test: image: friendicaci/php${PHP_MAJOR_VERSION}:php${PHP_VERSION} environment: From 35d95b991bd51cf0f27691f2e03ae92941261d76 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Feb 2025 15:26:16 +0000 Subject: [PATCH 13/91] Fix 4 PHPStan errors --- .../Notifications/Repository/Notification.php | 55 +++++++----------- .../Notifications/Repository/Notify.php | 29 ++++------ .../ValueObject/Introduction.php | 58 +++++++++---------- .../HTTPClient/Response/CurlResult.php | 2 +- .../HTTPClient/Response/GuzzleResponse.php | 2 +- 5 files changed, 65 insertions(+), 81 deletions(-) diff --git a/src/Navigation/Notifications/Repository/Notification.php b/src/Navigation/Notifications/Repository/Notification.php index 11d3bd6b54..e0e1d2aa98 100644 --- a/src/Navigation/Notifications/Repository/Notification.php +++ b/src/Navigation/Notifications/Repository/Notification.php @@ -15,8 +15,8 @@ use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\Model\Post\UserNotification; use Friendica\Model\Verb; -use Friendica\Navigation\Notifications\Collection; -use Friendica\Navigation\Notifications\Entity; +use Friendica\Navigation\Notifications\Collection\Notifications as NotificationsCollection; +use Friendica\Navigation\Notifications\Entity\Notification as NotificationEntity; use Friendica\Navigation\Notifications\Factory; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Protocol\Activity; @@ -41,19 +41,18 @@ class Notification extends BaseRepository } /** - * @param array $condition - * @param array $params - * @return Entity\Notification * @throws NotFoundException */ - private function selectOne(array $condition, array $params = []): Entity\Notification + private function selectOne(array $condition, array $params = []): NotificationEntity { - return parent::_selectOne($condition, $params); + $fields = $this->_selectFirstRowAsArray( $condition, $params); + + return $this->factory->createFromTableRow($fields); } - private function select(array $condition, array $params = []): Collection\Notifications + private function select(array $condition, array $params = []): NotificationsCollection { - return new Collection\Notifications(parent::_select($condition, $params)->getArrayCopy()); + return new NotificationsCollection(parent::_select($condition, $params)->getArrayCopy()); } public function countForUser($uid, array $condition, array $params = []): int @@ -71,23 +70,21 @@ class Notification extends BaseRepository } /** - * @param int $id - * @return Entity\Notification * @throws NotFoundException */ - public function selectOneById(int $id): Entity\Notification + public function selectOneById(int $id): NotificationEntity { return $this->selectOne(['id' => $id]); } - public function selectOneForUser(int $uid, array $condition, array $params = []): Entity\Notification + public function selectOneForUser(int $uid, array $condition, array $params = []): NotificationEntity { $condition = DBA::mergeConditions($condition, ['uid' => $uid]); return $this->selectOne($condition, $params); } - public function selectForUser(int $uid, array $condition = [], array $params = []): Collection\Notifications + public function selectForUser(int $uid, array $condition = [], array $params = []): NotificationsCollection { $condition = DBA::mergeConditions($condition, ['uid' => $uid]); @@ -98,12 +95,9 @@ class Notification extends BaseRepository /** * Returns only the most recent notifications for the same conversation or contact * - * @param int $uid - * - * @return Collection\Notifications * @throws Exception */ - public function selectDetailedForUser(int $uid): Collection\Notifications + public function selectDetailedForUser(int $uid): NotificationsCollection { $notify_type = $this->pconfig->get($uid, 'system', 'notify_type'); if (!is_null($notify_type)) { @@ -113,11 +107,11 @@ class Notification extends BaseRepository } if (!$this->pconfig->get($uid, 'system', 'notify_like')) { - $condition = DBA::mergeConditions($condition, ['NOT `vid` IN (?, ?)', Verb::getID(\Friendica\Protocol\Activity::LIKE), Verb::getID(\Friendica\Protocol\Activity::DISLIKE)]); + $condition = DBA::mergeConditions($condition, ['NOT `vid` IN (?, ?)', Verb::getID(Activity::LIKE), Verb::getID(Activity::DISLIKE)]); } if (!$this->pconfig->get($uid, 'system', 'notify_announce')) { - $condition = DBA::mergeConditions($condition, ['`vid` != ?', Verb::getID(\Friendica\Protocol\Activity::ANNOUNCE)]); + $condition = DBA::mergeConditions($condition, ['`vid` != ?', Verb::getID(Activity::ANNOUNCE)]); } return $this->selectForUser($uid, $condition, ['limit' => 50, 'order' => ['id' => true]]); @@ -126,12 +120,9 @@ class Notification extends BaseRepository /** * Returns only the most recent notifications for the same conversation or contact * - * @param int $uid - * - * @return Collection\Notifications * @throws Exception */ - public function selectDigestForUser(int $uid): Collection\Notifications + public function selectDigestForUser(int $uid): NotificationsCollection { $values = [$uid]; @@ -145,14 +136,14 @@ class Notification extends BaseRepository $like_condition = ''; if (!$this->pconfig->get($uid, 'system', 'notify_like')) { $like_condition = 'AND NOT `vid` IN (?, ?)'; - $values[] = Verb::getID(\Friendica\Protocol\Activity::LIKE); - $values[] = Verb::getID(\Friendica\Protocol\Activity::DISLIKE); + $values[] = Verb::getID(Activity::LIKE); + $values[] = Verb::getID(Activity::DISLIKE); } $announce_condition = ''; if (!$this->pconfig->get($uid, 'system', 'notify_announce')) { $announce_condition = 'AND vid != ?'; - $values[] = Verb::getID(\Friendica\Protocol\Activity::ANNOUNCE); + $values[] = Verb::getID(Activity::ANNOUNCE); } $rows = $this->db->p(" @@ -171,7 +162,7 @@ class Notification extends BaseRepository LIMIT 50 ", ...$values); - $Entities = new Collection\Notifications(); + $Entities = new NotificationsCollection(); foreach ($rows as $fields) { $Entities[] = $this->factory->createFromTableRow($fields); } @@ -179,7 +170,7 @@ class Notification extends BaseRepository return $Entities; } - public function selectAllForUser(int $uid): Collection\Notifications + public function selectAllForUser(int $uid): NotificationsCollection { return $this->selectForUser($uid); } @@ -199,7 +190,7 @@ class Notification extends BaseRepository { $BaseCollection = parent::_selectByBoundaries($condition, $params, $min_id, $max_id, $limit); - return new Collection\Notifications($BaseCollection->getArrayCopy(), $BaseCollection->getTotalCount()); + return new NotificationsCollection($BaseCollection->getArrayCopy(), $BaseCollection->getTotalCount()); } public function setAllSeenForUser(int $uid, array $condition = []): bool @@ -217,11 +208,9 @@ class Notification extends BaseRepository } /** - * @param Entity\Notification $Notification - * @return Entity\Notification * @throws Exception */ - public function save(Entity\Notification $Notification): Entity\Notification + public function save(NotificationEntity $Notification): NotificationEntity { $fields = [ 'uid' => $Notification->uid, diff --git a/src/Navigation/Notifications/Repository/Notify.php b/src/Navigation/Notifications/Repository/Notify.php index 1c793faaee..8c8cde1333 100644 --- a/src/Navigation/Notifications/Repository/Notify.php +++ b/src/Navigation/Notifications/Repository/Notify.php @@ -20,7 +20,8 @@ use Friendica\Database\DBA; use Friendica\Factory\Api\Mastodon\Notification as NotificationFactory; use Friendica\Model; use Friendica\Navigation\Notifications\Collection; -use Friendica\Navigation\Notifications\Entity; +use Friendica\Navigation\Notifications\Entity\Notification as NotificationEntity; +use Friendica\Navigation\Notifications\Entity\Notify as NotifyEntity; use Friendica\Navigation\Notifications\Exception; use Friendica\Navigation\Notifications\Factory; use Friendica\Network\HTTPException; @@ -31,7 +32,7 @@ use Friendica\Util\Emailer; use Psr\Log\LoggerInterface; /** - * @deprecated since 2022.05 Use \Friendica\Navigation\Notifications\Repository\Notification instead + * @deprecated 2022.05 Use `\Friendica\Navigation\Notifications\Repository\Notification` instead */ class Notify extends BaseRepository { @@ -71,15 +72,13 @@ class Notify extends BaseRepository } /** - * @param array $condition - * @param array $params - * - * @return Entity\Notify * @throws HTTPException\NotFoundException */ - private function selectOne(array $condition, array $params = []): Entity\Notify + private function selectOne(array $condition, array $params = []): NotifyEntity { - return parent::_selectOne($condition, $params); + $fields = $this->_selectFirstRowAsArray( $condition, $params); + + return $this->factory->createFromTableRow($fields); } private function select(array $condition, array $params = []): Collection\Notifies @@ -104,10 +103,9 @@ class Notify extends BaseRepository /** * @param int $id * - * @return Entity\Notify * @throws HTTPException\NotFoundException */ - public function selectOneById(int $id): Entity\Notify + public function selectOneById(int $id): NotifyEntity { return $this->selectOne(['id' => $id]); } @@ -139,14 +137,11 @@ class Notify extends BaseRepository } /** - * @param Entity\Notify $Notify - * - * @return Entity\Notify * @throws HTTPException\NotFoundException * @throws HTTPException\InternalServerErrorException * @throws Exception\NotificationCreationInterceptedException */ - public function save(Entity\Notify $Notify): Entity\Notify + public function save(NotifyEntity $Notify): NotifyEntity { $fields = [ 'type' => $Notify->type, @@ -181,7 +176,7 @@ class Notify extends BaseRepository return $Notify; } - public function setAllSeenForRelatedNotify(Entity\Notify $Notify): bool + public function setAllSeenForRelatedNotify(NotifyEntity $Notify): bool { $condition = [ '(`link` = ? OR (`parent` != 0 AND `parent` = ? AND `otype` = ?)) AND `uid` = ?', @@ -670,7 +665,7 @@ class Notify extends BaseRepository return false; } - public function shouldShowOnDesktop(Entity\Notification $Notification, string $type = null): bool + public function shouldShowOnDesktop(NotificationEntity $Notification, string $type = null): bool { if (is_null($type)) { $type = NotificationFactory::getType($Notification); @@ -702,7 +697,7 @@ class Notify extends BaseRepository return false; } - public function createFromNotification(Entity\Notification $Notification): bool + public function createFromNotification(NotificationEntity $Notification): bool { $this->logger->info('Start', ['uid' => $Notification->uid, 'id' => $Notification->id, 'type' => $Notification->type]); diff --git a/src/Navigation/Notifications/ValueObject/Introduction.php b/src/Navigation/Notifications/ValueObject/Introduction.php index 587daa8f4e..6e2c24d340 100644 --- a/src/Navigation/Notifications/ValueObject/Introduction.php +++ b/src/Navigation/Notifications/ValueObject/Introduction.php @@ -61,6 +61,34 @@ class Introduction implements \JsonSerializable /** @var string */ private $about; + public function __construct(array $data = []) + { + $this->label = $data['label'] ?? ''; + $this->type = $data['str_type'] ?? ''; + $this->intro_id = $data['intro_id'] ?? -1; + $this->madeBy = $data['madeBy'] ?? ''; + $this->madeByUrl = $data['madeByUrl'] ?? ''; + $this->madeByZrl = $data['madeByZrl'] ?? ''; + $this->madeByAddr = $data['madeByAddr'] ?? ''; + $this->contactId = $data['contactId'] ?? -1; + $this->photo = $data['photo'] ?? ''; + $this->name = $data['name'] ?? ''; + $this->url = $data['url'] ?? ''; + $this->zrl = $data['zrl'] ?? ''; + $this->hidden = $data['hidden'] ?? false; + $this->postNewFriend = $data['postNewFriend'] ?? ''; + $this->knowYou = $data['knowYou'] ?? false; + $this->note = $data['note'] ?? ''; + $this->request = $data['request'] ?? ''; + $this->dfrnId = -1; + $this->addr = $data['addr'] ?? ''; + $this->network = $data['network'] ?? ''; + $this->uid = $data['uid'] ?? -1; + $this->keywords = $data['keywords'] ?? ''; + $this->location = $data['location'] ?? ''; + $this->about = $data['about'] ?? ''; + } + public function getLabel(): string { return $this->label; @@ -131,7 +159,7 @@ class Introduction implements \JsonSerializable return $this->postNewFriend; } - public function getKnowYou(): string + public function getKnowYou(): bool { return $this->knowYou; } @@ -181,34 +209,6 @@ class Introduction implements \JsonSerializable return $this->about; } - public function __construct(array $data = []) - { - $this->label = $data['label'] ?? ''; - $this->type = $data['str_type'] ?? ''; - $this->intro_id = $data['intro_id'] ?? -1; - $this->madeBy = $data['madeBy'] ?? ''; - $this->madeByUrl = $data['madeByUrl'] ?? ''; - $this->madeByZrl = $data['madeByZrl'] ?? ''; - $this->madeByAddr = $data['madeByAddr'] ?? ''; - $this->contactId = $data['contactId'] ?? -1; - $this->photo = $data['photo'] ?? ''; - $this->name = $data['name'] ?? ''; - $this->url = $data['url'] ?? ''; - $this->zrl = $data['zrl'] ?? ''; - $this->hidden = $data['hidden'] ?? false; - $this->postNewFriend = $data['postNewFriend'] ?? ''; - $this->knowYou = $data['knowYou'] ?? false; - $this->note = $data['note'] ?? ''; - $this->request = $data['request'] ?? ''; - $this->dfrnId = -1; - $this->addr = $data['addr'] ?? ''; - $this->network = $data['network'] ?? ''; - $this->uid = $data['uid'] ?? -1; - $this->keywords = $data['keywords'] ?? ''; - $this->location = $data['location'] ?? ''; - $this->about = $data['about'] ?? ''; - } - /** * @inheritDoc */ diff --git a/src/Network/HTTPClient/Response/CurlResult.php b/src/Network/HTTPClient/Response/CurlResult.php index a79023132a..30b8be3830 100644 --- a/src/Network/HTTPClient/Response/CurlResult.php +++ b/src/Network/HTTPClient/Response/CurlResult.php @@ -246,7 +246,7 @@ class CurlResult implements ICanHandleHttpResponses /** {@inheritDoc} */ public function getReturnCode(): string { - return $this->returnCode; + return (string) $this->returnCode; } /** {@inheritDoc} */ diff --git a/src/Network/HTTPClient/Response/GuzzleResponse.php b/src/Network/HTTPClient/Response/GuzzleResponse.php index 0e246a0cb0..fde67cdd8c 100644 --- a/src/Network/HTTPClient/Response/GuzzleResponse.php +++ b/src/Network/HTTPClient/Response/GuzzleResponse.php @@ -100,7 +100,7 @@ class GuzzleResponse extends Response implements ICanHandleHttpResponses, Respon /** {@inheritDoc} */ public function getReturnCode(): string { - return $this->getStatusCode(); + return (string) $this->getStatusCode(); } /** {@inheritDoc} */ From 1820bfc2b3edb4936acfa69c7da8ea3a9f8307a7 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 26 Feb 2025 08:11:50 +0000 Subject: [PATCH 14/91] Fix 5 PHPStan errors --- src/Database/Database.php | 2 +- .../Collection/Notifications.php | 40 +++++++++++++------ .../Notifications/Collection/Notifies.php | 18 +++++---- .../Notifications/Repository/Notification.php | 13 ++++-- 4 files changed, 47 insertions(+), 26 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 6ee4394901..14416a1899 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -474,7 +474,7 @@ class Database * * @param string $sql SQL statement * - * @return bool|object statement object or result object + * @return bool|mysqli_result|mysqli_stmt|object|PDOStatement statement object or result object * @throws \Exception */ public function p(string $sql) diff --git a/src/Navigation/Notifications/Collection/Notifications.php b/src/Navigation/Notifications/Collection/Notifications.php index 2174b213a9..4c32cf598b 100644 --- a/src/Navigation/Notifications/Collection/Notifications.php +++ b/src/Navigation/Notifications/Collection/Notifications.php @@ -8,36 +8,50 @@ namespace Friendica\Navigation\Notifications\Collection; use Friendica\BaseCollection; -use Friendica\Navigation\Notifications\Entity; +use Friendica\Navigation\Notifications\Entity\Notification as NotificationEntity; class Notifications extends BaseCollection { - /** - * @return Entity\Notification - */ - public function current(): Entity\Notification + public function current(): NotificationEntity { return parent::current(); } public function setSeen(): Notifications { - return $this->map(function (Entity\Notification $Notification) { - $Notification->setSeen(); - }); + $class = get_class($this); + + return new $class( + array_map( + function (NotificationEntity $notification) { + $notification->setSeen(); + }, + $this->getArrayCopy() + ), + $this->getTotalCount(), + ); } public function setDismissed(): Notifications { - return $this->map(function (Entity\Notification $Notification) { - $Notification->setDismissed(); - }); + $class = get_class($this); + + return new $class( + array_map( + function (NotificationEntity $notification) { + $notification->setDismissed(); + }, + $this->getArrayCopy(), + ), + $this->getTotalCount(), + ); + } public function countUnseen(): int { - return array_reduce($this->getArrayCopy(), function (int $carry, Entity\Notification $Notification) { - return $carry + ($Notification->seen ? 0 : 1); + return array_reduce($this->getArrayCopy(), function (int $carry, NotificationEntity $notification) { + return $carry + ($notification->seen ? 0 : 1); }, 0); } } diff --git a/src/Navigation/Notifications/Collection/Notifies.php b/src/Navigation/Notifications/Collection/Notifies.php index 4f41d2e261..fc97880de3 100644 --- a/src/Navigation/Notifications/Collection/Notifies.php +++ b/src/Navigation/Notifications/Collection/Notifies.php @@ -8,22 +8,24 @@ namespace Friendica\Navigation\Notifications\Collection; use Friendica\BaseCollection; -use Friendica\Navigation\Notifications\Entity; +use Friendica\Navigation\Notifications\Entity\Notify as NotifyEntity; class Notifies extends BaseCollection { - /** - * @return Entity\Notify - */ - public function current(): Entity\Notify + public function current(): NotifyEntity { return parent::current(); } public function setSeen(): Notifies { - return $this->map(function (Entity\Notify $Notify) { - $Notify->setSeen(); - }); + $class = get_class($this); + + return new $class(array_map( + function (NotifyEntity $notify) { + $notify->setSeen(); + }, + $this->getArrayCopy()), $this->getTotalCount(), + ); } } diff --git a/src/Navigation/Notifications/Repository/Notification.php b/src/Navigation/Notifications/Repository/Notification.php index e0e1d2aa98..49703bc1f9 100644 --- a/src/Navigation/Notifications/Repository/Notification.php +++ b/src/Navigation/Notifications/Repository/Notification.php @@ -162,12 +162,17 @@ class Notification extends BaseRepository LIMIT 50 ", ...$values); - $Entities = new NotificationsCollection(); - foreach ($rows as $fields) { - $Entities[] = $this->factory->createFromTableRow($fields); + $entities = new NotificationsCollection(); + + if (!is_iterable($rows)) { + return $entities; } - return $Entities; + foreach ($rows as $fields) { + $entities[] = $this->factory->createFromTableRow($fields); + } + + return $entities; } public function selectAllForUser(int $uid): NotificationsCollection From f64660ec255873840a7766fc3228a5a433f6c3ce Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 26 Feb 2025 08:15:27 +0000 Subject: [PATCH 15/91] Deprecate BaseCollection::map() method --- src/BaseCollection.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/BaseCollection.php b/src/BaseCollection.php index b30dbfc6b0..36c6b9a63e 100644 --- a/src/BaseCollection.php +++ b/src/BaseCollection.php @@ -83,12 +83,16 @@ class BaseCollection extends \ArrayIterator /** * Apply a callback function on all elements in the collection and returns a new collection with the updated elements * + * @deprecated 2025.05 Use `array_map()` instead + * * @param callable $callback * @return BaseCollection * @see array_map() */ public function map(callable $callback): BaseCollection { + @trigger_error('`' . __METHOD__ . '()` is deprecated since 2025.05 and will be removed after 5 months, use `array_map()` instead.', E_USER_DEPRECATED); + $class = get_class($this); return new $class(array_map($callback, $this->getArrayCopy()), $this->getTotalCount()); From b6312f1dfcd637d9dbabd49a5ded8395616b3c7d Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 26 Feb 2025 13:00:50 +0000 Subject: [PATCH 16/91] Fix 10 PHPStan errors --- src/Module/Api/Mastodon/Search.php | 5 +++++ src/Module/Api/Twitter/Lists/Ownership.php | 7 +++++-- src/Module/Conversation/Network.php | 4 ++-- src/Module/Filer/RemoveTag.php | 9 ++++----- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Module/Api/Mastodon/Search.php b/src/Module/Api/Mastodon/Search.php index 9301c60cdc..c054329dde 100644 --- a/src/Module/Api/Mastodon/Search.php +++ b/src/Module/Api/Mastodon/Search.php @@ -196,6 +196,11 @@ class Search extends BaseApi $tags = DBA::select('tag', ['name'], $condition, $params); $hashtags = []; + + if (!is_iterable($tags)) { + return $hashtags; + } + foreach ($tags as $tag) { if ($version == 1) { $hashtags[] = $tag['name']; diff --git a/src/Module/Api/Twitter/Lists/Ownership.php b/src/Module/Api/Twitter/Lists/Ownership.php index bdf34ed280..0b18f6bc18 100644 --- a/src/Module/Api/Twitter/Lists/Ownership.php +++ b/src/Module/Api/Twitter/Lists/Ownership.php @@ -48,8 +48,11 @@ class Ownership extends BaseApi // loop through all circles $lists = []; - foreach ($circles as $circle) { - $lists[] = $this->friendicaCircle->createFromId($circle['id']); + + if (is_iterable($circles)) { + foreach ($circles as $circle) { + $lists[] = $this->friendicaCircle->createFromId($circle['id']); + } } $this->response->addFormattedContent('statuses', ['lists' => ['lists' => $lists]], $this->parameters['extension'] ?? null, Contact::getPublicIdByUserId($uid)); diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index 86c2fcf736..629295f7c8 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -59,9 +59,9 @@ class Network extends Timeline protected $dateFrom; /** @var string */ protected $dateTo; - /** @var int */ + /** @var bool */ protected $star; - /** @var int */ + /** @var bool */ protected $mention; /** @var AppHelper */ diff --git a/src/Module/Filer/RemoveTag.php b/src/Module/Filer/RemoveTag.php index 330f6953a6..28666c8a44 100644 --- a/src/Module/Filer/RemoveTag.php +++ b/src/Module/Filer/RemoveTag.php @@ -11,7 +11,6 @@ use Friendica\App; use Friendica\BaseModule; use Friendica\Core\L10n; use Friendica\Core\Session\Capability\IHandleUserSessions; -use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\Model\Post; use Friendica\Module\Response; @@ -59,15 +58,15 @@ class RemoveTag extends BaseModule } /** - * @param array $request The $_REQUEST array - * @param string|null $type Output parameter with the computed type - * @param string|null $term Output parameter with the computed term + * @param array $request The $_REQUEST array + * @param string|int|null $type Output parameter with the computed type + * @param string|null $term Output parameter with the computed term * * @return int The relevant HTTP code * * @throws \Exception */ - private function removeTag(array $request, string &$type = null, string &$term = null): int + private function removeTag(array $request, &$type = null, string &$term = null): int { $item_id = $this->parameters['id'] ?? 0; From 3bc3f5fe4d59fabeb2664c8a4b082f3c53f9e311 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 26 Feb 2025 15:06:57 +0000 Subject: [PATCH 17/91] Fix 2 PHPStan errors --- src/Moderation/Repository/Report.php | 33 +++++++++++++--------- src/Module/Api/Mastodon/Lists/Accounts.php | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/src/Moderation/Repository/Report.php b/src/Moderation/Repository/Report.php index 69ca81c167..9777e6b9cf 100644 --- a/src/Moderation/Repository/Report.php +++ b/src/Moderation/Repository/Report.php @@ -7,12 +7,14 @@ namespace Friendica\Moderation\Repository; -use Friendica\BaseEntity; use Friendica\Database\Database; -use Friendica\DI; use Friendica\Model\Post; -use Friendica\Moderation\Factory; -use Friendica\Moderation\Collection; +use Friendica\Moderation\Collection\Report\Posts as PostsCollection; +use Friendica\Moderation\Collection\Report\Rules as RulesCollection; +use Friendica\Moderation\Entity\Report as ReportEntity; +use Friendica\Moderation\Factory\Report as ReportFactory; +use Friendica\Moderation\Factory\Report\Post as PostFactory; +use Friendica\Moderation\Factory\Report\Rule as RuleFactory; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Util\DateTimeFormat; use Psr\Log\LoggerInterface; @@ -21,14 +23,14 @@ final class Report extends \Friendica\BaseRepository { protected static $table_name = 'report'; - /** @var Factory\Report */ + /** @var ReportFactory */ protected $factory; - /** @var Factory\Report\Post */ + /** @var PostFactory */ protected $postFactory; - /** @var Factory\Report\Rule */ + /** @var RuleFactory */ protected $ruleFactory; - public function __construct(Database $database, LoggerInterface $logger, Factory\Report $factory, Factory\Report\Post $postFactory, Factory\Report\Rule $ruleFactory) + public function __construct(Database $database, LoggerInterface $logger, ReportFactory $factory, PostFactory $postFactory, RuleFactory $ruleFactory) { parent::__construct($database, $logger, $factory); @@ -37,12 +39,12 @@ final class Report extends \Friendica\BaseRepository $this->ruleFactory = $ruleFactory; } - public function selectOneById(int $lastInsertId): \Friendica\Moderation\Entity\Report + public function selectOneById(int $lastInsertId): ReportEntity { return $this->_selectOne(['id' => $lastInsertId]); } - public function save(\Friendica\Moderation\Entity\Report $Report): \Friendica\Moderation\Entity\Report + public function save(ReportEntity $Report): ReportEntity { $fields = [ 'reporter-id' => $Report->reporterCid, @@ -73,7 +75,7 @@ final class Report extends \Friendica\BaseRepository if (Post::exists(['uri-id' => $post->uriId])) { $this->db->insert('report-post', ['rid' => $newReportId, 'uri-id' => $post->uriId, 'status' => $post->status]); } else { - DI::logger()->notice('Post does not exist', ['uri-id' => $post->uriId, 'report' => $Report]); + $this->logger->notice('Post does not exist', ['uri-id' => $post->uriId, 'report' => $Report]); } } @@ -87,15 +89,18 @@ final class Report extends \Friendica\BaseRepository return $Report; } - protected function _selectOne(array $condition, array $params = []): BaseEntity + /** + * @throws NotFoundException + */ + protected function _selectOne(array $condition, array $params = []): ReportEntity { $fields = $this->db->selectFirst(self::$table_name, [], $condition, $params); if (!$this->db->isResult($fields)) { throw new NotFoundException(); } - $reportPosts = new Collection\Report\Posts(array_map([$this->postFactory, 'createFromTableRow'], $this->db->selectToArray('report-post', ['uri-id', 'status'], ['rid' => $condition['id'] ?? 0]))); - $reportRules = new Collection\Report\Rules(array_map([$this->ruleFactory, 'createFromTableRow'], $this->db->selectToArray('report-rule', ['line-id', 'text'], ['rid' => $condition['id'] ?? 0]))); + $reportPosts = new PostsCollection(array_map([$this->postFactory, 'createFromTableRow'], $this->db->selectToArray('report-post', ['uri-id', 'status'], ['rid' => $condition['id'] ?? 0]))); + $reportRules = new RulesCollection(array_map([$this->ruleFactory, 'createFromTableRow'], $this->db->selectToArray('report-rule', ['line-id', 'text'], ['rid' => $condition['id'] ?? 0]))); return $this->factory->createFromTableRow($fields, $reportPosts, $reportRules); } diff --git a/src/Module/Api/Mastodon/Lists/Accounts.php b/src/Module/Api/Mastodon/Lists/Accounts.php index 796ced67b8..65a76c78ea 100644 --- a/src/Module/Api/Mastodon/Lists/Accounts.php +++ b/src/Module/Api/Mastodon/Lists/Accounts.php @@ -31,7 +31,7 @@ class Accounts extends BaseApi $this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity()); } - return Circle::removeMembers($this->parameters['id'], $request['account_ids']); + Circle::removeMembers($this->parameters['id'], $request['account_ids']); } protected function post(array $request = []) From 354d13167edb2138099e8e14ce64bcfdb6c97726 Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Thu, 27 Feb 2025 12:50:19 +0100 Subject: [PATCH 18/91] Update src/Module/Api/Mastodon/Search.php Co-authored-by: Hypolite Petovan --- src/Module/Api/Mastodon/Search.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Module/Api/Mastodon/Search.php b/src/Module/Api/Mastodon/Search.php index c054329dde..d7224ff950 100644 --- a/src/Module/Api/Mastodon/Search.php +++ b/src/Module/Api/Mastodon/Search.php @@ -193,14 +193,10 @@ class Search extends BaseApi $condition = ["`id` IN (SELECT `tid` FROM `post-tag` WHERE `type` = ?) AND `name` LIKE ?", Tag::HASHTAG, $q . '%']; - $tags = DBA::select('tag', ['name'], $condition, $params); + $tags = DBA::selectToArray('tag', ['name'], $condition, $params); $hashtags = []; - if (!is_iterable($tags)) { - return $hashtags; - } - foreach ($tags as $tag) { if ($version == 1) { $hashtags[] = $tag['name']; From 980beb4b1c0fcf09eeb622dd45b0cd2fe3a59af7 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 27 Feb 2025 12:47:25 +0000 Subject: [PATCH 19/91] Use selectToArray() instead of select() and is_iterable() --- src/Module/Api/Twitter/Lists/Ownership.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Module/Api/Twitter/Lists/Ownership.php b/src/Module/Api/Twitter/Lists/Ownership.php index 0b18f6bc18..bea9367a6d 100644 --- a/src/Module/Api/Twitter/Lists/Ownership.php +++ b/src/Module/Api/Twitter/Lists/Ownership.php @@ -44,15 +44,13 @@ class Ownership extends BaseApi $this->checkAllowedScope(BaseApi::SCOPE_READ); $uid = BaseApi::getCurrentUserID(); - $circles = $this->dba->select('group', [], ['deleted' => false, 'uid' => $uid, 'cid' => null]); + $circles = $this->dba->selectToArray('group', [], ['deleted' => false, 'uid' => $uid, 'cid' => null]); // loop through all circles $lists = []; - if (is_iterable($circles)) { - foreach ($circles as $circle) { - $lists[] = $this->friendicaCircle->createFromId($circle['id']); - } + foreach ($circles as $circle) { + $lists[] = $this->friendicaCircle->createFromId($circle['id']); } $this->response->addFormattedContent('statuses', ['lists' => ['lists' => $lists]], $this->parameters['extension'] ?? null, Contact::getPublicIdByUserId($uid)); From 4ebabd5997fec5ea0fd1cb6db0375e1e38c18a67 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 5 Mar 2025 14:27:34 +0000 Subject: [PATCH 20/91] Fix 7 PHPStan errors --- src/Core/Hook.php | 2 +- src/Factory/Api/Friendica/Photo.php | 3 +-- src/Model/Item.php | 15 +++++++++++++-- src/Model/Log/ParsedLogIterator.php | 2 +- src/Model/Photo.php | 7 +++---- src/Model/Post/Delayed.php | 3 +-- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/Core/Hook.php b/src/Core/Hook.php index 44dfad70bc..8c9f3ba910 100644 --- a/src/Core/Hook.php +++ b/src/Core/Hook.php @@ -172,7 +172,7 @@ class Hook * the provided data. * * @param string $name of the hook to call - * @param string|array &$data to transmit to the callback handler + * @param string|array|null $data to transmit to the callback handler * @return void * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ diff --git a/src/Factory/Api/Friendica/Photo.php b/src/Factory/Api/Friendica/Photo.php index 82c80ac7f3..051ae66a5d 100644 --- a/src/Factory/Api/Friendica/Photo.php +++ b/src/Factory/Api/Friendica/Photo.php @@ -41,7 +41,6 @@ class Photo extends BaseFactory * @param int $scale * @param int $uid * @param string $type - * @return Array */ public function createFromId(string $photo_id, int $scale = null, int $uid, string $type = 'json', bool $with_posts = true): array { @@ -66,7 +65,7 @@ class Photo extends BaseFactory $data['id'] = $data['resource-id']; if (is_int($scale)) { - $data['data'] = base64_encode(ModelPhoto::getImageDataForPhoto($data)); + $data['data'] = base64_encode(ModelPhoto::getImageDataForPhoto($data) ?? ''); } if ($type == 'xml') { diff --git a/src/Model/Item.php b/src/Model/Item.php index 31f8a8e22e..6500c8005c 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -672,7 +672,7 @@ class Item /** * Inserts item record * - * @param array $item Item array to be inserted + * @param array $item Item array to be inserted * @param int $notify Notification (type?) * @param bool $post_local (???) * @return int Zero means error, otherwise primary key (id) is being returned @@ -695,6 +695,7 @@ class Item // If it is a posting where users should get notifications, then define it as wall posting if ($notify) { + /** @var array */ $item = $itemHelper->prepareOriginPost($item); if (is_int($notify) && in_array($notify, Worker::PRIORITIES)) { @@ -708,6 +709,7 @@ class Item $item['network'] = trim(($item['network'] ?? '') ?: Protocol::PHANTOM); } + /** @var array */ $item = $itemHelper->prepareItemData($item, (bool) $notify); // Store conversation data @@ -749,6 +751,7 @@ class Item } } + /** @var array */ $item = $itemHelper->validateItemData($item); // Ensure that there is an avatar cache @@ -846,6 +849,7 @@ class Item $dummy_session = false; } + /** @var array */ $item = $eventDispatcher->dispatch( new ArrayFilterEvent(ArrayFilterEvent::POST_LOCAL, $item) )->getArray(); @@ -3061,7 +3065,14 @@ class Item { $appHelper = DI::appHelper(); $uid = DI::userSession()->getLocalUserId(); - Hook::callAll('prepare_body_init', $item); + + $item_copy = $item; + + Hook::callAll('prepare_body_init', $item_copy); + + if (is_array($item_copy)) { + $item = $item_copy; + } // In order to provide theme developers more possibilities, event items // are treated differently. diff --git a/src/Model/Log/ParsedLogIterator.php b/src/Model/Log/ParsedLogIterator.php index 44c98462c1..58c8bddb77 100644 --- a/src/Model/Log/ParsedLogIterator.php +++ b/src/Model/Log/ParsedLogIterator.php @@ -21,7 +21,7 @@ class ParsedLogIterator implements \Iterator /** @var ReversedFileReader */ private $reader; - /** @var ParsedLogLine current iterator value*/ + /** @var ParsedLogLine|null current iterator value*/ private $value = null; /** @var int max number of lines to read */ diff --git a/src/Model/Photo.php b/src/Model/Photo.php index c275753960..74edaf360d 100644 --- a/src/Model/Photo.php +++ b/src/Model/Photo.php @@ -244,7 +244,7 @@ class Photo * * @param array $photo Photo data. Needs at least 'id', 'type', 'backend-class', 'backend-ref' * - * @return \Friendica\Object\Image|null Image object or null on error + * @return string|null Image data as string or null on error */ public static function getImageDataForPhoto(array $photo) { @@ -254,7 +254,7 @@ class Photo try { $backendClass = DI::storageManager()->getByName($photo['backend-class'] ?? ''); - /// @todo refactoring this returning, because the storage returns a "string" which is casted in different ways - a check "instanceof Image" will fail! + return $backendClass->get($photo['backend-ref'] ?? ''); } catch (InvalidClassStorageException $storageException) { try { @@ -834,10 +834,9 @@ class Photo * - Sharing a post with a group will create a photo that only the group can see. * - Sharing a photo again that been shared non public before doesn't alter the permissions. * - * @return string * @throws \Exception */ - public static function setPermissionFromBody($body, $uid, $original_contact_id, $str_contact_allow, $str_circle_allow, $str_contact_deny, $str_circle_deny) + public static function setPermissionFromBody($body, $uid, $original_contact_id, $str_contact_allow, $str_circle_allow, $str_contact_deny, $str_circle_deny): bool { // Simplify image codes $img_body = preg_replace("/\[img\=([0-9]*)x([0-9]*)\](.*?)\[\/img\]/ism", '[img]$3[/img]', $body); diff --git a/src/Model/Post/Delayed.php b/src/Model/Post/Delayed.php index e4862c27c2..b0c5d09dcd 100644 --- a/src/Model/Post/Delayed.php +++ b/src/Model/Post/Delayed.php @@ -170,9 +170,8 @@ class Delayed * @param array $attachments * @param int $preparation_mode * @param string $uri - * @return bool */ - public static function publish(array $item, int $notify = 0, array $taglist = [], array $attachments = [], int $preparation_mode = self::PREPARED, string $uri = '') + public static function publish(array $item, int $notify = 0, array $taglist = [], array $attachments = [], int $preparation_mode = self::PREPARED, string $uri = ''): int { if (!empty($attachments)) { $item['attachments'] = $attachments; From 6b7dfa34e96455405e7200d4ed5720886c47d5d1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 5 Mar 2025 15:15:18 +0000 Subject: [PATCH 21/91] fix 7 PHPStan errors in factoriy and Model --- src/Factory/Api/Mastodon/Attachment.php | 23 ++++++++++++++++------- src/Factory/Api/Twitter/Status.php | 2 +- src/Federation/Repository/GServer.php | 4 +++- src/Model/Contact/User.php | 5 ++--- src/Model/Event.php | 2 +- src/Model/GServer.php | 4 +--- 6 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/Factory/Api/Mastodon/Attachment.php b/src/Factory/Api/Mastodon/Attachment.php index ae0ebf1826..52361284ac 100644 --- a/src/Factory/Api/Mastodon/Attachment.php +++ b/src/Factory/Api/Mastodon/Attachment.php @@ -11,7 +11,7 @@ use Friendica\App\BaseURL; use Friendica\BaseFactory; use Friendica\Model\Attach; use Friendica\Model\Photo; -use Friendica\Network\HTTPException; +use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Model\Post; use Friendica\Util\Images; use Friendica\Util\Proxy; @@ -32,7 +32,7 @@ class Attachment extends BaseFactory /** * @param int $uriId Uri-ID of the attachments * @return array - * @throws HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public function createFromUriId(int $uriId): array { @@ -47,21 +47,30 @@ class Attachment extends BaseFactory /** * @param int $id id of the media * @return \Friendica\Object\Api\Mastodon\Attachment - * @throws HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public function createFromId(int $id): \Friendica\Object\Api\Mastodon\Attachment { $attachment = Post\Media::getById($id); + if (empty($attachment)) { - return []; + $attachment = [ + 'id' => '', + 'description' => '', + 'url' => '', + 'mimetype' => '', + 'blurhash' => '', + 'type' => Post\Media::UNKNOWN, + ]; } + return $this->createFromMediaArray($attachment); } /** * @param array $attachment * @return \Friendica\Object\Api\Mastodon\Attachment - * @throws HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ private function createFromMediaArray(array $attachment): \Friendica\Object\Api\Mastodon\Attachment { @@ -100,7 +109,7 @@ class Attachment extends BaseFactory * @param int $id id of the photo * * @return array - * @throws HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public function createFromPhoto(int $id): array { @@ -136,7 +145,7 @@ class Attachment extends BaseFactory * @param int $id id of the attachment * * @return array - * @throws HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ public function createFromAttach(int $id): array { diff --git a/src/Factory/Api/Twitter/Status.php b/src/Factory/Api/Twitter/Status.php index b31a89fc44..c83b0aa9ab 100644 --- a/src/Factory/Api/Twitter/Status.php +++ b/src/Factory/Api/Twitter/Status.php @@ -39,7 +39,7 @@ class Status extends BaseFactory private $mention; /** @var Activities entity */ private $activities; - /** @var Activities entity */ + /** @var Attachment entity */ private $attachment; /** @var ContentItem */ private $contentItem; diff --git a/src/Federation/Repository/GServer.php b/src/Federation/Repository/GServer.php index 5a12f3339b..8e9c7e9449 100644 --- a/src/Federation/Repository/GServer.php +++ b/src/Federation/Repository/GServer.php @@ -28,6 +28,8 @@ class GServer extends \Friendica\BaseRepository */ public function selectOneById(int $gsid): Entity\GServer { - return $this->_selectOne(['id' => $gsid]); + $fields = $this->_selectFirstRowAsArray( ['id' => $gsid]); + + return $this->factory->createFromTableRow($fields); } } diff --git a/src/Model/Contact/User.php b/src/Model/Contact/User.php index 17663e233b..aa85013811 100644 --- a/src/Model/Contact/User.php +++ b/src/Model/Contact/User.php @@ -30,9 +30,8 @@ class User * Insert a user-contact for a given contact array * * @param array $contact - * @return void */ - public static function insertForContactArray(array $contact) + public static function insertForContactArray(array $contact): bool { if (empty($contact['uid'])) { // We don't create entries for the public user - by now @@ -339,7 +338,7 @@ class User { $pcid = Contact::getPublicContactId($cid, $uid); if (!$pcid) { - return false; + return self::FREQUENCY_DEFAULT; } $public_contact = DBA::selectFirst('user-contact', ['channel-frequency'], ['cid' => $pcid, 'uid' => $uid]); diff --git a/src/Model/Event.php b/src/Model/Event.php index 6cb73f4c37..39aba01efd 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -305,7 +305,7 @@ class Event Hook::callAll("event_created", $event['id']); } - return $event['id']; + return (int) $event['id']; } public static function getItemArrayForId(int $event_id, array $item = []): array diff --git a/src/Model/GServer.php b/src/Model/GServer.php index 7029adbb53..8ead599408 100644 --- a/src/Model/GServer.php +++ b/src/Model/GServer.php @@ -2200,8 +2200,6 @@ class GServer * Converts input value to a boolean value * * @param string|integer $val - * - * @return boolean */ private static function toBoolean($val): bool { @@ -2211,7 +2209,7 @@ class GServer return false; } - return $val; + return (bool) $val; } /** From 77831aaf49770ed868d0d952caea4e15d3d2d642 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 6 Mar 2025 09:25:39 +0000 Subject: [PATCH 22/91] Handle missing attachment with correct response --- src/Factory/Api/Mastodon/Attachment.php | 9 +-------- src/Module/Api/Mastodon/Media.php | 13 ++++++++++++- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/Factory/Api/Mastodon/Attachment.php b/src/Factory/Api/Mastodon/Attachment.php index 52361284ac..bd16b61b38 100644 --- a/src/Factory/Api/Mastodon/Attachment.php +++ b/src/Factory/Api/Mastodon/Attachment.php @@ -54,14 +54,7 @@ class Attachment extends BaseFactory $attachment = Post\Media::getById($id); if (empty($attachment)) { - $attachment = [ - 'id' => '', - 'description' => '', - 'url' => '', - 'mimetype' => '', - 'blurhash' => '', - 'type' => Post\Media::UNKNOWN, - ]; + throw new InternalServerErrorException(); } return $this->createFromMediaArray($attachment); diff --git a/src/Module/Api/Mastodon/Media.php b/src/Module/Api/Mastodon/Media.php index 5dbcfc3687..f9d61e0db3 100644 --- a/src/Module/Api/Mastodon/Media.php +++ b/src/Module/Api/Mastodon/Media.php @@ -13,6 +13,7 @@ use Friendica\Model\Contact; use Friendica\Model\Photo; use Friendica\Model\Post; use Friendica\Module\BaseApi; +use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Util\Strings; /** @@ -97,14 +98,24 @@ class Media extends BaseApi $photo = Photo::selectFirst(['resource-id'], ['id' => $this->parameters['id'], 'uid' => $uid]); if (empty($photo['resource-id'])) { $media = Post\Media::getById($this->parameters['id']); + if (empty($media['uri-id'])) { $this->logAndJsonError(404, $this->errorFactory->RecordNotFound()); } + if (!Post::exists(['uri-id' => $media['uri-id'], 'uid' => $uid, 'origin' => true])) { $this->logAndJsonError(404, $this->errorFactory->RecordNotFound()); } + Post\Media::updateById(['description' => $request['description']], $this->parameters['id']); - $this->jsonExit(DI::mstdnAttachment()->createFromId($this->parameters['id'])); + + try { + $attachment = DI::mstdnAttachment()->createFromId($this->parameters['id'] . '1'); + } catch (InternalServerErrorException $th) { + $this->logAndJsonError(404, $this->errorFactory->RecordNotFound()); + } + + $this->jsonExit($attachment); } Photo::update(['desc' => $request['description']], ['resource-id' => $photo['resource-id']]); From 39754918877405d8607430374e69c0a79ae566ee Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 6 Mar 2025 11:57:29 +0000 Subject: [PATCH 23/91] Fix upload error handling for media see https://github.com/friendica/friendica/pull/14475 refs #14475 --- src/Module/Api/Mastodon/Media.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Module/Api/Mastodon/Media.php b/src/Module/Api/Mastodon/Media.php index f9d61e0db3..df6c521008 100644 --- a/src/Module/Api/Mastodon/Media.php +++ b/src/Module/Api/Mastodon/Media.php @@ -44,12 +44,13 @@ class Media extends BaseApi if (in_array($type, [Post\Media::IMAGE, Post\Media::UNKNOWN, Post\Media::APPLICATION])) { $media = Photo::upload($uid, $request['file'], '', null, null, '', '', $request['description']); - if (!empty($media)) { - $this->logger->info('Uploaded photo', ['media' => $media]); - $this->jsonExit(DI::mstdnAttachment()->createFromPhoto($media['id'])); - } elseif ($type == Post\Media::IMAGE) { - $this->jsonExit(DI::mstdnAttachment()->createFromPhoto($media['id'])); + + if (empty($media)) { + $this->logAndJsonError(500, $this->errorFactory->InternalError('Error while uploading media.')); } + + $this->logger->info('Uploaded photo', ['media' => $media]); + $this->jsonExit(DI::mstdnAttachment()->createFromPhoto($media['id'])); } $tempFileName = $request['file']['tmp_name']; From eb37bcaa74903edb72665b69ef02a6d0beba66d1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 7 Mar 2025 10:50:15 +0000 Subject: [PATCH 24/91] Change 500 response to 422 response see https://github.com/friendica/friendica/pull/14475 --- src/Module/Api/Mastodon/Media.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Api/Mastodon/Media.php b/src/Module/Api/Mastodon/Media.php index df6c521008..31ab33c527 100644 --- a/src/Module/Api/Mastodon/Media.php +++ b/src/Module/Api/Mastodon/Media.php @@ -46,7 +46,7 @@ class Media extends BaseApi $media = Photo::upload($uid, $request['file'], '', null, null, '', '', $request['description']); if (empty($media)) { - $this->logAndJsonError(500, $this->errorFactory->InternalError('Error while uploading media.')); + $this->logAndJsonError(422, $this->errorFactory->UnprocessableEntity('Error while uploading media.')); } $this->logger->info('Uploaded photo', ['media' => $media]); From 38343ee417bd1cf4f37d76e13c59779451e8d12f Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 7 Mar 2025 13:46:18 +0000 Subject: [PATCH 25/91] Refactor GServer Repository --- src/Federation/Repository/GServer.php | 29 +++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Federation/Repository/GServer.php b/src/Federation/Repository/GServer.php index 8e9c7e9449..d9d7772582 100644 --- a/src/Federation/Repository/GServer.php +++ b/src/Federation/Repository/GServer.php @@ -8,27 +8,40 @@ namespace Friendica\Federation\Repository; use Friendica\Database\Database; -use Friendica\Federation\Factory; -use Friendica\Federation\Entity; +use Friendica\Federation\Entity\GServer as GServerEntity; +use Friendica\Federation\Factory\GServer as GServerFactory; +use Friendica\Network\HTTPException\NotFoundException; use Psr\Log\LoggerInterface; -class GServer extends \Friendica\BaseRepository +final class GServer { protected static $table_name = 'gserver'; - public function __construct(Database $database, LoggerInterface $logger, Factory\GServer $factory) + protected Database $db; + + protected LoggerInterface $logger; + + protected GServerFactory $factory; + + public function __construct(Database $database, LoggerInterface $logger, GServerFactory $factory) { - parent::__construct($database, $logger, $factory); + $this->db = $database; + $this->logger = $logger; + $this->factory = $factory; } /** * @param int $gsid - * @return Entity\GServer + * * @throws \Friendica\Network\HTTPException\NotFoundException */ - public function selectOneById(int $gsid): Entity\GServer + public function selectOneById(int $gsid): GServerEntity { - $fields = $this->_selectFirstRowAsArray( ['id' => $gsid]); + $fields = $this->db->selectFirst(static::$table_name, [], ['id' => $gsid], []); + + if (!$this->db->isResult($fields)) { + throw new NotFoundException(); + } return $this->factory->createFromTableRow($fields); } From 767ac778c96eebc048a30a939b66d2e257cb1a82 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 7 Mar 2025 13:49:22 +0000 Subject: [PATCH 26/91] simplify GServer repository --- src/Federation/Repository/GServer.php | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/Federation/Repository/GServer.php b/src/Federation/Repository/GServer.php index d9d7772582..d299210800 100644 --- a/src/Federation/Repository/GServer.php +++ b/src/Federation/Repository/GServer.php @@ -11,22 +11,18 @@ use Friendica\Database\Database; use Friendica\Federation\Entity\GServer as GServerEntity; use Friendica\Federation\Factory\GServer as GServerFactory; use Friendica\Network\HTTPException\NotFoundException; -use Psr\Log\LoggerInterface; final class GServer { - protected static $table_name = 'gserver'; + private string $table_name = 'gserver'; - protected Database $db; + private Database $db; - protected LoggerInterface $logger; + private GServerFactory $factory; - protected GServerFactory $factory; - - public function __construct(Database $database, LoggerInterface $logger, GServerFactory $factory) + public function __construct(Database $database, GServerFactory $factory) { $this->db = $database; - $this->logger = $logger; $this->factory = $factory; } @@ -37,7 +33,7 @@ final class GServer */ public function selectOneById(int $gsid): GServerEntity { - $fields = $this->db->selectFirst(static::$table_name, [], ['id' => $gsid], []); + $fields = $this->db->selectFirst($this->table_name, [], ['id' => $gsid], []); if (!$this->db->isResult($fields)) { throw new NotFoundException(); From bf530a00d7fe363b36c3e4727cb8cdb2c221b8a7 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 12 Mar 2025 15:02:50 +0000 Subject: [PATCH 27/91] Fix 2 PHPStan errors --- src/Factory/Api/Twitter/Status.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Factory/Api/Twitter/Status.php b/src/Factory/Api/Twitter/Status.php index c83b0aa9ab..b77ee801f7 100644 --- a/src/Factory/Api/Twitter/Status.php +++ b/src/Factory/Api/Twitter/Status.php @@ -165,7 +165,7 @@ class Status extends BaseFactory $urls = $this->url->createFromUriId($item['uri-id']); $mentions = $this->mention->createFromUriId($item['uri-id']); } else { - $attachments = $this->attachment->createFromUriId($item['uri-id'], $text); + $attachments = $this->attachment->createFromUriId($item['uri-id']); } $friendica_activities = $this->activities->createFromUriId($item['uri-id'], $uid); @@ -180,7 +180,7 @@ class Status extends BaseFactory $urls = array_merge($urls, $this->url->createFromUriId($shared_uri_id)); $mentions = array_merge($mentions, $this->mention->createFromUriId($shared_uri_id)); } else { - $attachments = array_merge($attachments, $this->attachment->createFromUriId($shared_uri_id, $text)); + $attachments = array_merge($attachments, $this->attachment->createFromUriId($shared_uri_id)); } } From a50383836d0bbbf87b695be8e1511222bc71d897 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 12 Mar 2025 15:03:15 +0000 Subject: [PATCH 28/91] Fix 13 PHPStan errors --- src/Database/Database.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Database/Database.php b/src/Database/Database.php index 14416a1899..6f42756302 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -60,7 +60,7 @@ class Database protected $syslock = null; protected $server_info = ''; - /** @var PDO|mysqli */ + /** @var PDO|mysqli|null */ protected $connection; protected $driver = ''; protected $pdo_emulate_prepares = false; @@ -253,7 +253,7 @@ class Database /** * Return the database object. * - * @return PDO|mysqli + * @return PDO|mysqli|null */ public function getConnection() { From 268d564930d3974607aa1c14f38a9baf43b50817 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 12 Mar 2025 15:50:24 +0000 Subject: [PATCH 29/91] remove deprecation of BaseCollection::map(), check return type of BaseCollection::map() --- src/BaseCollection.php | 4 -- .../Collection/Notifications.php | 45 ++++++++++--------- .../Notifications/Collection/Notifies.php | 20 ++++++--- .../ProfileField/Collection/ProfileFields.php | 17 ++++--- 4 files changed, 50 insertions(+), 36 deletions(-) diff --git a/src/BaseCollection.php b/src/BaseCollection.php index 36c6b9a63e..b30dbfc6b0 100644 --- a/src/BaseCollection.php +++ b/src/BaseCollection.php @@ -83,16 +83,12 @@ class BaseCollection extends \ArrayIterator /** * Apply a callback function on all elements in the collection and returns a new collection with the updated elements * - * @deprecated 2025.05 Use `array_map()` instead - * * @param callable $callback * @return BaseCollection * @see array_map() */ public function map(callable $callback): BaseCollection { - @trigger_error('`' . __METHOD__ . '()` is deprecated since 2025.05 and will be removed after 5 months, use `array_map()` instead.', E_USER_DEPRECATED); - $class = get_class($this); return new $class(array_map($callback, $this->getArrayCopy()), $this->getTotalCount()); diff --git a/src/Navigation/Notifications/Collection/Notifications.php b/src/Navigation/Notifications/Collection/Notifications.php index 4c32cf598b..e422283891 100644 --- a/src/Navigation/Notifications/Collection/Notifications.php +++ b/src/Navigation/Notifications/Collection/Notifications.php @@ -19,33 +19,38 @@ class Notifications extends BaseCollection public function setSeen(): Notifications { - $class = get_class($this); + $notifications = $this->map(function (NotificationEntity $notification) { + $notification->setSeen(); + }); - return new $class( - array_map( - function (NotificationEntity $notification) { - $notification->setSeen(); - }, - $this->getArrayCopy() - ), - $this->getTotalCount(), - ); + if (!$notifications instanceof Notifications) { + // Show the possible error explicitly + throw new \Exception(sprintf( + 'BaseCollection::map() should return instance of %s, but returns %s instead.', + Notifications::class, + get_class($notifications), + )); + } + + return $notifications; } public function setDismissed(): Notifications { - $class = get_class($this); + $notifications = $this->map(function (NotificationEntity $notification) { + $notification->setDismissed(); + }); - return new $class( - array_map( - function (NotificationEntity $notification) { - $notification->setDismissed(); - }, - $this->getArrayCopy(), - ), - $this->getTotalCount(), - ); + if (!$notifications instanceof Notifications) { + // Show the possible error explicitly + throw new \Exception(sprintf( + 'BaseCollection::map() should return instance of %s, but returns %s instead.', + Notifications::class, + get_class($notifications), + )); + } + return $notifications; } public function countUnseen(): int diff --git a/src/Navigation/Notifications/Collection/Notifies.php b/src/Navigation/Notifications/Collection/Notifies.php index fc97880de3..9c2f5dcc74 100644 --- a/src/Navigation/Notifications/Collection/Notifies.php +++ b/src/Navigation/Notifications/Collection/Notifies.php @@ -19,13 +19,19 @@ class Notifies extends BaseCollection public function setSeen(): Notifies { - $class = get_class($this); + $notifies = $this->map(function (NotifyEntity $notify) { + $notify->setSeen(); + }); - return new $class(array_map( - function (NotifyEntity $notify) { - $notify->setSeen(); - }, - $this->getArrayCopy()), $this->getTotalCount(), - ); + if (!$notifies instanceof Notifies) { + // Show the possible error explicitly + throw new \Exception(sprintf( + 'BaseCollection::map() should return instance of %s, but returns %s instead.', + Notifies::class, + get_class($notifies), + )); + } + + return $notifies; } } diff --git a/src/Profile/ProfileField/Collection/ProfileFields.php b/src/Profile/ProfileField/Collection/ProfileFields.php index dcf5498df3..44f13673d7 100644 --- a/src/Profile/ProfileField/Collection/ProfileFields.php +++ b/src/Profile/ProfileField/Collection/ProfileFields.php @@ -19,15 +19,22 @@ class ProfileFields extends BaseCollection public function map(callable $callback): ProfileFields { - $class = get_class($this); + $profileFields = parent::map($callback); - return new $class(array_map($callback, $this->getArrayCopy()), $this->getTotalCount()); + if (!$profileFields instanceof ProfileFields) { + // Show the possible error explicitly + throw new \Exception(sprintf( + 'BaseCollection::map() should return instance of %s, but returns %s instead.', + ProfileFields::class, + get_class($profileFields), + )); + } + + return $profileFields; } public function filter(?callable $callback = null, int $flag = 0): ProfileFields { - $class = get_class($this); - - return new $class(array_filter($this->getArrayCopy(), $callback, $flag)); + return new self(array_filter($this->getArrayCopy(), $callback, $flag)); } } From 7ce6afd1517f136f2b3796aad9ce36a096c66125 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 09:14:48 +0000 Subject: [PATCH 30/91] Fix 10 PHPStan errors --- src/BaseCollection.php | 18 +++--- .../Repository/FriendSuggest.php | 33 ++++------- .../Introduction/Repository/Introduction.php | 58 +++++------------- .../Repository/LocalRelationship.php | 59 ++++++++----------- .../Repository/UserDefinedChannel.php | 26 ++++---- src/Content/Post/Entity/PostMedia.php | 3 +- src/Content/Post/Factory/PostMedia.php | 29 ++++----- src/Content/Post/Repository/PostMedia.php | 42 +++++++------ src/Core/Worker/Repository/Process.php | 21 +++---- 9 files changed, 122 insertions(+), 167 deletions(-) diff --git a/src/BaseCollection.php b/src/BaseCollection.php index b30dbfc6b0..d7d707960a 100644 --- a/src/BaseCollection.php +++ b/src/BaseCollection.php @@ -24,7 +24,7 @@ class BaseCollection extends \ArrayIterator * @param BaseEntity[] $entities * @param int|null $totalCount */ - public function __construct(array $entities = [], int $totalCount = null) + public function __construct(array $entities = [], ?int $totalCount = null) { parent::__construct($entities); @@ -102,7 +102,7 @@ class BaseCollection extends \ArrayIterator * @return BaseCollection * @see array_filter() */ - public function filter(callable $callback = null, int $flag = 0): BaseCollection + public function filter(?callable $callback = null, int $flag = 0): BaseCollection { $class = get_class($this); @@ -111,8 +111,6 @@ class BaseCollection extends \ArrayIterator /** * Reverse the orders of the elements in the collection - * - * @return $this */ public function reverse(): BaseCollection { @@ -125,7 +123,6 @@ class BaseCollection extends \ArrayIterator * Split the collection in smaller collections no bigger than the provided length * * @param int $length - * @return static[] */ public function chunk(int $length): array { @@ -133,11 +130,14 @@ class BaseCollection extends \ArrayIterator throw new \RangeException('BaseCollection->chunk(): Size parameter expected to be greater than 0'); } - return array_map(function ($array) { - $class = get_class($this); + return array_map( + function ($array) { + $class = get_class($this); - return new $class($array); - }, array_chunk($this->getArrayCopy(), $length)); + return new $class($array); + }, + array_chunk($this->getArrayCopy(), $length) + ); } diff --git a/src/Contact/FriendSuggest/Repository/FriendSuggest.php b/src/Contact/FriendSuggest/Repository/FriendSuggest.php index 1b22c7b797..a9f4610439 100644 --- a/src/Contact/FriendSuggest/Repository/FriendSuggest.php +++ b/src/Contact/FriendSuggest/Repository/FriendSuggest.php @@ -8,11 +8,11 @@ namespace Friendica\Contact\FriendSuggest\Repository; use Friendica\BaseRepository; -use Friendica\Contact\FriendSuggest\Collection; +use Friendica\Contact\FriendSuggest\Collection\FriendSuggests as FriendSuggestsCollection; use Friendica\Contact\FriendSuggest\Entity\FriendSuggest as FriendSuggestEntity; use Friendica\Contact\FriendSuggest\Exception\FriendSuggestNotFoundException; use Friendica\Contact\FriendSuggest\Exception\FriendSuggestPersistenceException; -use Friendica\Contact\FriendSuggest\Factory; +use Friendica\Contact\FriendSuggest\Factory\FriendSuggest as FriendSuggestFactory; use Friendica\Database\Database; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Util\DateTimeFormat; @@ -20,12 +20,12 @@ use Psr\Log\LoggerInterface; class FriendSuggest extends BaseRepository { - /** @var Factory\FriendSuggest */ + /** @var FriendSuggestFactory */ protected $factory; protected static $table_name = 'fsuggest'; - public function __construct(Database $database, LoggerInterface $logger, Factory\FriendSuggest $factory) + public function __construct(Database $database, LoggerInterface $logger, FriendSuggestFactory $factory) { parent::__construct($database, $logger, $factory); } @@ -49,20 +49,17 @@ class FriendSuggest extends BaseRepository */ private function selectOne(array $condition, array $params = []): FriendSuggestEntity { - return parent::_selectOne($condition, $params); + $fields = $this->_selectFirstRowAsArray( $condition, $params); + + return $this->factory->createFromTableRow($fields); } /** - * @param array $condition - * @param array $params - * - * @return Collection\FriendSuggests - * * @throws \Exception */ - private function select(array $condition, array $params = []): Collection\FriendSuggests + private function select(array $condition, array $params = []): FriendSuggestsCollection { - return new Collection\FriendSuggests(parent::_select($condition, $params)->getArrayCopy()); + return new FriendSuggestsCollection(parent::_select($condition, $params)->getArrayCopy()); } /** @@ -78,13 +75,9 @@ class FriendSuggest extends BaseRepository } /** - * @param int $cid - * - * @return Collection\FriendSuggests - * * @throws FriendSuggestPersistenceException In case the underlying storage cannot select the suggestion */ - public function selectForContact(int $cid): Collection\FriendSuggests + public function selectForContact(int $cid): FriendSuggestsCollection { try { return $this->select(['cid' => $cid]); @@ -114,13 +107,9 @@ class FriendSuggest extends BaseRepository } /** - * @param Collection\FriendSuggests $fsuggests - * - * @return bool - * * @throws FriendSuggestNotFoundException in case the underlying storage cannot delete the suggestion */ - public function delete(Collection\FriendSuggests $fsuggests): bool + public function delete(FriendSuggestsCollection $fsuggests): bool { try { $ids = $fsuggests->column('id'); diff --git a/src/Contact/Introduction/Repository/Introduction.php b/src/Contact/Introduction/Repository/Introduction.php index 562b3c472f..dec2f2a246 100644 --- a/src/Contact/Introduction/Repository/Introduction.php +++ b/src/Contact/Introduction/Repository/Introduction.php @@ -10,9 +10,9 @@ namespace Friendica\Contact\Introduction\Repository; use Friendica\BaseRepository; use Friendica\Contact\Introduction\Exception\IntroductionNotFoundException; use Friendica\Contact\Introduction\Exception\IntroductionPersistenceException; -use Friendica\Contact\Introduction\Collection; -use Friendica\Contact\Introduction\Entity; -use Friendica\Contact\Introduction\Factory; +use Friendica\Contact\Introduction\Collection\Introductions as IntroductionsCollection; +use Friendica\Contact\Introduction\Entity\Introduction as IntroductionEntity; +use Friendica\Contact\Introduction\Factory\Introduction as IntroductionFactory; use Friendica\Database\Database; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Util\DateTimeFormat; @@ -20,37 +20,30 @@ use Psr\Log\LoggerInterface; class Introduction extends BaseRepository { - /** @var Factory\Introduction */ + /** @var IntroductionFactory */ protected $factory; protected static $table_name = 'intro'; - public function __construct(Database $database, LoggerInterface $logger, Factory\Introduction $factory) + public function __construct(Database $database, LoggerInterface $logger, IntroductionFactory $factory) { parent::__construct($database, $logger, $factory); } /** - * @param array $condition - * @param array $params - * - * @return Entity\Introduction - * * @throws NotFoundException the underlying exception if there's no Introduction with the given conditions */ - private function selectOne(array $condition, array $params = []): Entity\Introduction + private function selectOne(array $condition, array $params = []): IntroductionEntity { - return parent::_selectOne($condition, $params); + $fields = $this->_selectFirstRowAsArray( $condition, $params); + + return $this->factory->createFromTableRow($fields); } /** * Converts a given Introduction into a DB compatible row array - * - * @param Entity\Introduction $introduction - * - * @return array */ - protected function convertToTableRow(Entity\Introduction $introduction): array + protected function convertToTableRow(IntroductionEntity $introduction): array { return [ 'uid' => $introduction->uid, @@ -65,14 +58,9 @@ class Introduction extends BaseRepository } /** - * @param int $id - * @param int $uid - * - * @return Entity\Introduction - * * @throws IntroductionNotFoundException in case there is no Introduction with this id */ - public function selectOneById(int $id, int $uid): Entity\Introduction + public function selectOneById(int $id, int $uid): IntroductionEntity { try { return $this->selectOne(['id' => $id, 'uid' => $uid]); @@ -88,10 +76,8 @@ class Introduction extends BaseRepository * @param int|null $min_id * @param int|null $max_id * @param int $limit - * - * @return Collection\Introductions */ - public function selectForUser(int $uid, int $min_id = null, int $max_id = null, int $limit = self::LIMIT): Collection\Introductions + public function selectForUser(int $uid, ?int $min_id = null, ?int $max_id = null, int $limit = self::LIMIT): IntroductionsCollection { try { $BaseCollection = parent::_selectByBoundaries( @@ -102,19 +88,15 @@ class Introduction extends BaseRepository throw new IntroductionPersistenceException(sprintf('Cannot select Introductions for used %d', $uid), $e); } - return new Collection\Introductions($BaseCollection->getArrayCopy(), $BaseCollection->getTotalCount()); + return new IntroductionsCollection($BaseCollection->getArrayCopy(), $BaseCollection->getTotalCount()); } /** * Selects the introduction for a given contact * - * @param int $cid - * - * @return Entity\Introduction - * * @throws IntroductionNotFoundException in case there is not Introduction for this contact */ - public function selectForContact(int $cid): Entity\Introduction + public function selectForContact(int $cid): IntroductionEntity { try { return $this->selectOne(['contact-id' => $cid]); @@ -150,13 +132,9 @@ class Introduction extends BaseRepository } /** - * @param Entity\Introduction $introduction - * - * @return bool - * * @throws IntroductionPersistenceException in case the underlying storage cannot delete the Introduction */ - public function delete(Entity\Introduction $introduction): bool + public function delete(IntroductionEntity $introduction): bool { if (!$introduction->id) { return false; @@ -170,13 +148,9 @@ class Introduction extends BaseRepository } /** - * @param Entity\Introduction $introduction - * - * @return Entity\Introduction - * * @throws IntroductionPersistenceException In case the underlying storage cannot save the Introduction */ - public function save(Entity\Introduction $introduction): Entity\Introduction + public function save(IntroductionEntity $introduction): IntroductionEntity { try { $fields = $this->convertToTableRow($introduction); diff --git a/src/Contact/LocalRelationship/Repository/LocalRelationship.php b/src/Contact/LocalRelationship/Repository/LocalRelationship.php index 2b9abc3dfc..f00002a066 100644 --- a/src/Contact/LocalRelationship/Repository/LocalRelationship.php +++ b/src/Contact/LocalRelationship/Repository/LocalRelationship.php @@ -7,59 +7,54 @@ namespace Friendica\Contact\LocalRelationship\Repository; -use Friendica\Contact\LocalRelationship\Entity; -use Friendica\Contact\LocalRelationship\Exception; -use Friendica\Contact\LocalRelationship\Factory; +use Exception; +use Friendica\BaseRepository; +use Friendica\Contact\LocalRelationship\Entity\LocalRelationship as LocalRelationshipEntity; +use Friendica\Contact\LocalRelationship\Exception\LocalRelationshipPersistenceException; +use Friendica\Contact\LocalRelationship\Factory\LocalRelationship as LocalRelationshipFactory; use Friendica\Database\Database; -use Friendica\Network\HTTPException; +use Friendica\Network\HTTPException\NotFoundException; use Psr\Log\LoggerInterface; -class LocalRelationship extends \Friendica\BaseRepository +class LocalRelationship extends BaseRepository { protected static $table_name = 'user-contact'; - /** @var Factory\LocalRelationship */ + /** @var LocalRelationshipFactory */ protected $factory; - public function __construct(Database $database, LoggerInterface $logger, Factory\LocalRelationship $factory) + public function __construct(Database $database, LoggerInterface $logger, LocalRelationshipFactory $factory) { parent::__construct($database, $logger, $factory); } /** - * @param int $uid - * @param int $cid - * @return Entity\LocalRelationship - * @throws HTTPException\NotFoundException + * @throws NotFoundException */ - public function selectForUserContact(int $uid, int $cid): Entity\LocalRelationship + public function selectForUserContact(int $uid, int $cid): LocalRelationshipEntity { - return $this->_selectOne(['uid' => $uid, 'cid' => $cid]); + $fields = $this->_selectFirstRowAsArray( ['uid' => $uid, 'cid' => $cid]); + + return $this->factory->createFromTableRow($fields); } /** * Returns the existing local relationship between a user and a public contact or a default * relationship if it doesn't. * - * @param int $uid - * @param int $cid - * @return Entity\LocalRelationship - * @throws HTTPException\NotFoundException + * @throws NotFoundException */ - public function getForUserContact(int $uid, int $cid): Entity\LocalRelationship + public function getForUserContact(int $uid, int $cid): LocalRelationshipEntity { try { return $this->selectForUserContact($uid, $cid); - } catch (HTTPException\NotFoundException $e) { + } catch (NotFoundException $e) { return $this->factory->createFromTableRow(['uid' => $uid, 'cid' => $cid]); } } /** - * @param int $uid - * @param int $cid - * @return bool - * @throws \Exception + * @throws Exception */ public function existsForUserContact(int $uid, int $cid): bool { @@ -68,12 +63,8 @@ class LocalRelationship extends \Friendica\BaseRepository /** * Converts a given local relationship into a DB compatible row array - * - * @param Entity\LocalRelationship $localRelationship - * - * @return array */ - protected function convertToTableRow(Entity\LocalRelationship $localRelationship): array + protected function convertToTableRow(LocalRelationshipEntity $localRelationship): array { return [ 'uid' => $localRelationship->userId, @@ -97,13 +88,9 @@ class LocalRelationship extends \Friendica\BaseRepository } /** - * @param Entity\LocalRelationship $localRelationship - * - * @return Entity\LocalRelationship - * - * @throws Exception\LocalRelationshipPersistenceException In case the underlying storage cannot save the LocalRelationship + * @throws LocalRelationshipPersistenceException In case the underlying storage cannot save the LocalRelationship */ - public function save(Entity\LocalRelationship $localRelationship): Entity\LocalRelationship + public function save(LocalRelationshipEntity $localRelationship): LocalRelationshipEntity { try { $fields = $this->convertToTableRow($localRelationship); @@ -111,8 +98,8 @@ class LocalRelationship extends \Friendica\BaseRepository $this->db->insert(self::$table_name, $fields, Database::INSERT_UPDATE); return $localRelationship; - } catch (\Exception $exception) { - throw new Exception\LocalRelationshipPersistenceException(sprintf('Cannot insert/update the local relationship %d for user %d', $localRelationship->contactId, $localRelationship->userId), $exception); + } catch (Exception $exception) { + throw new LocalRelationshipPersistenceException(sprintf('Cannot insert/update the local relationship %d for user %d', $localRelationship->contactId, $localRelationship->userId), $exception); } } } diff --git a/src/Content/Conversation/Repository/UserDefinedChannel.php b/src/Content/Conversation/Repository/UserDefinedChannel.php index 229ef8e40c..65b29d0c94 100644 --- a/src/Content/Conversation/Repository/UserDefinedChannel.php +++ b/src/Content/Conversation/Repository/UserDefinedChannel.php @@ -7,10 +7,10 @@ namespace Friendica\Content\Conversation\Repository; -use Friendica\BaseCollection; +use Friendica\BaseRepository; use Friendica\Content\Conversation\Collection\UserDefinedChannels; -use Friendica\Content\Conversation\Entity; -use Friendica\Content\Conversation\Factory; +use Friendica\Content\Conversation\Entity\UserDefinedChannel as UserDefinedChannelEntity; +use Friendica\Content\Conversation\Factory\UserDefinedChannel as UserDefinedChannelFactory; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Database\Database; use Friendica\Database\DBA; @@ -21,13 +21,16 @@ use Friendica\Model\User; use Friendica\Util\DateTimeFormat; use Psr\Log\LoggerInterface; -class UserDefinedChannel extends \Friendica\BaseRepository +class UserDefinedChannel extends BaseRepository { protected static $table_name = 'channel'; + /** @var UserDefinedChannelFactory */ + protected $factory; + private IManageConfigValues $config; - public function __construct(Database $database, LoggerInterface $logger, Factory\UserDefinedChannel $factory, IManageConfigValues $config) + public function __construct(Database $database, LoggerInterface $logger, UserDefinedChannelFactory $factory, IManageConfigValues $config) { parent::__construct($database, $logger, $factory); @@ -40,7 +43,7 @@ class UserDefinedChannel extends \Friendica\BaseRepository * @return UserDefinedChannels * @throws \Exception */ - protected function _select(array $condition, array $params = []): BaseCollection + protected function _select(array $condition, array $params = []): UserDefinedChannels { $rows = $this->db->selectToArray(static::$table_name, [], $condition, $params); @@ -62,12 +65,13 @@ class UserDefinedChannel extends \Friendica\BaseRepository * * @param int $id The id of the user defined channel * @param int $uid The user that this channel belongs to. (Not part of the primary key) - * @return Entity\UserDefinedChannel * @throws \Friendica\Network\HTTPException\NotFoundException */ - public function selectById(int $id, int $uid): Entity\UserDefinedChannel + public function selectById(int $id, int $uid): UserDefinedChannelEntity { - return $this->_selectOne(['id' => $id, 'uid' => $uid]); + $fields = $this->_selectFirstRowAsArray( ['id' => $id, 'uid' => $uid]); + + return $this->factory->createFromTableRow($fields); } /** @@ -106,7 +110,7 @@ class UserDefinedChannel extends \Friendica\BaseRepository return $this->_select(['uid' => $uid]); } - public function save(Entity\UserDefinedChannel $Channel): Entity\UserDefinedChannel + public function save(UserDefinedChannelEntity $Channel): UserDefinedChannelEntity { $fields = [ 'label' => $Channel->label, @@ -210,7 +214,7 @@ class UserDefinedChannel extends \Friendica\BaseRepository $disposableFullTextSearch = new DisposableFullTextSearch($this->db, $searchtext); $filteredChannels = $this->select(['uid' => array_column($users, 'uid'), 'publish' => true, 'valid' => true])->filter( - function (Entity\UserDefinedChannel $channel) use ($owner_id, $reshare_id, $language, $tags, $media_type, $disposableFullTextSearch, $searchtext) { + function (UserDefinedChannelEntity $channel) use ($owner_id, $reshare_id, $language, $tags, $media_type, $disposableFullTextSearch, $searchtext) { static $uids = []; // Filter out channels from already picked users diff --git a/src/Content/Post/Entity/PostMedia.php b/src/Content/Post/Entity/PostMedia.php index 4b4268b750..59d1ec9c57 100644 --- a/src/Content/Post/Entity/PostMedia.php +++ b/src/Content/Post/Entity/PostMedia.php @@ -13,7 +13,6 @@ use Friendica\Util\Images; use Friendica\Util\Proxy; use Psr\Http\Message\UriInterface; - /** * @property-read int $id * @property-read int $uriId @@ -210,7 +209,7 @@ class PostMedia extends BaseEntity * * @param \GuzzleHttp\Psr7\Uri $preview * @param string $size - * @return $this + * @return self */ public function withPreview(\GuzzleHttp\Psr7\Uri $preview, string $size = ''): self { diff --git a/src/Content/Post/Factory/PostMedia.php b/src/Content/Post/Factory/PostMedia.php index 0dbfeb4896..1ebedda72e 100644 --- a/src/Content/Post/Factory/PostMedia.php +++ b/src/Content/Post/Factory/PostMedia.php @@ -9,8 +9,9 @@ namespace Friendica\Content\Post\Factory; use Friendica\BaseFactory; use Friendica\Capabilities\ICanCreateFromTableRow; -use Friendica\Content\Post\Entity; -use Friendica\Network; +use Friendica\Content\Post\Entity\PostMedia as PostMediaEntity; +use Friendica\Network\Entity\MimeType as MimeTypeEntity; +use Friendica\Network\Factory\MimeType as MimeTypeFactory; use Friendica\Util\Network as UtilNetwork; use GuzzleHttp\Psr7\Uri; use Psr\Log\LoggerInterface; @@ -18,10 +19,10 @@ use stdClass; class PostMedia extends BaseFactory implements ICanCreateFromTableRow { - /** @var Network\Factory\MimeType */ + /** @var MimeTypeFactory */ private $mimeTypeFactory; - public function __construct(Network\Factory\MimeType $mimeTypeFactory, LoggerInterface $logger) + public function __construct(MimeTypeFactory $mimeTypeFactory, LoggerInterface $logger) { parent::__construct($logger); @@ -31,9 +32,9 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow /** * @inheritDoc */ - public function createFromTableRow(array $row) + public function createFromTableRow(array $row): PostMediaEntity { - return new Entity\PostMedia( + return new PostMediaEntity( $row['uri-id'], UtilNetwork::createUriFromString($row['url']), $row['type'], @@ -58,13 +59,13 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow ); } - public function createFromBlueskyImageEmbed(int $uriId, stdClass $image): Entity\PostMedia + public function createFromBlueskyImageEmbed(int $uriId, stdClass $image): PostMediaEntity { - return new Entity\PostMedia( + return new PostMediaEntity( $uriId, new Uri($image->fullsize), - Entity\PostMedia::TYPE_IMAGE, - new Network\Entity\MimeType('unkn', 'unkn'), + PostMediaEntity::TYPE_IMAGE, + new MimeTypeEntity('unkn', 'unkn'), null, null, null, @@ -77,13 +78,13 @@ class PostMedia extends BaseFactory implements ICanCreateFromTableRow } - public function createFromBlueskyExternalEmbed(int $uriId, stdClass $external): Entity\PostMedia + public function createFromBlueskyExternalEmbed(int $uriId, stdClass $external): PostMediaEntity { - return new Entity\PostMedia( + return new PostMediaEntity( $uriId, new Uri($external->uri), - Entity\PostMedia::TYPE_HTML, - new Network\Entity\MimeType('text', 'html'), + PostMediaEntity::TYPE_HTML, + new MimeTypeEntity('text', 'html'), null, null, null, diff --git a/src/Content/Post/Repository/PostMedia.php b/src/Content/Post/Repository/PostMedia.php index 778591c1ab..f02d93c665 100644 --- a/src/Content/Post/Repository/PostMedia.php +++ b/src/Content/Post/Repository/PostMedia.php @@ -7,11 +7,10 @@ namespace Friendica\Content\Post\Repository; -use Friendica\BaseCollection; use Friendica\BaseRepository; -use Friendica\Content\Post\Collection; -use Friendica\Content\Post\Entity; -use Friendica\Content\Post\Factory; +use Friendica\Content\Post\Collection\PostMedias as PostMediasCollection; +use Friendica\Content\Post\Entity\PostMedia as PostMediaEntity; +use Friendica\Content\Post\Factory\PostMedia as PostMediaFactory; use Friendica\Database\Database; use Friendica\Model\Post; use Friendica\Util\Strings; @@ -21,16 +20,19 @@ class PostMedia extends BaseRepository { protected static $table_name = 'post-media'; - public function __construct(Database $database, LoggerInterface $logger, Factory\PostMedia $factory) + /** @var PostMediaFactory */ + protected $factory; + + public function __construct(Database $database, LoggerInterface $logger, PostMediaFactory $factory) { parent::__construct($database, $logger, $factory); } - protected function _select(array $condition, array $params = []): BaseCollection + protected function _select(array $condition, array $params = []): PostMediasCollection { $rows = $this->db->selectToArray(static::$table_name, [], $condition, $params); - $Entities = new Collection\PostMedias(); + $Entities = new PostMediasCollection(); foreach ($rows as $fields) { try { $Entities[] = $this->factory->createFromTableRow($fields); @@ -42,17 +44,19 @@ class PostMedia extends BaseRepository return $Entities; } - public function selectOneById(int $postMediaId): Entity\PostMedia + public function selectOneById(int $postMediaId): PostMediaEntity { - return $this->_selectOne(['id' => $postMediaId]); + $fields = $this->_selectFirstRowAsArray( ['id' => $postMediaId]); + + return $this->factory->createFromTableRow($fields); } - public function selectByUriId(int $uriId): Collection\PostMedias + public function selectByUriId(int $uriId): PostMediasCollection { return $this->_select(["`uri-id` = ? AND `type` != ?", $uriId, Post\Media::UNKNOWN]); } - public function save(Entity\PostMedia $PostMedia): Entity\PostMedia + public function save(PostMediaEntity $PostMedia): PostMediaEntity { $fields = [ 'uri-id' => $PostMedia->uriId, @@ -97,14 +101,14 @@ class PostMedia extends BaseRepository * @param int $uri_id URI id * @param array $links list of links that shouldn't be added * @param bool $has_media - * @return Collection\PostMedias[] Three collections in "visual", "link" and "additional" keys + * @return PostMediasCollection[] Three collections in "visual", "link" and "additional" keys */ public function splitAttachments(int $uri_id, array $links = [], bool $has_media = true): array { $attachments = [ - 'visual' => new Collection\PostMedias(), - 'link' => new Collection\PostMedias(), - 'additional' => new Collection\PostMedias(), + 'visual' => new PostMediasCollection(), + 'link' => new PostMediasCollection(), + 'additional' => new PostMediasCollection(), ]; if (!$has_media) { @@ -137,7 +141,7 @@ class PostMedia extends BaseRepository // Currently these two types are ignored here. // Posts are added differently and contacts are not displayed as attachments. - if (in_array($PostMedia->type, [Entity\PostMedia::TYPE_ACCOUNT, Entity\PostMedia::TYPE_ACTIVITY])) { + if (in_array($PostMedia->type, [PostMediaEntity::TYPE_ACCOUNT, PostMediaEntity::TYPE_ACTIVITY])) { continue; } @@ -148,17 +152,17 @@ class PostMedia extends BaseRepository //$PostMedia->filetype = $filetype; //$PostMedia->subtype = $subtype; - if ($PostMedia->type == Entity\PostMedia::TYPE_HTML || ($PostMedia->mimetype->type == 'text' && $PostMedia->mimetype->subtype == 'html')) { + if ($PostMedia->type == PostMediaEntity::TYPE_HTML || ($PostMedia->mimetype->type == 'text' && $PostMedia->mimetype->subtype == 'html')) { $attachments['link'][] = $PostMedia; continue; } if ( - in_array($PostMedia->type, [Entity\PostMedia::TYPE_AUDIO, Entity\PostMedia::TYPE_IMAGE, Entity\PostMedia::TYPE_HLS]) || + in_array($PostMedia->type, [PostMediaEntity::TYPE_AUDIO, PostMediaEntity::TYPE_IMAGE, PostMediaEntity::TYPE_HLS]) || in_array($PostMedia->mimetype->type, ['audio', 'image']) ) { $attachments['visual'][] = $PostMedia; - } elseif (($PostMedia->type == Entity\PostMedia::TYPE_VIDEO) || ($PostMedia->mimetype->type == 'video')) { + } elseif (($PostMedia->type == PostMediaEntity::TYPE_VIDEO) || ($PostMedia->mimetype->type == 'video')) { if (!empty($PostMedia->height)) { // Peertube videos are delivered in many different resolutions. We pick a moderate one. // Since only Peertube provides a "height" parameter, this wouldn't be executed diff --git a/src/Core/Worker/Repository/Process.php b/src/Core/Worker/Repository/Process.php index 146854234e..ee4d46a9f4 100644 --- a/src/Core/Worker/Repository/Process.php +++ b/src/Core/Worker/Repository/Process.php @@ -8,11 +8,11 @@ namespace Friendica\Core\Worker\Repository; use Friendica\BaseRepository; +use Friendica\Core\Worker\Entity\Process as ProcessEntity; use Friendica\Core\Worker\Exception\ProcessPersistenceException; +use Friendica\Core\Worker\Factory\Process as ProcessFactory; use Friendica\Database\Database; use Friendica\Util\DateTimeFormat; -use Friendica\Core\Worker\Factory; -use Friendica\Core\Worker\Entity; use Psr\Log\LoggerInterface; /** @@ -24,13 +24,13 @@ class Process extends BaseRepository protected static $table_name = 'process'; - /** @var Factory\Process */ + /** @var ProcessFactory */ protected $factory; /** @var string */ private $currentHost; - public function __construct(Database $database, LoggerInterface $logger, Factory\Process $factory, array $server) + public function __construct(Database $database, LoggerInterface $logger, ProcessFactory $factory, array $server) { parent::__construct($database, $logger, $factory); @@ -39,13 +39,8 @@ class Process extends BaseRepository /** * Starts and Returns the process for a given PID at the current host - * - * @param int $pid - * @param string $command - * - * @return Entity\Process */ - public function create(int $pid, string $command): Entity\Process + public function create(int $pid, string $command): ProcessEntity { // Cleanup inactive process $this->deleteInactive(); @@ -64,7 +59,9 @@ class Process extends BaseRepository } } - $result = $this->_selectOne(['pid' => $pid, 'hostname' => $this->currentHost]); + $fields = $this->_selectFirstRowAsArray( ['pid' => $pid, 'hostname' => $this->currentHost]); + + $result = $this->factory->createFromTableRow($fields); $this->db->commit(); @@ -74,7 +71,7 @@ class Process extends BaseRepository } } - public function delete(Entity\Process $process) + public function delete(ProcessEntity $process) { try { if (!$this->db->delete(static::$table_name, [ From e1eb6fff839fcfbb2f6cf74d5e2dc22cec7d1af4 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 09:18:53 +0000 Subject: [PATCH 31/91] Deprecate BaseRepository::_selectOne() set BaseRepository::_selectFirstRowAsArray() as final --- src/BaseRepository.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/BaseRepository.php b/src/BaseRepository.php index ead4bf73bf..bf495a6a5d 100644 --- a/src/BaseRepository.php +++ b/src/BaseRepository.php @@ -136,7 +136,7 @@ abstract class BaseRepository * * @return array The resulted fields as array */ - protected function _selectFirstRowAsArray(array $condition, array $params = []): array + final protected function _selectFirstRowAsArray(array $condition, array $params = []): array { $fields = $this->db->selectFirst(static::$table_name, [], $condition, $params); @@ -154,6 +154,8 @@ abstract class BaseRepository */ protected function _selectOne(array $condition, array $params = []): BaseEntity { + @trigger_error('`' . __METHOD__ . '()` is deprecated since 2025.05 and will be removed after 5 months, use `\Friendica\BaseRepository::_selectFirstRowAsArray()` instead.', E_USER_DEPRECATED); + $fields = $this->_selectFirstRowAsArray( $condition, $params); return $this->factory->createFromTableRow($fields); From 7e66b35b4626fa84f12dfd4a63dd416d37b9177e Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 11:39:02 +0000 Subject: [PATCH 32/91] Fix 10 PHPStan errors --- src/Core/Storage/Type/Database.php | 2 +- src/Core/System.php | 8 +++----- src/Core/Update.php | 4 ++-- src/Core/Worker.php | 7 ++++--- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Core/Storage/Type/Database.php b/src/Core/Storage/Type/Database.php index 39b84528e5..6ed8527533 100644 --- a/src/Core/Storage/Type/Database.php +++ b/src/Core/Storage/Type/Database.php @@ -80,7 +80,7 @@ class Database implements ICanWriteToStorage throw new StorageException(sprintf('Database storage failed to update %s', $reference), 500, new Exception($this->dba->errorMessage(), $this->dba->errorNo())); } - return $this->dba->lastInsertId(); + return (string) $this->dba->lastInsertId(); } } diff --git a/src/Core/System.php b/src/Core/System.php index df494bec5d..d7367e871c 100644 --- a/src/Core/System.php +++ b/src/Core/System.php @@ -452,19 +452,17 @@ class System /** * Returns the current Load of the System - * - * @return integer */ - public static function currentLoad() + public static function currentLoad(): float { if (!function_exists('sys_getloadavg')) { - return false; + return (float) 0; } $load_arr = sys_getloadavg(); if (!is_array($load_arr)) { - return false; + return (float) 0; } return round(max($load_arr[0], $load_arr[1]), 2); diff --git a/src/Core/Update.php b/src/Core/Update.php index 7aeefc3793..dc68f280cc 100644 --- a/src/Core/Update.php +++ b/src/Core/Update.php @@ -217,7 +217,7 @@ class Update ->set('system', 'maintenance', false) ->delete('system', 'maintenance_reason') ->commit(); - return $r; + return 'Pre update failed'; } else { DI::logger()->notice('Pre update executed.', ['version' => $version]); } @@ -262,7 +262,7 @@ class Update ->set('system', 'maintenance', false) ->delete('system', 'maintenance_reason') ->commit(); - return $r; + return 'Post update failed'; } else { DI::config()->set('system', 'build', $version); DI::logger()->notice('Post update executed.', ['version' => $version]); diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 995239cde9..75a457f38e 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -271,12 +271,13 @@ class Worker * * @param integer $priority The priority that should be checked * - * @return integer Is there a process running with that priority? + * @return bool Is there a process running with that priority? * @throws \Exception */ - private static function processWithPriorityActive(int $priority): int + private static function processWithPriorityActive(int $priority): bool { $condition = ["`priority` <= ? AND `pid` != 0 AND NOT `done`", $priority]; + return DBA::exists('workerqueue', $condition); } @@ -955,7 +956,7 @@ class Worker /** * Returns the priority of the next workerqueue job * - * @return string|bool priority or FALSE on failure + * @return int|false priority or FALSE on failure * @throws \Exception */ private static function nextPriority() From 441846cfbdce0b368486f7d782c8ececb52b14c6 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 11:50:15 +0000 Subject: [PATCH 33/91] Fix return type or UserSession::getUserIDForVisitorContactID() --- src/Core/Session/Model/UserSession.php | 4 ++-- src/Object/Post.php | 2 +- tests/src/Core/Session/UserSessionTest.php | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Core/Session/Model/UserSession.php b/src/Core/Session/Model/UserSession.php index cc3db7f806..70370371ff 100644 --- a/src/Core/Session/Model/UserSession.php +++ b/src/Core/Session/Model/UserSession.php @@ -101,7 +101,7 @@ class UserSession implements IHandleUserSessions public function getUserIDForVisitorContactID(int $cid): int { if (empty($this->session->get('remote'))) { - return false; + return 0; } return array_search($cid, $this->session->get('remote')); @@ -142,7 +142,7 @@ class UserSession implements IHandleUserSessions { return !$this->session->get('authenticated', false); } - + /** {@inheritDoc} */ public function setVisitorsContacts(string $my_url) { diff --git a/src/Object/Post.php b/src/Object/Post.php index 4dd5cdea30..7c19a99842 100644 --- a/src/Object/Post.php +++ b/src/Object/Post.php @@ -71,7 +71,7 @@ class Post $this->setTemplate('wall'); $this->toplevel = $this->getId() == $this->getDataValue('parent'); - if (!empty(DI::userSession()->getUserIDForVisitorContactID($this->getDataValue('contact-id')))) { + if (DI::userSession()->getUserIDForVisitorContactID($this->getDataValue('contact-id')) !== 0) { $this->visiting = true; } diff --git a/tests/src/Core/Session/UserSessionTest.php b/tests/src/Core/Session/UserSessionTest.php index 64c7d8b950..cecae1d90c 100644 --- a/tests/src/Core/Session/UserSessionTest.php +++ b/tests/src/Core/Session/UserSessionTest.php @@ -152,13 +152,13 @@ class UserSessionTest extends MockedTestCase 'data' => [ 'remote' => ['3' => '21'], ], - 'expected' => false, + 'expected' => 0, ], 'empty' => [ 'cid' => 21, 'data' => [ ], - 'expected' => false, + 'expected' => 0, ], ]; } @@ -167,7 +167,7 @@ class UserSessionTest extends MockedTestCase public function testGetUserIdForVisitorContactID(int $cid, array $data, $expected) { $userSession = new UserSession(new ArraySession($data)); - $this->assertEquals($expected, $userSession->getUserIDForVisitorContactID($cid)); + $this->assertSame($expected, $userSession->getUserIDForVisitorContactID($cid)); } public function dataAuthenticated() From a63babc658fe7a609474fb9328419c3a2e380f76 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 12:20:43 +0000 Subject: [PATCH 34/91] Fix 6 PHPStan errors --- src/Core/Logger/Type/StreamLogger.php | 8 ++---- src/Core/Logger/Type/SyslogLogger.php | 28 ++++++++----------- src/Core/PConfig/Repository/PConfig.php | 2 +- .../Logger/SyslogLoggerFactoryWrapper.php | 10 +++---- tests/src/Core/Logger/SyslogLoggerWrapper.php | 2 +- 5 files changed, 21 insertions(+), 29 deletions(-) diff --git a/src/Core/Logger/Type/StreamLogger.php b/src/Core/Logger/Type/StreamLogger.php index 81af7e4474..03dfe69b6d 100644 --- a/src/Core/Logger/Type/StreamLogger.php +++ b/src/Core/Logger/Type/StreamLogger.php @@ -22,21 +22,19 @@ class StreamLogger extends AbstractLogger /** * The minimum loglevel at which this logger will be triggered - * @var string */ - private $logLevel; + private int $logLevel; /** * The stream, where the current logger is writing into - * @var resource + * @var resource|null */ private $stream; /** * The current process ID - * @var int */ - private $pid; + private int $pid; /** * Translates LogLevel log levels to integer values diff --git a/src/Core/Logger/Type/SyslogLogger.php b/src/Core/Logger/Type/SyslogLogger.php index 8f24af053c..8b5f34634f 100644 --- a/src/Core/Logger/Type/SyslogLogger.php +++ b/src/Core/Logger/Type/SyslogLogger.php @@ -29,7 +29,7 @@ class SyslogLogger extends AbstractLogger /** * Translates LogLevel log levels to syslog log priorities. - * @var array + * @var array */ public const logLevels = [ LogLevel::DEBUG => LOG_DEBUG, @@ -60,39 +60,33 @@ class SyslogLogger extends AbstractLogger /** * Indicates what logging options will be used when generating a log message * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters - * - * @var int */ - private $logOpts; + private int $logOpts; /** * Used to specify what type of program is logging the message * @see http://php.net/manual/en/function.openlog.php#refsect1-function.openlog-parameters - * - * @var int */ - private $logFacility; + private int $logFacility; /** * The minimum loglevel at which this logger will be triggered - * @var int */ - private $logLevel; + private int $logLevel; /** * A error message of the current operation - * @var string */ - private $errorMessage; + private string $errorMessage; /** * {@inheritdoc} * - * @param string $logLevel The minimum loglevel at which this logger will be triggered - * @param string $logOptions - * @param string $logFacility + * @param int $logLevel The minimum loglevel at which this logger will be triggered + * @param int $logOptions + * @param int $logFacility */ - public function __construct(string $channel, IHaveCallIntrospections $introspection, string $logLevel, string $logOptions, string $logFacility) + public function __construct(string $channel, IHaveCallIntrospections $introspection, int $logLevel, int $logOptions, int $logFacility) { parent::__construct($channel, $introspection); @@ -166,7 +160,7 @@ class SyslogLogger extends AbstractLogger restore_error_handler(); if (!$opened) { - throw new LoggerException(sprintf('Can\'t open syslog for ident "%s" and facility "%s": ' . $this->errorMessage, $this->channel, $this->logFacility)); + throw new LoggerException(sprintf('Can\'t open syslog for ident "%s" and facility "%s": ' . $this->errorMessage, $this->channel, (string) $this->logFacility)); } $this->syslogWrapper($priority, $message); @@ -215,7 +209,7 @@ class SyslogLogger extends AbstractLogger restore_error_handler(); if (!$written) { - throw new LoggerException(sprintf('Can\'t write into syslog for ident "%s" and facility "%s": ' . $this->errorMessage, $this->channel, $this->logFacility)); + throw new LoggerException(sprintf('Can\'t write into syslog for ident "%s" and facility "%s": ' . $this->errorMessage, $this->channel, (string) $this->logFacility)); } } } diff --git a/src/Core/PConfig/Repository/PConfig.php b/src/Core/PConfig/Repository/PConfig.php index d3b68b8ce1..af59e23fc3 100644 --- a/src/Core/PConfig/Repository/PConfig.php +++ b/src/Core/PConfig/Repository/PConfig.php @@ -37,7 +37,7 @@ class PConfig */ public function isConnected(): bool { - return $this->db->isConnected() & !$this->mode->isInstall(); + return $this->db->isConnected() && !$this->mode->isInstall(); } /** diff --git a/tests/src/Core/Logger/SyslogLoggerFactoryWrapper.php b/tests/src/Core/Logger/SyslogLoggerFactoryWrapper.php index 10b19d1991..6bc30bc439 100644 --- a/tests/src/Core/Logger/SyslogLoggerFactoryWrapper.php +++ b/tests/src/Core/Logger/SyslogLoggerFactoryWrapper.php @@ -17,16 +17,16 @@ class SyslogLoggerFactoryWrapper extends SyslogLogger { public function create(IManageConfigValues $config): LoggerInterface { - $logOpts = $config->get('system', 'syslog_flags') ?? SyslogLoggerClass::DEFAULT_FLAGS; - $logFacility = $config->get('system', 'syslog_facility') ?? SyslogLoggerClass::DEFAULT_FACILITY; + $logOpts = (int) $config->get('system', 'syslog_flags') ?? SyslogLoggerClass::DEFAULT_FLAGS; + $logFacility = (int) $config->get('system', 'syslog_facility') ?? SyslogLoggerClass::DEFAULT_FACILITY; $loglevel = SyslogLogger::mapLegacyConfigDebugLevel($config->get('system', 'loglevel')); - if (array_key_exists($loglevel, SyslogLoggerClass::logLevels)) { - $loglevel = SyslogLoggerClass::logLevels[$loglevel]; - } else { + if (!array_key_exists($loglevel, SyslogLoggerClass::logLevels)) { throw new LogLevelException(sprintf('The level "%s" is not valid.', $loglevel)); } + $loglevel = SyslogLoggerClass::logLevels[$loglevel]; + return new SyslogLoggerWrapper($this->channel, $this->introspection, $loglevel, $logOpts, $logFacility); } } diff --git a/tests/src/Core/Logger/SyslogLoggerWrapper.php b/tests/src/Core/Logger/SyslogLoggerWrapper.php index e0e360a50f..df2944c4c5 100644 --- a/tests/src/Core/Logger/SyslogLoggerWrapper.php +++ b/tests/src/Core/Logger/SyslogLoggerWrapper.php @@ -17,7 +17,7 @@ class SyslogLoggerWrapper extends SyslogLogger { private $content; - public function __construct(string $channel, IHaveCallIntrospections $introspection, string $logLevel, string $logOptions, string $logFacility) + public function __construct(string $channel, IHaveCallIntrospections $introspection, int $logLevel, int $logOptions, int $logFacility) { parent::__construct($channel, $introspection, $logLevel, $logOptions, $logFacility); From 2dfd7c83cf27cd80fef6c00384f075e4e2f90b56 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 12:26:16 +0000 Subject: [PATCH 35/91] ignore PHPStan error in deprecated code --- src/Core/Config/Util/ConfigFileManager.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Core/Config/Util/ConfigFileManager.php b/src/Core/Config/Util/ConfigFileManager.php index d76e3e53cd..96c416e4de 100644 --- a/src/Core/Config/Util/ConfigFileManager.php +++ b/src/Core/Config/Util/ConfigFileManager.php @@ -257,6 +257,7 @@ class ConfigFileManager // map the legacy configuration structure to the current structure foreach ($htConfigCategories as $htConfigCategory) { + /** @phpstan-ignore-next-line $a->config could be modified after `include $fullName` */ if (is_array($a->config[$htConfigCategory])) { $keys = array_keys($a->config[$htConfigCategory]); From bb6a4a3acd1125ba52a0d38a2d96925b61b1a159 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 12:37:30 +0000 Subject: [PATCH 36/91] fix 14 PHPStan errors in console --- src/Console/Contact.php | 14 ++++++++------ src/Console/User.php | 20 ++++++++++---------- src/Content/PageInfo.php | 1 + 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/Console/Contact.php b/src/Console/Contact.php index 8173054826..d54979c11b 100644 --- a/src/Console/Contact.php +++ b/src/Console/Contact.php @@ -56,7 +56,7 @@ HELP; return $help; } - public function __construct(Mode $appMode, array $argv = null) + public function __construct(Mode $appMode, ?array $argv = null) { parent::__construct($argv); @@ -84,13 +84,13 @@ HELP; switch ($command) { case 'add': - return $this->addContact(); + return ($this->addContact()) ? 0 : 1; case 'remove': - return $this->removeContact(); + return ($this->removeContact()) ? 0 : 1; case 'search': - return $this->searchContact(); + return ($this->searchContact()) ? 0 : 1; case 'terminate': - return $this->terminateContact(); + return ($this->terminateContact()) ? 0 : 1; default: throw new \Asika\SimpleConsole\CommandArgsException('Wrong command.'); } @@ -206,7 +206,7 @@ HELP; /** * Marks a contact for removal */ - private function removeContact() + private function removeContact(): bool { $cid = $this->getArgument(1); if (empty($cid)) { @@ -218,6 +218,8 @@ HELP; } ContactModel::remove($cid); + + return true; } /** diff --git a/src/Console/User.php b/src/Console/User.php index 89c217694d..5a8f62cc8c 100644 --- a/src/Console/User.php +++ b/src/Console/User.php @@ -106,21 +106,21 @@ HELP; case 'password': return $this->password(); case 'add': - return $this->addUser(); + return ($this->addUser()) ? 0 : 1; case 'allow': - return $this->pendingUser(true); + return ($this->pendingUser(true)) ? 0 : 1; case 'deny': - return $this->pendingUser(false); + return ($this->pendingUser(false)) ? 0 : 1; case 'block': - return $this->blockUser(true); + return ($this->blockUser(true)) ? 0 : 1; case 'unblock': - return $this->blockUser(false); + return ($this->blockUser(false)) ? 0 : 1; case 'delete': - return $this->deleteUser(); + return ($this->deleteUser()) ? 0 : 1; case 'list': - return $this->listUser(); + return ($this->listUser()) ? 0 : 1; case 'search': - return $this->searchUser(); + return ($this->searchUser()) ? 0 : 1; case 'config': return ($this->configUser()) ? 0 : 1; default: @@ -178,7 +178,7 @@ HELP; * * @throws \Exception */ - private function password() + private function password(): int { $user = $this->getUserByNick(1); @@ -212,7 +212,7 @@ HELP; * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException */ - private function addUser() + private function addUser(): bool { $name = $this->getArgument(1); $nick = $this->getArgument(2); diff --git a/src/Content/PageInfo.php b/src/Content/PageInfo.php index 4d2a1180d3..a53c36b68c 100644 --- a/src/Content/PageInfo.php +++ b/src/Content/PageInfo.php @@ -92,6 +92,7 @@ class PageInfo { $eventDispatcher = DI::eventDispatcher(); + /** @var array */ $data = $eventDispatcher->dispatch( new ArrayFilterEvent(ArrayFilterEvent::PAGE_INFO, $data), )->getArray(); From b999472ddb6e2196f482c34d9c4e209620832bbc Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 12:49:09 +0000 Subject: [PATCH 37/91] Fix possible false return type in PHP 7.4 --- src/Console/PoToPhp.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Console/PoToPhp.php b/src/Console/PoToPhp.php index ec5c050e70..a99cd6e806 100644 --- a/src/Console/PoToPhp.php +++ b/src/Console/PoToPhp.php @@ -175,11 +175,11 @@ HELP; * @param string $string * @param array|string $node */ - private static function parse(string $string, &$node = []) + private static function parse(string $string, &$node) { // Removes extra outward parentheses if (strpos($string, '(') === 0 && strrpos($string, ')') === strlen($string) - 1) { - $string = substr($string, 1, -1); + $string = (string) substr($string, 1, -1); } $q = strpos($string, '?'); From 0427812269b0c671b9f89a93a69bec43ecf3777f Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 12:54:00 +0000 Subject: [PATCH 38/91] Run phpstan in addons with level 3 --- .phpstan-addons.neon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.phpstan-addons.neon b/.phpstan-addons.neon index 801db2ab6a..c4864d468d 100644 --- a/.phpstan-addons.neon +++ b/.phpstan-addons.neon @@ -3,7 +3,7 @@ # SPDX-License-Identifier: CC0-1.0 parameters: - level: 2 + level: 3 paths: - addon/ From 4d96875656445ca5204e98b3240c4fadcae90066 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 13:42:54 +0000 Subject: [PATCH 39/91] Add event for unfollow hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Core/Protocol.php | 7 ++++++- src/Event/ArrayFilterEvent.php | 2 ++ tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 2f1e51a297..6b652cf4f0 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -62,6 +62,7 @@ final class HookEventBridge ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW => 'support_follow', ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW => 'support_revoke_follow', ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE => 'support_probe', + ArrayFilterEvent::UNFOLLOW => 'unfollow', HtmlFilterEvent::HEAD => 'head', HtmlFilterEvent::FOOTER => 'footer', HtmlFilterEvent::PAGE_HEADER => 'page_header', @@ -104,6 +105,7 @@ final class HookEventBridge ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW => 'onArrayFilterEvent', ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW => 'onArrayFilterEvent', ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE => 'onArrayFilterEvent', + ArrayFilterEvent::UNFOLLOW => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', diff --git a/src/Core/Protocol.php b/src/Core/Protocol.php index 1e5b7e7f21..61427d1017 100644 --- a/src/Core/Protocol.php +++ b/src/Core/Protocol.php @@ -183,7 +183,12 @@ class Protocol 'uid' => $owner['uid'], 'result' => null, ]; - Hook::callAll('unfollow', $hook_data); + + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW, $hook_data), + )->getArray(); return $hook_data['result']; } diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index d21c6f8d78..9664071714 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -62,6 +62,8 @@ final class ArrayFilterEvent extends Event public const PROTOCOL_SUPPORTS_PROBE = 'friendica.data.protocol_supports_probe'; + public const UNFOLLOW = 'friendica.data.unfollow'; + private array $array; public function __construct(string $name, array $array) diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index cdd3e0d61b..93d62965c3 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -51,6 +51,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW => 'onArrayFilterEvent', ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW => 'onArrayFilterEvent', ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE => 'onArrayFilterEvent', + ArrayFilterEvent::UNFOLLOW => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', @@ -278,6 +279,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW, 'support_follow'], [ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW, 'support_revoke_follow'], [ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE, 'support_probe'], + [ArrayFilterEvent::UNFOLLOW, 'unfollow'], ]; } From 10e4f4bf36cb601af0c419f0c864fd672dbb8999 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 14:02:35 +0000 Subject: [PATCH 40/91] Add events for follow, revoke_follow, block and unblock hooks --- src/Core/Hooks/HookEventBridge.php | 12 ++++++++-- src/Core/Protocol.php | 23 +++++++++++++++---- src/Event/ArrayFilterEvent.php | 10 +++++++- src/Model/Contact.php | 7 +++++- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 12 ++++++++-- tests/Unit/Event/ArrayFilterEventTest.php | 5 ++++ 6 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 6b652cf4f0..39da9a13d0 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -62,7 +62,11 @@ final class HookEventBridge ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW => 'support_follow', ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW => 'support_revoke_follow', ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE => 'support_probe', - ArrayFilterEvent::UNFOLLOW => 'unfollow', + ArrayFilterEvent::FOLLOW_CONTACT => 'follow', + ArrayFilterEvent::UNFOLLOW_CONTACT => 'unfollow', + ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'revoke_follow', + ArrayFilterEvent::BLOCK_CONTACT => 'block', + ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', HtmlFilterEvent::HEAD => 'head', HtmlFilterEvent::FOOTER => 'footer', HtmlFilterEvent::PAGE_HEADER => 'page_header', @@ -105,7 +109,11 @@ final class HookEventBridge ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW => 'onArrayFilterEvent', ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW => 'onArrayFilterEvent', ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE => 'onArrayFilterEvent', - ArrayFilterEvent::UNFOLLOW => 'onArrayFilterEvent', + ArrayFilterEvent::FOLLOW_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::UNFOLLOW_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', diff --git a/src/Core/Protocol.php b/src/Core/Protocol.php index 61427d1017..ef57c22f18 100644 --- a/src/Core/Protocol.php +++ b/src/Core/Protocol.php @@ -187,7 +187,7 @@ class Protocol $eventDispatcher = DI::eventDispatcher(); $hook_data = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW, $hook_data), + new ArrayFilterEvent(ArrayFilterEvent::UNFOLLOW_CONTACT, $hook_data), )->getArray(); return $hook_data['result']; @@ -223,7 +223,12 @@ class Protocol 'uid' => $owner['uid'], 'result' => null, ]; - Hook::callAll('revoke_follow', $hook_data); + + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, $hook_data), + )->getArray(); return $hook_data['result']; } @@ -261,7 +266,12 @@ class Protocol 'uid' => $uid, 'result' => null, ]; - Hook::callAll('block', $hook_data); + + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::BLOCK_CONTACT, $hook_data), + )->getArray(); return $hook_data['result']; } @@ -300,7 +310,12 @@ class Protocol 'uid' => $uid, 'result' => null, ]; - Hook::callAll('unblock', $hook_data); + + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::UNBLOCK_CONTACT, $hook_data), + )->getArray(); return $hook_data['result']; } diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 9664071714..b4ec112272 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -62,7 +62,15 @@ final class ArrayFilterEvent extends Event public const PROTOCOL_SUPPORTS_PROBE = 'friendica.data.protocol_supports_probe'; - public const UNFOLLOW = 'friendica.data.unfollow'; + public const FOLLOW_CONTACT = 'friendica.data.follow_contact'; + + public const UNFOLLOW_CONTACT = 'friendica.data.unfollow_contact'; + + public const REVOKE_FOLLOW_CONTACT = 'friendica.data.revoke_follow_contact'; + + public const BLOCK_CONTACT = 'friendica.data.block_contact'; + + public const UNBLOCK_CONTACT = 'friendica.data.unblock_contact'; private array $array; diff --git a/src/Model/Contact.php b/src/Model/Contact.php index cced0ed626..e94ef46964 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -22,6 +22,7 @@ use Friendica\Core\Worker; use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; use Friendica\Network\HTTPException\NotFoundException; @@ -3144,7 +3145,11 @@ class Contact $arr = ['url' => $url, 'uid' => $uid, 'contact' => []]; - Hook::callAll('follow', $arr); + $eventDispatcher = DI::eventDispatcher(); + + $arr = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::FOLLOW_CONTACT, $arr), + )->getArray(); if (empty($arr)) { $result['message'] = DI::l10n()->t('The contact could not be added. Please check the relevant network credentials in your Settings -> Social Networks page.'); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 93d62965c3..f1b10ed3c7 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -51,7 +51,11 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW => 'onArrayFilterEvent', ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW => 'onArrayFilterEvent', ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE => 'onArrayFilterEvent', - ArrayFilterEvent::UNFOLLOW => 'onArrayFilterEvent', + ArrayFilterEvent::FOLLOW_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::UNFOLLOW_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', @@ -279,7 +283,11 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW, 'support_follow'], [ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW, 'support_revoke_follow'], [ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE, 'support_probe'], - [ArrayFilterEvent::UNFOLLOW, 'unfollow'], + [ArrayFilterEvent::FOLLOW_CONTACT, 'follow'], + [ArrayFilterEvent::UNFOLLOW_CONTACT, 'unfollow'], + [ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'revoke_follow'], + [ArrayFilterEvent::BLOCK_CONTACT, 'block'], + [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], ]; } diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 2d396e6760..be576995c7 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -47,6 +47,11 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW, 'friendica.data.protocol_supports_follow'], [ArrayFilterEvent::PROTOCOL_SUPPORTS_REVOKE_FOLLOW, 'friendica.data.protocol_supports_revoke_follow'], [ArrayFilterEvent::PROTOCOL_SUPPORTS_PROBE, 'friendica.data.protocol_supports_probe'], + [ArrayFilterEvent::FOLLOW_CONTACT, 'friendica.data.follow_contact'], + [ArrayFilterEvent::UNFOLLOW_CONTACT, 'friendica.data.unfollow_contact'], + [ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'friendica.data.revoke_follow_contact'], + [ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'], + [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], ]; } From 2a722b16aab9c23288d1f961b7dbd6f6d308854f Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 13 Mar 2025 14:50:29 +0000 Subject: [PATCH 41/91] Add event for proc_run hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Core/Worker.php | 12 +++++++----- src/Event/ArrayFilterEvent.php | 2 ++ tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 39da9a13d0..18a41a1730 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -67,6 +67,7 @@ final class HookEventBridge ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'revoke_follow', ArrayFilterEvent::BLOCK_CONTACT => 'block', ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', + ArrayFilterEvent::ADD_WORKER_TASK => 'proc_run', HtmlFilterEvent::HEAD => 'head', HtmlFilterEvent::FOOTER => 'footer', HtmlFilterEvent::PAGE_HEADER => 'page_header', @@ -114,6 +115,7 @@ final class HookEventBridge ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', diff --git a/src/Core/Worker.php b/src/Core/Worker.php index 995239cde9..0f14807adb 100644 --- a/src/Core/Worker.php +++ b/src/Core/Worker.php @@ -13,6 +13,7 @@ use Friendica\Core\Logger\Type\WorkerLogger; use Friendica\Core\Worker\Entity\Process; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Util\DateTimeFormat; /** @@ -1237,10 +1238,6 @@ class Worker * @return int '0' if worker queue entry already existed or there had been an error, otherwise the ID of the worker task * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @note $cmd and string args are surrounded with '' - * - * @hooks 'proc_run' - * array $arr - * */ public static function add(...$args) { @@ -1250,7 +1247,12 @@ class Worker $arr = ['args' => $args, 'run_cmd' => true]; - Hook::callAll('proc_run', $arr); + $eventDispatcher = DI::eventDispatcher(); + + $arr = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ADD_WORKER_TASK, $arr), + )->getArray(); + if (!$arr['run_cmd'] || !count($args)) { return 1; } diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index b4ec112272..6967524f86 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -72,6 +72,8 @@ final class ArrayFilterEvent extends Event public const UNBLOCK_CONTACT = 'friendica.data.unblock_contact'; + public const ADD_WORKER_TASK = 'friendica.data.add_worker_task'; + private array $array; public function __construct(string $name, array $array) diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index f1b10ed3c7..d7df82e4d1 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -56,6 +56,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', @@ -288,6 +289,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'revoke_follow'], [ArrayFilterEvent::BLOCK_CONTACT, 'block'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], + [ArrayFilterEvent::ADD_WORKER_TASK, 'proc_run'], ]; } diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index be576995c7..2afebba496 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -52,6 +52,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'friendica.data.revoke_follow_contact'], [ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], + [ArrayFilterEvent::ADD_WORKER_TASK, 'friendica.data.add_worker_task'], ]; } From cd00a8950f568ed653177cd4d68949fea8d9f9fb Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Thu, 13 Mar 2025 15:59:56 +0100 Subject: [PATCH 42/91] Update src/Contact/FriendSuggest/Repository/FriendSuggest.php Co-authored-by: Hypolite Petovan --- src/Contact/FriendSuggest/Repository/FriendSuggest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Contact/FriendSuggest/Repository/FriendSuggest.php b/src/Contact/FriendSuggest/Repository/FriendSuggest.php index a9f4610439..833421c7f6 100644 --- a/src/Contact/FriendSuggest/Repository/FriendSuggest.php +++ b/src/Contact/FriendSuggest/Repository/FriendSuggest.php @@ -49,7 +49,7 @@ class FriendSuggest extends BaseRepository */ private function selectOne(array $condition, array $params = []): FriendSuggestEntity { - $fields = $this->_selectFirstRowAsArray( $condition, $params); + $fields = $this->_selectFirstRowAsArray($condition, $params); return $this->factory->createFromTableRow($fields); } From bdfc87ab0d097d75b0f3009089360be2c1559d63 Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Thu, 13 Mar 2025 16:00:05 +0100 Subject: [PATCH 43/91] Update src/Contact/LocalRelationship/Repository/LocalRelationship.php Co-authored-by: Hypolite Petovan --- src/Contact/LocalRelationship/Repository/LocalRelationship.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Contact/LocalRelationship/Repository/LocalRelationship.php b/src/Contact/LocalRelationship/Repository/LocalRelationship.php index f00002a066..d1a87d5569 100644 --- a/src/Contact/LocalRelationship/Repository/LocalRelationship.php +++ b/src/Contact/LocalRelationship/Repository/LocalRelationship.php @@ -33,7 +33,7 @@ class LocalRelationship extends BaseRepository */ public function selectForUserContact(int $uid, int $cid): LocalRelationshipEntity { - $fields = $this->_selectFirstRowAsArray( ['uid' => $uid, 'cid' => $cid]); + $fields = $this->_selectFirstRowAsArray(['uid' => $uid, 'cid' => $cid]); return $this->factory->createFromTableRow($fields); } From 71bef03316288eab757bd27203c305f438520288 Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Thu, 13 Mar 2025 16:00:17 +0100 Subject: [PATCH 44/91] Update src/Content/Conversation/Repository/UserDefinedChannel.php Co-authored-by: Hypolite Petovan --- src/Content/Conversation/Repository/UserDefinedChannel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Content/Conversation/Repository/UserDefinedChannel.php b/src/Content/Conversation/Repository/UserDefinedChannel.php index 65b29d0c94..b9eecbf53c 100644 --- a/src/Content/Conversation/Repository/UserDefinedChannel.php +++ b/src/Content/Conversation/Repository/UserDefinedChannel.php @@ -69,7 +69,7 @@ class UserDefinedChannel extends BaseRepository */ public function selectById(int $id, int $uid): UserDefinedChannelEntity { - $fields = $this->_selectFirstRowAsArray( ['id' => $id, 'uid' => $uid]); + $fields = $this->_selectFirstRowAsArray(['id' => $id, 'uid' => $uid]); return $this->factory->createFromTableRow($fields); } From 2c87e7e102f2a383967a065108db3682b7462332 Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Thu, 13 Mar 2025 16:00:25 +0100 Subject: [PATCH 45/91] Update src/Content/Post/Repository/PostMedia.php Co-authored-by: Hypolite Petovan --- src/Content/Post/Repository/PostMedia.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Content/Post/Repository/PostMedia.php b/src/Content/Post/Repository/PostMedia.php index f02d93c665..9d6b09cb5f 100644 --- a/src/Content/Post/Repository/PostMedia.php +++ b/src/Content/Post/Repository/PostMedia.php @@ -46,7 +46,7 @@ class PostMedia extends BaseRepository public function selectOneById(int $postMediaId): PostMediaEntity { - $fields = $this->_selectFirstRowAsArray( ['id' => $postMediaId]); + $fields = $this->_selectFirstRowAsArray(['id' => $postMediaId]); return $this->factory->createFromTableRow($fields); } From b632b1d84e275b4061f09c0a38df0056ab5732cf Mon Sep 17 00:00:00 2001 From: Artur Weigandt Date: Thu, 13 Mar 2025 16:00:34 +0100 Subject: [PATCH 46/91] Update src/Core/Worker/Repository/Process.php Co-authored-by: Hypolite Petovan --- src/Core/Worker/Repository/Process.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Core/Worker/Repository/Process.php b/src/Core/Worker/Repository/Process.php index ee4d46a9f4..ece8dc9db2 100644 --- a/src/Core/Worker/Repository/Process.php +++ b/src/Core/Worker/Repository/Process.php @@ -59,7 +59,7 @@ class Process extends BaseRepository } } - $fields = $this->_selectFirstRowAsArray( ['pid' => $pid, 'hostname' => $this->currentHost]); + $fields = $this->_selectFirstRowAsArray(['pid' => $pid, 'hostname' => $this->currentHost]); $result = $this->factory->createFromTableRow($fields); From 8ba652818f169a4391c193f9dde31c3c0dddb61e Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 07:50:24 +0000 Subject: [PATCH 47/91] let ATProtocol Processor::fetchUriId() return int --- src/Protocol/ATProtocol/Processor.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Protocol/ATProtocol/Processor.php b/src/Protocol/ATProtocol/Processor.php index ba838817a9..da11cbb479 100755 --- a/src/Protocol/ATProtocol/Processor.php +++ b/src/Protocol/ATProtocol/Processor.php @@ -279,7 +279,7 @@ class Processor $uri = $this->getUri($post); if ($uri_id = $this->fetchUriId($uri, $uid)) { - return (int) $uri_id; + return $uri_id; } if (empty($post->record)) { @@ -322,7 +322,7 @@ class Processor $this->logger->warning('Fetched post was not inserted', ['guid' => $item['guid'], 'uri' => $item['uri']]); } - return (int) $this->fetchUriId($uri, $uid); + return $this->fetchUriId($uri, $uid); } private function getHeaderFromJetstream(stdClass $data, int $uid, int $protocol = Conversation::PARCEL_JETSTREAM): array @@ -848,19 +848,19 @@ class Processor return $class; } - public function fetchUriId(string $uri, int $uid): string + public function fetchUriId(string $uri, int $uid): int { $reply = Post::selectFirst(['uri-id'], ['uri' => $uri, 'uid' => [$uid, 0]]); if (!empty($reply['uri-id'])) { $this->logger->debug('Post exists', ['uri' => $uri]); - return $reply['uri-id']; + return (int) $reply['uri-id']; } $reply = Post::selectFirst(['uri-id'], ['extid' => $uri, 'uid' => [$uid, 0]]); if (!empty($reply['uri-id'])) { $this->logger->debug('Post with extid exists', ['uri' => $uri]); - return $reply['uri-id']; + return (int) $reply['uri-id']; } - return '0'; + return 0; } private function getPostUids(string $uri, bool $with_public_user): array From 2c0c87339ef72c0af7af24d892bacdd8c872869d Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 10:12:56 +0000 Subject: [PATCH 48/91] add events for storage_config and storage_instance hooks --- src/Core/Hooks/HookEventBridge.php | 4 + .../Storage/Repository/StorageManager.php | 18 ++- src/Event/ArrayFilterEvent.php | 4 + tests/Unit/Core/Hooks/HookEventBridgeTest.php | 4 + tests/Unit/Event/ArrayFilterEventTest.php | 2 + tests/Util/FakeEventDispatcher.php | 31 ++++++ .../Storage/Repository/StorageManagerTest.php | 103 +++++++++++++++--- 7 files changed, 149 insertions(+), 17 deletions(-) create mode 100644 tests/Util/FakeEventDispatcher.php diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 18a41a1730..6dc9d01e20 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -68,6 +68,8 @@ final class HookEventBridge ArrayFilterEvent::BLOCK_CONTACT => 'block', ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', ArrayFilterEvent::ADD_WORKER_TASK => 'proc_run', + ArrayFilterEvent::STORAGE_CONFIG => 'storage_config', + ArrayFilterEvent::STORAGE_INSTANCE => 'storage_instance', HtmlFilterEvent::HEAD => 'head', HtmlFilterEvent::FOOTER => 'footer', HtmlFilterEvent::PAGE_HEADER => 'page_header', @@ -116,6 +118,8 @@ final class HookEventBridge ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', + ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', + ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', diff --git a/src/Core/Storage/Repository/StorageManager.php b/src/Core/Storage/Repository/StorageManager.php index bbd9e13f14..1de89dbddc 100644 --- a/src/Core/Storage/Repository/StorageManager.php +++ b/src/Core/Storage/Repository/StorageManager.php @@ -20,7 +20,9 @@ use Friendica\Core\Storage\Capability\ICanWriteToStorage; use Friendica\Database\Database; use Friendica\Core\Storage\Type; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Network\HTTPException\InternalServerErrorException; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -55,6 +57,7 @@ class StorageManager private $config; /** @var LoggerInterface */ private $logger; + private EventDispatcherInterface $eventDispatcher; /** @var L10n */ private $l10n; @@ -71,11 +74,12 @@ class StorageManager * @throws InvalidClassStorageException in case the active backend class is invalid * @throws StorageException in case of unexpected errors during the active backend class loading */ - public function __construct(Database $dba, IManageConfigValues $config, LoggerInterface $logger, L10n $l10n, bool $includeAddon = true) + public function __construct(Database $dba, IManageConfigValues $config, LoggerInterface $logger, EventDispatcherInterface $eventDispatcher, L10n $l10n, bool $includeAddon = true) { $this->dba = $dba; $this->config = $config; $this->logger = $logger; + $this->eventDispatcher = $eventDispatcher; $this->l10n = $l10n; $this->validBackends = $config->get('storage', 'backends', self::DEFAULT_BACKENDS); @@ -146,8 +150,12 @@ class StorageManager 'name' => $name, 'storage_config' => null, ]; + try { - Hook::callAll('storage_config', $data); + $data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::STORAGE_CONFIG, $data), + )->getArray(); + if (!($data['storage_config'] ?? null) instanceof ICanConfigureStorage) { throw new InvalidClassStorageException(sprintf('Configuration for backend %s was not found', $name)); } @@ -201,8 +209,12 @@ class StorageManager 'name' => $name, 'storage' => null, ]; + try { - Hook::callAll('storage_instance', $data); + $data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::STORAGE_INSTANCE, $data), + )->getArray(); + if (!($data['storage'] ?? null) instanceof ICanReadFromStorage) { throw new InvalidClassStorageException(sprintf('Backend %s was not found', $name)); } diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 6967524f86..4a08ba4fa3 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -74,6 +74,10 @@ final class ArrayFilterEvent extends Event public const ADD_WORKER_TASK = 'friendica.data.add_worker_task'; + public const STORAGE_CONFIG = 'friendica.data.storage_config'; + + public const STORAGE_INSTANCE = 'friendica.data.storage_instance'; + private array $array; public function __construct(string $name, array $array) diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index d7df82e4d1..8ae803bdab 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -57,6 +57,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', + ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', + ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', @@ -290,6 +292,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::BLOCK_CONTACT, 'block'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], [ArrayFilterEvent::ADD_WORKER_TASK, 'proc_run'], + [ArrayFilterEvent::STORAGE_CONFIG, 'storage_config'], + [ArrayFilterEvent::STORAGE_INSTANCE, 'storage_instance'], ]; } diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 2afebba496..c57b45ceb1 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -53,6 +53,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], [ArrayFilterEvent::ADD_WORKER_TASK, 'friendica.data.add_worker_task'], + [ArrayFilterEvent::STORAGE_CONFIG, 'friendica.data.storage_config'], + [ArrayFilterEvent::STORAGE_INSTANCE, 'friendica.data.storage_instance'], ]; } diff --git a/tests/Util/FakeEventDispatcher.php b/tests/Util/FakeEventDispatcher.php new file mode 100644 index 0000000000..070e8e77d9 --- /dev/null +++ b/tests/Util/FakeEventDispatcher.php @@ -0,0 +1,31 @@ +at($this->root); - $this->logger = new NullLogger(); $this->database = $this->getDbInstance(); $configFactory = new Config(); @@ -87,7 +85,14 @@ class StorageManagerTest extends DatabaseTestCase */ public function testInstance() { - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); self::assertInstanceOf(StorageManager::class, $storageManager); } @@ -149,7 +154,14 @@ class StorageManagerTest extends DatabaseTestCase $this->config->set('storage', 'name', $name); } - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); if ($interface === ICanWriteToStorage::class) { $storage = $storageManager->getWritableStorageByName($name); @@ -169,7 +181,14 @@ class StorageManagerTest extends DatabaseTestCase */ public function testIsValidBackend($name, $valid, $interface, $assert, $assertName) { - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); // true in every of the backends self::assertEquals(!empty($assertName), $storageManager->isValidBackend($name)); @@ -183,7 +202,14 @@ class StorageManagerTest extends DatabaseTestCase */ public function testListBackends() { - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); self::assertEquals(StorageManager::DEFAULT_BACKENDS, $storageManager->listBackends()); } @@ -199,7 +225,14 @@ class StorageManagerTest extends DatabaseTestCase static::markTestSkipped('only works for ICanWriteToStorage'); } - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); $selBackend = $storageManager->getWritableStorageByName($name); $storageManager->setBackend($selBackend); @@ -219,7 +252,14 @@ class StorageManagerTest extends DatabaseTestCase $this->expectException(InvalidClassStorageException::class); } - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); self::assertInstanceOf($assert, $storageManager->getBackend()); } @@ -240,7 +280,14 @@ class StorageManagerTest extends DatabaseTestCase ->addRule(IHandleSessions::class, ['instanceOf' => Memory::class, 'shared' => true, 'call' => null]); DI::init($dice); - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); self::assertTrue($storageManager->register(SampleStorageBackend::class)); @@ -268,7 +315,21 @@ class StorageManagerTest extends DatabaseTestCase ->addRule(IHandleSessions::class, ['instanceOf' => Memory::class, 'shared' => true, 'call' => null]); DI::init($dice); - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + /** @var \Friendica\Event\EventDispatcher */ + $eventDispatcher = DI::eventDispatcher(); + + foreach (HookEventBridge::getStaticSubscribedEvents() as $eventName => $methodName) { + $eventDispatcher->addListener($eventName, [HookEventBridge::class, $methodName]); + } + + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + $eventDispatcher, + $this->l10n, + false + ); self::assertTrue($storageManager->register(SampleStorageBackend::class)); @@ -307,7 +368,14 @@ class StorageManagerTest extends DatabaseTestCase $this->loadFixture(__DIR__ . '/../../../../datasets/storage/database.fixture.php', $this->database); - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); $storage = $storageManager->getWritableStorageByName($name); $storageManager->move($storage); @@ -331,7 +399,14 @@ class StorageManagerTest extends DatabaseTestCase $this->expectException(InvalidClassStorageException::class); $this->expectExceptionMessage('Backend SystemResource is not valid'); - $storageManager = new StorageManager($this->database, $this->config, $this->logger, $this->l10n, false); + $storageManager = new StorageManager( + $this->database, + $this->config, + new NullLogger(), + new FakeEventDispatcher(), + $this->l10n, + false + ); $storage = $storageManager->getWritableStorageByName(SystemResource::getName()); $storageManager->move($storage); } From 04818781a79d28292f5fff7f487a73225c3d3099 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 10:14:23 +0000 Subject: [PATCH 49/91] Fix code style --- tests/Util/FakeEventDispatcher.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Util/FakeEventDispatcher.php b/tests/Util/FakeEventDispatcher.php index 070e8e77d9..434e9ba5a6 100644 --- a/tests/Util/FakeEventDispatcher.php +++ b/tests/Util/FakeEventDispatcher.php @@ -16,15 +16,15 @@ use Psr\EventDispatcher\EventDispatcherInterface; */ final class FakeEventDispatcher implements EventDispatcherInterface { - /** - * Provide all relevant listeners with an event to process. - * - * @template T of object + /** + * Provide all relevant listeners with an event to process. + * + * @template T of object * @param T $event * * @return T The passed $event MUST be returned - */ - public function dispatch(object $event): object + */ + public function dispatch(object $event): object { return $event; } From 9e3b0b3c40706bddb5f0c96a294c61ee5539fb87 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 12:24:02 +0000 Subject: [PATCH 50/91] Create event for dbstructure_definition hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Database/Definition/DbaDefinition.php | 10 +++++++--- src/Event/ArrayFilterEvent.php | 2 ++ tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 2 ++ 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 6dc9d01e20..7c23e333f1 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -70,6 +70,7 @@ final class HookEventBridge ArrayFilterEvent::ADD_WORKER_TASK => 'proc_run', ArrayFilterEvent::STORAGE_CONFIG => 'storage_config', ArrayFilterEvent::STORAGE_INSTANCE => 'storage_instance', + ArrayFilterEvent::DB_STRUCTURE_DEFINITION => 'dbstructure_definition', HtmlFilterEvent::HEAD => 'head', HtmlFilterEvent::FOOTER => 'footer', HtmlFilterEvent::PAGE_HEADER => 'page_header', @@ -120,6 +121,7 @@ final class HookEventBridge ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', + ArrayFilterEvent::DB_STRUCTURE_DEFINITION => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', diff --git a/src/Database/Definition/DbaDefinition.php b/src/Database/Definition/DbaDefinition.php index 378ba86867..ecc75f6aa3 100644 --- a/src/Database/Definition/DbaDefinition.php +++ b/src/Database/Definition/DbaDefinition.php @@ -8,9 +8,9 @@ namespace Friendica\Database\Definition; use Exception; -use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Hook; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; /** * Stores the whole database definition @@ -109,12 +109,16 @@ class DbaDefinition { $definition = require $this->configFile; - if (!$definition) { + if (!is_array($definition)) { throw new Exception('Corrupted database structure config file static/dbstructure.config.php'); } if ($withAddonStructure) { - Hook::callAll('dbstructure_definition', $definition); + $eventDispatcher = DI::eventDispatcher(); + + $definition = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::DB_STRUCTURE_DEFINITION, $definition), + )->getArray(); } $this->definition = $definition; diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 4a08ba4fa3..f8e19bdad5 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -78,6 +78,8 @@ final class ArrayFilterEvent extends Event public const STORAGE_INSTANCE = 'friendica.data.storage_instance'; + public const DB_STRUCTURE_DEFINITION = 'friendica.data.db_structure_definition'; + private array $array; public function __construct(string $name, array $array) diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 8ae803bdab..ca0cb2c160 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -59,6 +59,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', + ArrayFilterEvent::DB_STRUCTURE_DEFINITION => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', @@ -294,6 +295,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::ADD_WORKER_TASK, 'proc_run'], [ArrayFilterEvent::STORAGE_CONFIG, 'storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'storage_instance'], + [ArrayFilterEvent::DB_STRUCTURE_DEFINITION, 'dbstructure_definition'], ]; } diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index c57b45ceb1..67b2e8a576 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -42,6 +42,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PAGE_INFO, 'friendica.data.page_info'], [ArrayFilterEvent::SMILEY_LIST, 'friendica.data.smiley_list'], [ArrayFilterEvent::BBCODE_TO_HTML_START, 'friendica.data.bbcode_to_html_start'], + [ArrayFilterEvent::HTML_TO_BBCODE_END, 'friendica.data.html_to_bbcode_end'], [ArrayFilterEvent::BBCODE_TO_MARKDOWN_END, 'friendica.data.bbcode_to_markdown_end'], [ArrayFilterEvent::JOT_NETWORKS, 'friendica.data.jot_networks'], [ArrayFilterEvent::PROTOCOL_SUPPORTS_FOLLOW, 'friendica.data.protocol_supports_follow'], @@ -55,6 +56,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::ADD_WORKER_TASK, 'friendica.data.add_worker_task'], [ArrayFilterEvent::STORAGE_CONFIG, 'friendica.data.storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'friendica.data.storage_instance'], + [ArrayFilterEvent::DB_STRUCTURE_DEFINITION, 'friendica.data.db_structure_definition'], ]; } From 9cf0ce0b99831f66f78c47752944732be61f3055 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 13:02:39 +0000 Subject: [PATCH 51/91] create event for dbview_definition hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Database/Definition/DbaDefinition.php | 1 - src/Database/Definition/ViewDefinition.php | 11 ++++++++--- src/Event/ArrayFilterEvent.php | 2 ++ tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 6 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 7c23e333f1..6c477dae36 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -71,6 +71,7 @@ final class HookEventBridge ArrayFilterEvent::STORAGE_CONFIG => 'storage_config', ArrayFilterEvent::STORAGE_INSTANCE => 'storage_instance', ArrayFilterEvent::DB_STRUCTURE_DEFINITION => 'dbstructure_definition', + ArrayFilterEvent::DB_VIEW_DEFINITION => 'dbview_definition', HtmlFilterEvent::HEAD => 'head', HtmlFilterEvent::FOOTER => 'footer', HtmlFilterEvent::PAGE_HEADER => 'page_header', @@ -122,6 +123,7 @@ final class HookEventBridge ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', ArrayFilterEvent::DB_STRUCTURE_DEFINITION => 'onArrayFilterEvent', + ArrayFilterEvent::DB_VIEW_DEFINITION => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', diff --git a/src/Database/Definition/DbaDefinition.php b/src/Database/Definition/DbaDefinition.php index ecc75f6aa3..c5d77d3a46 100644 --- a/src/Database/Definition/DbaDefinition.php +++ b/src/Database/Definition/DbaDefinition.php @@ -8,7 +8,6 @@ namespace Friendica\Database\Definition; use Exception; -use Friendica\Core\Hook; use Friendica\DI; use Friendica\Event\ArrayFilterEvent; diff --git a/src/Database/Definition/ViewDefinition.php b/src/Database/Definition/ViewDefinition.php index b64e0d0ffc..3c6cb2f43a 100644 --- a/src/Database/Definition/ViewDefinition.php +++ b/src/Database/Definition/ViewDefinition.php @@ -8,7 +8,8 @@ namespace Friendica\Database\Definition; use Exception; -use Friendica\Core\Hook; +use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; /** * Stores the whole View definitions @@ -62,12 +63,16 @@ class ViewDefinition { $definition = require $this->configFile; - if (!$definition) { + if (!is_array($definition)) { throw new Exception('Corrupted database structure config file static/dbstructure.config.php'); } if ($withAddonStructure) { - Hook::callAll('dbview_definition', $definition); + $eventDispatcher = DI::eventDispatcher(); + + $definition = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::DB_VIEW_DEFINITION, $definition), + )->getArray(); } $this->definition = $definition; diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index f8e19bdad5..f62d7f02c6 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -80,6 +80,8 @@ final class ArrayFilterEvent extends Event public const DB_STRUCTURE_DEFINITION = 'friendica.data.db_structure_definition'; + public const DB_VIEW_DEFINITION = 'friendica.data.db_view_definition'; + private array $array; public function __construct(string $name, array $array) diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index ca0cb2c160..f496467e54 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -60,6 +60,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', ArrayFilterEvent::DB_STRUCTURE_DEFINITION => 'onArrayFilterEvent', + ArrayFilterEvent::DB_VIEW_DEFINITION => 'onArrayFilterEvent', HtmlFilterEvent::HEAD => 'onHtmlFilterEvent', HtmlFilterEvent::FOOTER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', @@ -296,6 +297,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::STORAGE_CONFIG, 'storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'storage_instance'], [ArrayFilterEvent::DB_STRUCTURE_DEFINITION, 'dbstructure_definition'], + [ArrayFilterEvent::DB_VIEW_DEFINITION, 'dbview_definition'], ]; } diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 67b2e8a576..e55fa313a6 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -57,6 +57,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::STORAGE_CONFIG, 'friendica.data.storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'friendica.data.storage_instance'], [ArrayFilterEvent::DB_STRUCTURE_DEFINITION, 'friendica.data.db_structure_definition'], + [ArrayFilterEvent::DB_VIEW_DEFINITION, 'friendica.data.db_view_definition'], ]; } From d34861ee9691dd0468e8de532b9513acce26c3f4 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 13:23:21 +0000 Subject: [PATCH 52/91] Create event for contact_photo_menu hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Model/Contact.php | 12 ++++++++++-- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 6c477dae36..6f61c58c72 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -52,6 +52,7 @@ final class HookEventBridge ArrayFilterEvent::DISPLAY_ITEM => 'display_item', ArrayFilterEvent::RENDER_LOCATION => 'render_location', ArrayFilterEvent::ITEM_PHOTO_MENU => 'item_photo_menu', + ArrayFilterEvent::CONTACT_PHOTO_MENU => 'contact_photo_menu', ArrayFilterEvent::OEMBED_FETCH_END => 'oembed_fetch_url', ArrayFilterEvent::PAGE_INFO => 'page_info_data', ArrayFilterEvent::SMILEY_LIST => 'smilie', @@ -104,6 +105,7 @@ final class HookEventBridge ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', + ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index f62d7f02c6..056cdec470 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -42,6 +42,8 @@ final class ArrayFilterEvent extends Event public const ITEM_PHOTO_MENU = 'friendica.data.item_photo_menu'; + public const CONTACT_PHOTO_MENU = 'friendica.data.contact_photo_menu'; + public const OEMBED_FETCH_END = 'friendica.data.oembed_fetch_end'; public const PAGE_INFO = 'friendica.data.page_info'; diff --git a/src/Model/Contact.php b/src/Model/Contact.php index e94ef46964..845c8be4ee 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -1312,9 +1312,17 @@ class Contact } } - $args = ['contact' => $contact, 'menu' => &$menu]; + $args = ['contact' => $contact, 'menu' => $menu]; - Hook::callAll('contact_photo_menu', $args); + $eventDispatcher = DI::eventDispatcher(); + + $args = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::CONTACT_PHOTO_MENU, $args), + )->getArray(); + + if (is_array($args['menu'])) { + $menu = $args['menu']; + } $menucondensed = []; diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index f496467e54..949401f364 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -41,6 +41,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', + ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', @@ -282,6 +283,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::DISPLAY_ITEM, 'display_item'], [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], + [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'], [ArrayFilterEvent::PAGE_INFO, 'page_info_data'], [ArrayFilterEvent::SMILEY_LIST, 'smilie'], [ArrayFilterEvent::JOT_NETWORKS, 'jot_networks'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index e55fa313a6..2e539e290e 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -38,6 +38,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::DISPLAY_ITEM, 'friendica.data.display_item'], [ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'friendica.data.item_photo_menu'], + [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'friendica.data.contact_photo_menu'], [ArrayFilterEvent::OEMBED_FETCH_END, 'friendica.data.oembed_fetch_end'], [ArrayFilterEvent::PAGE_INFO, 'friendica.data.page_info'], [ArrayFilterEvent::SMILEY_LIST, 'friendica.data.smiley_list'], From 68b604812cc9d2a80ee4ffaf0732c994c44af924 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 13:31:11 +0000 Subject: [PATCH 53/91] create event for avatar_lookup hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Model/Contact.php | 7 +++++-- src/Util/Network.php | 8 ++++++-- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 6 files changed, 18 insertions(+), 4 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 6f61c58c72..cc2e8be225 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -68,6 +68,7 @@ final class HookEventBridge ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'revoke_follow', ArrayFilterEvent::BLOCK_CONTACT => 'block', ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', + ArrayFilterEvent::AVATAR_LOOKUP => 'avatar_lookup', ArrayFilterEvent::ADD_WORKER_TASK => 'proc_run', ArrayFilterEvent::STORAGE_CONFIG => 'storage_config', ArrayFilterEvent::STORAGE_INSTANCE => 'storage_instance', @@ -121,6 +122,7 @@ final class HookEventBridge ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 056cdec470..ac72f3d29a 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -74,6 +74,8 @@ final class ArrayFilterEvent extends Event public const UNBLOCK_CONTACT = 'friendica.data.unblock_contact'; + public const AVATAR_LOOKUP = 'friendica.data.avatar_lookup'; + public const ADD_WORKER_TASK = 'friendica.data.add_worker_task'; public const STORAGE_CONFIG = 'friendica.data.storage_config'; diff --git a/src/Model/Contact.php b/src/Model/Contact.php index 845c8be4ee..4684317e76 100644 --- a/src/Model/Contact.php +++ b/src/Model/Contact.php @@ -14,7 +14,6 @@ use Friendica\Contact\Introduction\Exception\IntroductionNotFoundException; use Friendica\Content\Conversation as ConversationContent; use Friendica\Content\Pager; use Friendica\Content\Text\HTML; -use Friendica\Core\Hook; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\System; @@ -2205,7 +2204,11 @@ class Contact $avatar['url'] = ''; $avatar['success'] = false; - Hook::callAll('avatar_lookup', $avatar); + $eventDispatcher = DI::eventDispatcher(); + + $avatar = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::AVATAR_LOOKUP, $avatar), + )->getArray(); if ($avatar['success'] && !empty($avatar['url'])) { return $avatar['url']; diff --git a/src/Util/Network.php b/src/Util/Network.php index 1584faea3f..2172c5a177 100644 --- a/src/Util/Network.php +++ b/src/Util/Network.php @@ -7,8 +7,8 @@ namespace Friendica\Util; -use Friendica\Core\Hook; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Contact; use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; @@ -302,7 +302,11 @@ class Network $avatar['url'] = ''; $avatar['success'] = false; - Hook::callAll('avatar_lookup', $avatar); + $eventDispatcher = DI::eventDispatcher(); + + $avatar = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::AVATAR_LOOKUP, $avatar), + )->getArray(); if (! $avatar['success']) { $avatar['url'] = DI::baseUrl() . Contact::DEFAULT_AVATAR_PHOTO; diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 949401f364..77e0b1ecfc 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -57,6 +57,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', @@ -295,6 +296,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'revoke_follow'], [ArrayFilterEvent::BLOCK_CONTACT, 'block'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], + [ArrayFilterEvent::AVATAR_LOOKUP, 'avatar_lookup'], [ArrayFilterEvent::ADD_WORKER_TASK, 'proc_run'], [ArrayFilterEvent::STORAGE_CONFIG, 'storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'storage_instance'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 2e539e290e..0e0c147216 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -54,6 +54,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'friendica.data.revoke_follow_contact'], [ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], + [ArrayFilterEvent::AVATAR_LOOKUP, 'friendica.data.avatar_lookup'], [ArrayFilterEvent::ADD_WORKER_TASK, 'friendica.data.add_worker_task'], [ArrayFilterEvent::STORAGE_CONFIG, 'friendica.data.storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'friendica.data.storage_instance'], From abe35732d85f93c80ddf5b91467f645598278783 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 14:11:58 +0000 Subject: [PATCH 54/91] create event for event_created and event_updated hooks --- src/Core/Hook.php | 4 +- src/Core/Hooks/HookEventBridge.php | 34 ++++++++++++++++- src/Event/ArrayFilterEvent.php | 4 ++ src/Model/Event.php | 10 ++++- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 38 +++++++++++++++++++ tests/Unit/Event/ArrayFilterEventTest.php | 2 + 6 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/Core/Hook.php b/src/Core/Hook.php index 44dfad70bc..c783f0a226 100644 --- a/src/Core/Hook.php +++ b/src/Core/Hook.php @@ -171,8 +171,8 @@ class Hook * Use this function when you want to be able to allow a hook to manipulate * the provided data. * - * @param string $name of the hook to call - * @param string|array &$data to transmit to the callback handler + * @param string $name of the hook to call + * @param int|string|array|null $data to transmit to the callback handler * @return void * @throws \Friendica\Network\HTTPException\InternalServerErrorException */ diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index cc2e8be225..1567b3e20a 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -69,6 +69,8 @@ final class HookEventBridge ArrayFilterEvent::BLOCK_CONTACT => 'block', ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', ArrayFilterEvent::AVATAR_LOOKUP => 'avatar_lookup', + ArrayFilterEvent::EVENT_CREATED => 'event_created', + ArrayFilterEvent::EVENT_UPDATED => 'event_updated', ArrayFilterEvent::ADD_WORKER_TASK => 'proc_run', ArrayFilterEvent::STORAGE_CONFIG => 'storage_config', ArrayFilterEvent::STORAGE_INSTANCE => 'storage_instance', @@ -123,6 +125,8 @@ final class HookEventBridge ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', + ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent', + ArrayFilterEvent::EVENT_UPDATED => 'onEventUpdatedEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', @@ -211,6 +215,32 @@ final class HookEventBridge $event->setArray($data); } + /** + * Map the EVENT_CREATED event to `event_created` hook + */ + public static function onEventCreatedEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $id = (int) $data['event']['id'] ?? 0; + + // one-way-event: we don't care about the returned value + static::callHook($event->getName(), $id); + } + + /** + * Map the EVENT_UPDATED event to `event_updated` hook + */ + public static function onEventUpdatedEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $id = (int) $data['event']['id'] ?? 0; + + // one-way-event: we don't care about the returned value + static::callHook($event->getName(), $id); + } + public static function onArrayFilterEvent(ArrayFilterEvent $event): void { $event->setArray( @@ -226,9 +256,9 @@ final class HookEventBridge } /** - * @param string|array|object $data + * @param int|string|array|object $data * - * @return string|array|object + * @return int|string|array|object */ private static function callHook(string $name, $data) { diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index ac72f3d29a..b3be9f70fa 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -76,6 +76,10 @@ final class ArrayFilterEvent extends Event public const AVATAR_LOOKUP = 'friendica.data.avatar_lookup'; + public const EVENT_CREATED = 'friendica.data.event_created'; + + public const EVENT_UPDATED = 'friendica.data.event_updated'; + public const ADD_WORKER_TASK = 'friendica.data.add_worker_task'; public const STORAGE_CONFIG = 'friendica.data.storage_config'; diff --git a/src/Model/Event.php b/src/Model/Event.php index 6cb73f4c37..debeb74d45 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -14,6 +14,7 @@ use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Network\HTTPException\InternalServerErrorException; use Friendica\Network\HTTPException\NotFoundException; use Friendica\Network\HTTPException\UnauthorizedException; @@ -255,6 +256,7 @@ class Event 'finish' => DateTimeFormat::utc(($arr['finish'] ?? '') ?: DBA::NULL_DATETIME), ]; + $eventDispatcher = DI::eventDispatcher(); if ($event['finish'] < DBA::NULL_DATETIME) { $event['finish'] = DBA::NULL_DATETIME; @@ -295,14 +297,18 @@ class Event Item::update($fields, ['id' => $item['id']]); } - Hook::callAll('event_updated', $event['id']); + $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::EVENT_UPDATED, ['event' => $event]), + ); } else { // New event. Store it. DBA::insert('event', $event); $event['id'] = DBA::lastInsertId(); - Hook::callAll("event_created", $event['id']); + $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::EVENT_CREATED, ['event' => $event]), + ); } return $event['id']; diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 77e0b1ecfc..1852248ebb 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -58,6 +58,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', + ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent', + ArrayFilterEvent::EVENT_UPDATED => 'onEventUpdatedEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_CONFIG => 'onArrayFilterEvent', ArrayFilterEvent::STORAGE_INSTANCE => 'onArrayFilterEvent', @@ -267,6 +269,40 @@ class HookEventBridgeTest extends TestCase ); } + public function testOnEventCreatedEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::EVENT_CREATED, ['event' => ['id' => 123]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, int $data): int { + $this->assertSame('event_created', $name); + $this->assertSame(123, $data); + + return 123; + }); + + HookEventBridge::onEventCreatedEvent($event); + } + + public function testOnEventUpdatedEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::EVENT_UPDATED, ['event' => ['id' => 123]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, int $data): int { + $this->assertSame('event_updated', $name); + $this->assertSame(123, $data); + + return 123; + }); + + HookEventBridge::onEventUpdatedEvent($event); + } + public static function getArrayFilterEventData(): array { return [ @@ -297,6 +333,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::BLOCK_CONTACT, 'block'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], [ArrayFilterEvent::AVATAR_LOOKUP, 'avatar_lookup'], + [ArrayFilterEvent::EVENT_CREATED, 'event_created'], + [ArrayFilterEvent::EVENT_UPDATED, 'event_updated'], [ArrayFilterEvent::ADD_WORKER_TASK, 'proc_run'], [ArrayFilterEvent::STORAGE_CONFIG, 'storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'storage_instance'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 0e0c147216..0e4467c1ed 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -55,6 +55,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], [ArrayFilterEvent::AVATAR_LOOKUP, 'friendica.data.avatar_lookup'], + [ArrayFilterEvent::EVENT_CREATED, 'friendica.data.event_created'], + [ArrayFilterEvent::EVENT_UPDATED, 'friendica.data.event_updated'], [ArrayFilterEvent::ADD_WORKER_TASK, 'friendica.data.add_worker_task'], [ArrayFilterEvent::STORAGE_CONFIG, 'friendica.data.storage_config'], [ArrayFilterEvent::STORAGE_INSTANCE, 'friendica.data.storage_instance'], From 9aeb68231d98bd4ad5a2b798c74d4d7d8436136b Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 15:35:53 +0000 Subject: [PATCH 55/91] Create events for post_remote and post_remote_end hook --- src/Core/Hooks/HookEventBridge.php | 4 ++++ src/Event/ArrayFilterEvent.php | 4 ++++ src/Model/Event.php | 1 - src/Model/Item.php | 10 ++++++++-- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 4 ++++ tests/Unit/Event/ArrayFilterEventTest.php | 2 ++ 6 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 1567b3e20a..18a2754e33 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -46,6 +46,8 @@ final class HookEventBridge ArrayFilterEvent::POST_LOCAL_START => 'post_local_start', ArrayFilterEvent::POST_LOCAL => 'post_local', ArrayFilterEvent::POST_LOCAL_END => 'post_local_end', + ArrayFilterEvent::INSERT_POST_REMOTE => 'post_remote', + ArrayFilterEvent::INSERT_POST_REMOTE_END => 'post_remote_end', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'photo_upload_form', ArrayFilterEvent::NETWORK_TO_NAME => 'network_to_name', ArrayFilterEvent::CONVERSATION_START => 'conversation_start', @@ -102,6 +104,8 @@ final class HookEventBridge ArrayFilterEvent::POST_LOCAL_START => 'onArrayFilterEvent', ArrayFilterEvent::POST_LOCAL => 'onArrayFilterEvent', ArrayFilterEvent::POST_LOCAL_END => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index b3be9f70fa..0ab06525bd 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -30,6 +30,10 @@ final class ArrayFilterEvent extends Event public const POST_LOCAL_END = 'friendica.data.post_local_end'; + public const INSERT_POST_REMOTE = 'friendica.data.insert_post_remote'; + + public const INSERT_POST_REMOTE_END = 'friendica.data.insert_post_remote_end'; + public const PHOTO_UPLOAD_FORM = 'friendica.data.photo_upload_form'; public const NETWORK_TO_NAME = 'friendica.data.network_to_name'; diff --git a/src/Model/Event.php b/src/Model/Event.php index debeb74d45..125692dfe1 100644 --- a/src/Model/Event.php +++ b/src/Model/Event.php @@ -9,7 +9,6 @@ namespace Friendica\Model; use Friendica\Content\Feature; use Friendica\Content\Text\BBCode; -use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\Core\System; use Friendica\Database\DBA; diff --git a/src/Model/Item.php b/src/Model/Item.php index 31f8a8e22e..99ebba8cae 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -855,7 +855,9 @@ class Item unset($_SESSION['uid']); } } elseif (!$notify) { - Hook::callAll('post_remote', $item); + $item = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_REMOTE, $item) + )->getArray(); } if (!empty($item['cancel'])) { @@ -1112,7 +1114,11 @@ class Item DI::contentItem()->copyPermissions($posted_item['thr-parent-id'], $posted_item['uri-id'], $posted_item['parent-uri-id']); } } else { - Hook::callAll('post_remote_end', $posted_item); + $eventDispatcher = DI::eventDispatcher(); + + $posted_item = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_REMOTE_END, $posted_item) + )->getArray(); } if ($posted_item['gravity'] === self::GRAVITY_PARENT) { diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 1852248ebb..69c49f3513 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -35,6 +35,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::POST_LOCAL_START => 'onArrayFilterEvent', ArrayFilterEvent::POST_LOCAL => 'onArrayFilterEvent', ArrayFilterEvent::POST_LOCAL_END => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', @@ -314,6 +316,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::POST_LOCAL_START, 'post_local_start'], [ArrayFilterEvent::POST_LOCAL, 'post_local'], [ArrayFilterEvent::POST_LOCAL_END, 'post_local_end'], + [ArrayFilterEvent::INSERT_POST_REMOTE, 'post_remote'], + [ArrayFilterEvent::INSERT_POST_REMOTE_END, 'post_remote_end'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'conversation_start'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 0e4467c1ed..193ccc77d8 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -32,6 +32,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::POST_LOCAL_START, 'friendica.data.post_local_start'], [ArrayFilterEvent::POST_LOCAL, 'friendica.data.post_local'], [ArrayFilterEvent::POST_LOCAL_END, 'friendica.data.post_local_end'], + [ArrayFilterEvent::INSERT_POST_REMOTE, 'friendica.data.insert_post_remote'], + [ArrayFilterEvent::INSERT_POST_REMOTE_END, 'friendica.data.insert_post_remote_end'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'], From 9c6f5f222d1daffe1254308d9ca6f1a18b9497d5 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 14 Mar 2025 15:45:36 +0000 Subject: [PATCH 56/91] Rename events to insert local post --- mod/item.php | 4 ++-- src/Content/Item.php | 2 +- src/Core/Hooks/HookEventBridge.php | 12 ++++++------ src/Event/ArrayFilterEvent.php | 6 +++--- src/Model/Item.php | 2 +- src/Module/Post/Tag/Add.php | 2 +- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 12 ++++++------ tests/Unit/Event/ArrayFilterEventTest.php | 6 +++--- 8 files changed, 23 insertions(+), 23 deletions(-) diff --git a/mod/item.php b/mod/item.php index 46f2a219e3..e6b2cb93f4 100644 --- a/mod/item.php +++ b/mod/item.php @@ -46,7 +46,7 @@ function item_post() $eventDispatcher = DI::eventDispatcher(); $_REQUEST = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::POST_LOCAL_START, $_REQUEST) + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_START, $_REQUEST) )->getArray(); $return_path = $_REQUEST['return'] ?? ''; @@ -282,7 +282,7 @@ function item_process(array $post, array $request, bool $preview, string $return $eventDispatcher = DI::eventDispatcher(); $post = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::POST_LOCAL, $post) + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, $post) )->getArray(); unset($post['edit']); diff --git a/src/Content/Item.php b/src/Content/Item.php index 9c9cd10bed..af26ebd8ed 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -1012,7 +1012,7 @@ class Item } $post = $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::POST_LOCAL_END, $post) + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, $post) )->getArray(); $author = DBA::selectFirst('contact', ['thumb'], ['uid' => $post['uid'], 'self' => true]); diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 18a2754e33..251c462929 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -43,9 +43,9 @@ final class HookEventBridge ArrayFilterEvent::NAV_INFO => 'nav_info', ArrayFilterEvent::FEATURE_ENABLED => 'isEnabled', ArrayFilterEvent::FEATURE_GET => 'get', - ArrayFilterEvent::POST_LOCAL_START => 'post_local_start', - ArrayFilterEvent::POST_LOCAL => 'post_local', - ArrayFilterEvent::POST_LOCAL_END => 'post_local_end', + ArrayFilterEvent::INSERT_POST_LOCAL_START => 'post_local_start', + ArrayFilterEvent::INSERT_POST_LOCAL => 'post_local', + ArrayFilterEvent::INSERT_POST_LOCAL_END => 'post_local_end', ArrayFilterEvent::INSERT_POST_REMOTE => 'post_remote', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'post_remote_end', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'photo_upload_form', @@ -101,9 +101,9 @@ final class HookEventBridge ArrayFilterEvent::NAV_INFO => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent', - ArrayFilterEvent::POST_LOCAL_START => 'onArrayFilterEvent', - ArrayFilterEvent::POST_LOCAL => 'onArrayFilterEvent', - ArrayFilterEvent::POST_LOCAL_END => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 0ab06525bd..51719e7de9 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -24,11 +24,11 @@ final class ArrayFilterEvent extends Event public const FEATURE_GET = 'friendica.data.feature_get'; - public const POST_LOCAL_START = 'friendica.data.post_local_start'; + public const INSERT_POST_LOCAL_START = 'friendica.data.insert_post_local_start'; - public const POST_LOCAL = 'friendica.data.post_local'; + public const INSERT_POST_LOCAL = 'friendica.data.insert_post_local'; - public const POST_LOCAL_END = 'friendica.data.post_local_end'; + public const INSERT_POST_LOCAL_END = 'friendica.data.insert_post_local_end'; public const INSERT_POST_REMOTE = 'friendica.data.insert_post_remote'; diff --git a/src/Model/Item.php b/src/Model/Item.php index 99ebba8cae..d2169d3156 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -847,7 +847,7 @@ class Item } $item = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::POST_LOCAL, $item) + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, $item) )->getArray(); if ($dummy_session) { diff --git a/src/Module/Post/Tag/Add.php b/src/Module/Post/Tag/Add.php index bf704a50c0..e03bf215a3 100644 --- a/src/Module/Post/Tag/Add.php +++ b/src/Module/Post/Tag/Add.php @@ -154,7 +154,7 @@ EOT; $post['id'] = $post_id; $post = $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::POST_LOCAL_END, $post) + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, $post) )->getArray(); $post = Post::selectFirst(['uri-id', 'uid'], ['id' => $post_id]); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 69c49f3513..325aefb742 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -32,9 +32,9 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::NAV_INFO => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent', - ArrayFilterEvent::POST_LOCAL_START => 'onArrayFilterEvent', - ArrayFilterEvent::POST_LOCAL => 'onArrayFilterEvent', - ArrayFilterEvent::POST_LOCAL_END => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', @@ -313,9 +313,9 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::NAV_INFO, 'nav_info'], [ArrayFilterEvent::FEATURE_ENABLED, 'isEnabled'], [ArrayFilterEvent::FEATURE_GET, 'get'], - [ArrayFilterEvent::POST_LOCAL_START, 'post_local_start'], - [ArrayFilterEvent::POST_LOCAL, 'post_local'], - [ArrayFilterEvent::POST_LOCAL_END, 'post_local_end'], + [ArrayFilterEvent::INSERT_POST_LOCAL_START, 'post_local_start'], + [ArrayFilterEvent::INSERT_POST_LOCAL, 'post_local'], + [ArrayFilterEvent::INSERT_POST_LOCAL_END, 'post_local_end'], [ArrayFilterEvent::INSERT_POST_REMOTE, 'post_remote'], [ArrayFilterEvent::INSERT_POST_REMOTE_END, 'post_remote_end'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 193ccc77d8..7c124f0b33 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -29,9 +29,9 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::NAV_INFO, 'friendica.data.nav_info'], [ArrayFilterEvent::FEATURE_ENABLED, 'friendica.data.feature_enabled'], [ArrayFilterEvent::FEATURE_GET, 'friendica.data.feature_get'], - [ArrayFilterEvent::POST_LOCAL_START, 'friendica.data.post_local_start'], - [ArrayFilterEvent::POST_LOCAL, 'friendica.data.post_local'], - [ArrayFilterEvent::POST_LOCAL_END, 'friendica.data.post_local_end'], + [ArrayFilterEvent::INSERT_POST_LOCAL_START, 'friendica.data.insert_post_local_start'], + [ArrayFilterEvent::INSERT_POST_LOCAL, 'friendica.data.insert_post_local'], + [ArrayFilterEvent::INSERT_POST_LOCAL_END, 'friendica.data.insert_post_local_end'], [ArrayFilterEvent::INSERT_POST_REMOTE, 'friendica.data.insert_post_remote'], [ArrayFilterEvent::INSERT_POST_REMOTE_END, 'friendica.data.insert_post_remote_end'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'], From 674b6c55def262df89fb21959003e91507a0d95c Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 17 Mar 2025 07:38:53 +0000 Subject: [PATCH 57/91] Fix code style --- src/Console/PoToPhp.php | 10 ++--- .../Introduction/Repository/Introduction.php | 5 ++- .../Repository/UserDefinedChannel.php | 6 +-- src/Content/Post/Entity/PostMedia.php | 7 ++-- src/Content/Post/Repository/PostMedia.php | 2 +- src/Core/Hook.php | 2 +- src/Database/Database.php | 34 ++++++++-------- src/Factory/Api/Mastodon/Attachment.php | 2 +- src/Factory/Api/Twitter/Status.php | 4 +- src/Module/Filer/RemoveTag.php | 2 +- .../Notifications/Repository/Notification.php | 14 +++---- .../ValueObject/Introduction.php | 40 +++++++++---------- .../HTTPClient/Response/CurlResult.php | 6 +-- src/Object/Api/Friendica/Notification.php | 6 +-- src/Object/Api/Mastodon/Field.php | 2 +- .../Diaspora/Repository/DiasporaContact.php | 4 +- .../Repository/PermissionSet.php | 4 +- src/Security/Security.php | 18 +++------ 18 files changed, 81 insertions(+), 87 deletions(-) diff --git a/src/Console/PoToPhp.php b/src/Console/PoToPhp.php index a99cd6e806..480da23c46 100644 --- a/src/Console/PoToPhp.php +++ b/src/Console/PoToPhp.php @@ -134,7 +134,7 @@ HELP; ); $fnname = 'string_plural_select_' . $lang; - $out = 'if(! function_exists("' . $fnname . '")) {' . "\n"; + $out = 'if(! function_exists("' . $fnname . '")) {' . "\n"; $out .= 'function ' . $fnname . '($n){' . "\n"; $out .= ' $n = intval($n);' . "\n"; $out .= ' ' . $return . "\n"; @@ -192,13 +192,13 @@ HELP; if ($q === false || $s < $q) { list($then, $else) = explode(':', $string, 2); - $node['then'] = $then; - $parsedElse = []; + $node['then'] = $then; + $parsedElse = []; self::parse($else, $parsedElse); $node['else'] = $parsedElse; } else { list($if, $thenelse) = explode('?', $string, 2); - $node['if'] = $if; + $node['if'] = $if; self::parse($thenelse, $node); } } @@ -214,7 +214,7 @@ HELP; private static function render($tree): string { if (is_array($tree)) { - $if = trim($tree['if']); + $if = trim($tree['if']); $then = trim($tree['then']); $else = self::render($tree['else']); diff --git a/src/Contact/Introduction/Repository/Introduction.php b/src/Contact/Introduction/Repository/Introduction.php index dec2f2a246..a624017a2a 100644 --- a/src/Contact/Introduction/Repository/Introduction.php +++ b/src/Contact/Introduction/Repository/Introduction.php @@ -83,7 +83,10 @@ class Introduction extends BaseRepository $BaseCollection = parent::_selectByBoundaries( ['`uid` = ? AND NOT `ignore`',$uid], ['order' => ['id' => 'DESC']], - $min_id, $max_id, $limit); + $min_id, + $max_id, + $limit + ); } catch (\Exception $e) { throw new IntroductionPersistenceException(sprintf('Cannot select Introductions for used %d', $uid), $e); } diff --git a/src/Content/Conversation/Repository/UserDefinedChannel.php b/src/Content/Conversation/Repository/UserDefinedChannel.php index b9eecbf53c..b256e34e56 100644 --- a/src/Content/Conversation/Repository/UserDefinedChannel.php +++ b/src/Content/Conversation/Repository/UserDefinedChannel.php @@ -169,14 +169,14 @@ class UserDefinedChannel extends BaseRepository $uids = array_column($users, 'uid'); $usercondition = ['uid' => $uids]; - $condition = DBA::mergeConditions($usercondition, ["`languages` != ? AND `include-tags` = ? AND `full-text-search` = ? AND `circle` = ?", '', '', '', 0]); + $condition = DBA::mergeConditions($usercondition, ["`languages` != ? AND `include-tags` = ? AND `full-text-search` = ? AND `circle` = ?", '', '', '', 0]); foreach ($this->select($condition) as $channel) { if (!empty($channel->languages) && in_array($language, $channel->languages)) { return true; } } - $search = ''; + $search = ''; $condition = DBA::mergeConditions($usercondition, ["`full-text-search` != ? AND `circle` = ? AND `valid`", '', 0]); foreach ($this->select($condition) as $channel) { $search .= '(' . $channel->fullTextSearch . ') '; @@ -201,7 +201,7 @@ class UserDefinedChannel extends BaseRepository { $condition = $this->getUserCondition(); $condition = DBA::mergeConditions($condition, ["`account-type` IN (?, ?) AND `uid` != ?", User::ACCOUNT_TYPE_RELAY, User::ACCOUNT_TYPE_COMMUNITY, 0]); - $users = $this->db->selectToArray('user', ['uid'], $condition); + $users = $this->db->selectToArray('user', ['uid'], $condition); if (empty($users)) { return []; } diff --git a/src/Content/Post/Entity/PostMedia.php b/src/Content/Post/Entity/PostMedia.php index 59d1ec9c57..b06e258710 100644 --- a/src/Content/Post/Entity/PostMedia.php +++ b/src/Content/Post/Entity/PostMedia.php @@ -121,8 +121,7 @@ class PostMedia extends BaseEntity ?UriInterface $publisherImage = null, ?string $blurhash = null, int $id = null - ) - { + ) { $this->uriId = $uriId; $this->url = $url; $this->type = $type; @@ -223,8 +222,8 @@ class PostMedia extends BaseEntity if ($newWidth && $newHeight && $size) { $dimensionts = Images::getScalingDimensions($newWidth, $newHeight, Proxy::getPixelsFromSize($size)); - $newWidth = $dimensionts['width']; - $newHeight = $dimensionts['height']; + $newWidth = $dimensionts['width']; + $newHeight = $dimensionts['height']; } return new self( diff --git a/src/Content/Post/Repository/PostMedia.php b/src/Content/Post/Repository/PostMedia.php index 9d6b09cb5f..d28d15bca7 100644 --- a/src/Content/Post/Repository/PostMedia.php +++ b/src/Content/Post/Repository/PostMedia.php @@ -167,7 +167,7 @@ class PostMedia extends BaseRepository // Peertube videos are delivered in many different resolutions. We pick a moderate one. // Since only Peertube provides a "height" parameter, this wouldn't be executed // when someone for example on Mastodon was sharing multiple videos in a single post. - $heights[$PostMedia->height] = (string)$PostMedia->url; + $heights[$PostMedia->height] = (string)$PostMedia->url; $video[(string) $PostMedia->url] = $PostMedia; } else { $attachments['visual'][] = $PostMedia; diff --git a/src/Core/Hook.php b/src/Core/Hook.php index 8c9f3ba910..555b6b5d9f 100644 --- a/src/Core/Hook.php +++ b/src/Core/Hook.php @@ -40,7 +40,7 @@ class Hook public static function loadHooks() { self::$hooks = []; - $stmt = DBA::select('hook', ['hook', 'file', 'function'], [], ['order' => ['priority' => 'desc', 'file']]); + $stmt = DBA::select('hook', ['hook', 'file', 'function'], [], ['order' => ['priority' => 'desc', 'file']]); while ($hook = DBA::fetch($stmt)) { self::add($hook['hook'], $hook['file'], $hook['function']); diff --git a/src/Database/Database.php b/src/Database/Database.php index 6f42756302..88aa636fd3 100644 --- a/src/Database/Database.php +++ b/src/Database/Database.php @@ -62,15 +62,15 @@ class Database protected $server_info = ''; /** @var PDO|mysqli|null */ protected $connection; - protected $driver = ''; + protected $driver = ''; protected $pdo_emulate_prepares = false; - private $error = ''; - private $errorno = 0; - private $affected_rows = 0; - protected $in_transaction = false; - protected $in_retrial = false; - protected $testmode = false; - private $relation = []; + private $error = ''; + private $errorno = 0; + private $affected_rows = 0; + protected $in_transaction = false; + protected $in_retrial = false; + protected $testmode = false; + private $relation = []; /** @var DbaDefinition */ protected $dbaDefinition; /** @var ViewDefinition */ @@ -86,7 +86,7 @@ class Database $this->viewDefinition = $viewDefinition; // Use dummy values - necessary for the first factory call of the logger itself - $this->logger = new NullLogger(); + $this->logger = new NullLogger(); $this->profiler = new Profiler($config); $this->connect(); @@ -630,7 +630,7 @@ class Database } elseif (is_string($args[$param])) { $param_types .= 's'; } elseif (is_object($args[$param]) && method_exists($args[$param], '__toString')) { - $param_types .= 's'; + $param_types .= 's'; $args[$param] = (string)$args[$param]; } else { $param_types .= 'b'; @@ -677,9 +677,9 @@ class Database } $this->logger->error('DB Error', [ - 'code' => $errorno, - 'error' => $error, - 'params' => $this->replaceParameters($sql, $args), + 'code' => $errorno, + 'error' => $error, + 'params' => $this->replaceParameters($sql, $args), ]); // On a lost connection we try to reconnect - but only once. @@ -784,9 +784,9 @@ class Database } $this->logger->error('DB Error', [ - 'code' => $errorno, - 'error' => $error, - 'params' => $this->replaceParameters($sql, $params), + 'code' => $errorno, + 'error' => $error, + 'params' => $this->replaceParameters($sql, $params), ]); // On a lost connection we simply quit. @@ -1335,7 +1335,7 @@ class Database return true; } - $fields = $this->castFields($table, $fields); + $fields = $this->castFields($table, $fields); $direct_fields = []; foreach ($fields as $key => $value) { diff --git a/src/Factory/Api/Mastodon/Attachment.php b/src/Factory/Api/Mastodon/Attachment.php index bd16b61b38..65eeec22eb 100644 --- a/src/Factory/Api/Mastodon/Attachment.php +++ b/src/Factory/Api/Mastodon/Attachment.php @@ -65,7 +65,7 @@ class Attachment extends BaseFactory * @return \Friendica\Object\Api\Mastodon\Attachment * @throws InternalServerErrorException */ - private function createFromMediaArray(array $attachment): \Friendica\Object\Api\Mastodon\Attachment + private function createFromMediaArray(array $attachment): \Friendica\Object\Api\Mastodon\Attachment { $filetype = !empty($attachment['mimetype']) ? strtolower(substr($attachment['mimetype'], 0, strpos($attachment['mimetype'], '/'))) : ''; diff --git a/src/Factory/Api/Twitter/Status.php b/src/Factory/Api/Twitter/Status.php index b77ee801f7..7d235cc870 100644 --- a/src/Factory/Api/Twitter/Status.php +++ b/src/Factory/Api/Twitter/Status.php @@ -111,7 +111,7 @@ class Status extends BaseFactory */ private function createFromArray(array $item, int $uid, bool $include_entities): \Friendica\Object\Api\Twitter\Status { - $item = Post\Media::addHTMLAttachmentToItem($item); + $item = Post\Media::addHTMLAttachmentToItem($item); $author = $this->twitterUser->createFromContactId($item['author-id'], $uid, true); if (!empty($item['causer-id']) && ($item['post-reason'] == Item::PR_ANNOUNCEMENT)) { @@ -203,6 +203,6 @@ class Status extends BaseFactory $entities = []; } - return new \Friendica\Object\Api\Twitter\Status($text, $statusnetHtml, $friendicaHtml, $item, $author, $owner, $retweeted, $quoted, $geo, $friendica_activities, $entities, $attachments, $friendica_comments, $liked); + return new \Friendica\Object\Api\Twitter\Status($text, $statusnetHtml, $friendicaHtml, $item, $author, $owner, $retweeted, $quoted, $geo, $friendica_activities, $entities, $attachments, $friendica_comments, $liked); } } diff --git a/src/Module/Filer/RemoveTag.php b/src/Module/Filer/RemoveTag.php index 28666c8a44..eb20efe0bb 100644 --- a/src/Module/Filer/RemoveTag.php +++ b/src/Module/Filer/RemoveTag.php @@ -71,7 +71,7 @@ class RemoveTag extends BaseModule $item_id = $this->parameters['id'] ?? 0; $term = trim($request['term'] ?? ''); - $cat = trim($request['cat'] ?? ''); + $cat = trim($request['cat'] ?? ''); if (!empty($cat)) { $type = Post\Category::CATEGORY; diff --git a/src/Navigation/Notifications/Repository/Notification.php b/src/Navigation/Notifications/Repository/Notification.php index 49703bc1f9..85c8895135 100644 --- a/src/Navigation/Notifications/Repository/Notification.php +++ b/src/Navigation/Notifications/Repository/Notification.php @@ -127,23 +127,23 @@ class Notification extends BaseRepository $values = [$uid]; $type_condition = ''; - $notify_type = $this->pconfig->get($uid, 'system', 'notify_type'); + $notify_type = $this->pconfig->get($uid, 'system', 'notify_type'); if (!is_null($notify_type)) { $type_condition = 'AND `type` & ? != 0'; - $values[] = $notify_type | UserNotification::TYPE_SHARED | UserNotification::TYPE_FOLLOW; + $values[] = $notify_type | UserNotification::TYPE_SHARED | UserNotification::TYPE_FOLLOW; } $like_condition = ''; if (!$this->pconfig->get($uid, 'system', 'notify_like')) { $like_condition = 'AND NOT `vid` IN (?, ?)'; - $values[] = Verb::getID(Activity::LIKE); - $values[] = Verb::getID(Activity::DISLIKE); + $values[] = Verb::getID(Activity::LIKE); + $values[] = Verb::getID(Activity::DISLIKE); } $announce_condition = ''; if (!$this->pconfig->get($uid, 'system', 'notify_announce')) { $announce_condition = 'AND vid != ?'; - $values[] = Verb::getID(Activity::ANNOUNCE); + $values[] = Verb::getID(Activity::ANNOUNCE); } $rows = $this->db->p(" @@ -253,12 +253,12 @@ class Notification extends BaseRepository public function deleteForItem(int $itemUriId): bool { $conditionTarget = [ - 'vid' => Verb::getID(Activity::POST), + 'vid' => Verb::getID(Activity::POST), 'target-uri-id' => $itemUriId, ]; $conditionParent = [ - 'vid' => Verb::getID(Activity::POST), + 'vid' => Verb::getID(Activity::POST), 'parent-uri-id' => $itemUriId, ]; diff --git a/src/Navigation/Notifications/ValueObject/Introduction.php b/src/Navigation/Notifications/ValueObject/Introduction.php index 6e2c24d340..36e490d0be 100644 --- a/src/Navigation/Notifications/ValueObject/Introduction.php +++ b/src/Navigation/Notifications/ValueObject/Introduction.php @@ -63,30 +63,30 @@ class Introduction implements \JsonSerializable public function __construct(array $data = []) { - $this->label = $data['label'] ?? ''; - $this->type = $data['str_type'] ?? ''; - $this->intro_id = $data['intro_id'] ?? -1; - $this->madeBy = $data['madeBy'] ?? ''; - $this->madeByUrl = $data['madeByUrl'] ?? ''; - $this->madeByZrl = $data['madeByZrl'] ?? ''; - $this->madeByAddr = $data['madeByAddr'] ?? ''; - $this->contactId = $data['contactId'] ?? -1; - $this->photo = $data['photo'] ?? ''; - $this->name = $data['name'] ?? ''; - $this->url = $data['url'] ?? ''; - $this->zrl = $data['zrl'] ?? ''; - $this->hidden = $data['hidden'] ?? false; + $this->label = $data['label'] ?? ''; + $this->type = $data['str_type'] ?? ''; + $this->intro_id = $data['intro_id'] ?? -1; + $this->madeBy = $data['madeBy'] ?? ''; + $this->madeByUrl = $data['madeByUrl'] ?? ''; + $this->madeByZrl = $data['madeByZrl'] ?? ''; + $this->madeByAddr = $data['madeByAddr'] ?? ''; + $this->contactId = $data['contactId'] ?? -1; + $this->photo = $data['photo'] ?? ''; + $this->name = $data['name'] ?? ''; + $this->url = $data['url'] ?? ''; + $this->zrl = $data['zrl'] ?? ''; + $this->hidden = $data['hidden'] ?? false; $this->postNewFriend = $data['postNewFriend'] ?? ''; - $this->knowYou = $data['knowYou'] ?? false; - $this->note = $data['note'] ?? ''; - $this->request = $data['request'] ?? ''; + $this->knowYou = $data['knowYou'] ?? false; + $this->note = $data['note'] ?? ''; + $this->request = $data['request'] ?? ''; $this->dfrnId = -1; - $this->addr = $data['addr'] ?? ''; - $this->network = $data['network'] ?? ''; - $this->uid = $data['uid'] ?? -1; + $this->addr = $data['addr'] ?? ''; + $this->network = $data['network'] ?? ''; + $this->uid = $data['uid'] ?? -1; $this->keywords = $data['keywords'] ?? ''; $this->location = $data['location'] ?? ''; - $this->about = $data['about'] ?? ''; + $this->about = $data['about'] ?? ''; } public function getLabel(): string diff --git a/src/Network/HTTPClient/Response/CurlResult.php b/src/Network/HTTPClient/Response/CurlResult.php index 30b8be3830..a38de01336 100644 --- a/src/Network/HTTPClient/Response/CurlResult.php +++ b/src/Network/HTTPClient/Response/CurlResult.php @@ -225,11 +225,11 @@ class CurlResult implements ICanHandleHttpResponses } } - $this->redirectUrl = (string)Uri::fromParts((array)$redirect_parts); - $this->isRedirectUrl = true; + $this->redirectUrl = (string)Uri::fromParts((array)$redirect_parts); + $this->isRedirectUrl = true; $this->redirectIsPermanent = $this->returnCode == 301 || $this->returnCode == 308; } else { - $this->isRedirectUrl = false; + $this->isRedirectUrl = false; $this->redirectIsPermanent = false; } } diff --git a/src/Object/Api/Friendica/Notification.php b/src/Object/Api/Friendica/Notification.php index f83cd9cc2c..2a49ea770c 100644 --- a/src/Object/Api/Friendica/Notification.php +++ b/src/Object/Api/Friendica/Notification.php @@ -84,15 +84,15 @@ class Notification extends BaseDataTransferObject $this->date_rel = Temporal::getRelativeDate($this->date); try { - $this->msg_html = BBCode::convertForUriId($notify->uriId, $this->msg, BBCode::EXTERNAL); + $this->msg_html = BBCode::convertForUriId($notify->uriId, $this->msg, BBCode::EXTERNAL); } catch (\Exception $e) { - $this->msg_html = ''; + $this->msg_html = ''; } try { $this->msg_plain = explode("\n", trim(HTML::toPlaintext($this->msg_html, 0)))[0]; } catch (\Exception $e) { - $this->msg_plain = ''; + $this->msg_plain = ''; } } } diff --git a/src/Object/Api/Mastodon/Field.php b/src/Object/Api/Mastodon/Field.php index 846aac4d0f..092f33b361 100644 --- a/src/Object/Api/Mastodon/Field.php +++ b/src/Object/Api/Mastodon/Field.php @@ -25,7 +25,7 @@ class Field extends BaseDataTransferObject public function __construct(string $name, string $value) { - $this->name = $name; + $this->name = $name; $this->value = $value; // Link verification unsupported $this->verified_at = null; diff --git a/src/Protocol/Diaspora/Repository/DiasporaContact.php b/src/Protocol/Diaspora/Repository/DiasporaContact.php index 6d92b066f8..5cf05b8aa0 100644 --- a/src/Protocol/Diaspora/Repository/DiasporaContact.php +++ b/src/Protocol/Diaspora/Repository/DiasporaContact.php @@ -245,8 +245,8 @@ class DiasporaContact extends BaseRepository $uriId, new DateTime($contact['created'] ?? 'now', new DateTimeZone('UTC')), $interacting_count ?? 0, - $interacted_count ?? 0, - $post_count ?? 0 + $interacted_count ?? 0, + $post_count ?? 0 ); $DiasporaContact = $this->save($DiasporaContact); diff --git a/src/Security/PermissionSet/Repository/PermissionSet.php b/src/Security/PermissionSet/Repository/PermissionSet.php index c77baf0f2e..42b6219e9c 100644 --- a/src/Security/PermissionSet/Repository/PermissionSet.php +++ b/src/Security/PermissionSet/Repository/PermissionSet.php @@ -119,8 +119,8 @@ class PermissionSet extends BaseRepository $circle_ids = []; if (!empty($user_contact_str) && $this->db->exists('contact', [ - 'id' => $cid, - 'uid' => $uid, + 'id' => $cid, + 'uid' => $uid, 'blocked' => false ])) { $circle_ids = Circle::getIdsByContactId($cid); diff --git a/src/Security/Security.php b/src/Security/Security.php index 9056596f27..f04af42061 100644 --- a/src/Security/Security.php +++ b/src/Security/Security.php @@ -79,33 +79,25 @@ class Security */ public static function getPermissionsSQLByUserId(int $owner_id, bool $accessible = false) { - $local_user = DI::userSession()->getLocalUserId(); + $local_user = DI::userSession()->getLocalUserId(); $remote_contact = DI::userSession()->getRemoteContactID($owner_id); - $acc_sql = ''; + $acc_sql = ''; if ($accessible) { $acc_sql = ' OR `accessible`'; } - /* - * Construct permissions - * - * default permissions - anonymous user - */ + // Construct permissions: default permissions - anonymous user $sql = " AND (allow_cid = '' AND allow_gid = '' AND deny_cid = '' AND deny_gid = ''" . $acc_sql . ") "; - /* - * Profile owner - everything is visible - */ if ($local_user && $local_user == $owner_id) { + // Profile owner - everything is visible $sql = ''; - /* - * Authenticated visitor. Load the circles the visitor belongs to. - */ } elseif ($remote_contact) { + // Authenticated visitor. Load the circles the visitor belongs to. $circleIds = '<<>>'; // should be impossible to match foreach (Circle::getIdsByContactId($remote_contact) as $circleId) { From d48e491144e8a5fd59a7d811923e9ac2774c6b1d Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 17 Mar 2025 08:26:45 +0000 Subject: [PATCH 58/91] Create events for prepare_body hooks --- src/Core/Hooks/HookEventBridge.php | 22 +++++++++ src/Event/ArrayFilterEvent.php | 20 +++++++++ src/Model/Item.php | 45 ++++++++++++++----- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 29 ++++++++++++ tests/Unit/Event/ArrayFilterEventTest.php | 4 ++ 5 files changed, 108 insertions(+), 12 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 251c462929..8d53df417f 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -48,6 +48,10 @@ final class HookEventBridge ArrayFilterEvent::INSERT_POST_LOCAL_END => 'post_local_end', ArrayFilterEvent::INSERT_POST_REMOTE => 'post_remote', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'post_remote_end', + ArrayFilterEvent::PREPARE_POST_START => 'prepare_body_init', + ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT => 'prepare_body_content_filter', + ArrayFilterEvent::PREPARE_POST => 'prepare_body', + ArrayFilterEvent::PREPARE_POST_END => 'prepare_body_final', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'photo_upload_form', ArrayFilterEvent::NETWORK_TO_NAME => 'network_to_name', ArrayFilterEvent::CONVERSATION_START => 'conversation_start', @@ -106,6 +110,10 @@ final class HookEventBridge ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', + ArrayFilterEvent::PREPARE_POST_START => 'onPreparePostStartEvent', + ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT => 'onArrayFilterEvent', + ArrayFilterEvent::PREPARE_POST => 'onArrayFilterEvent', + ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', @@ -163,6 +171,20 @@ final class HookEventBridge ); } + /** + * Map the PREPARE_POST_START event to `prepare_body_init` hook + */ + public static function onPreparePostStartEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $item = (array) $data['item'] ?? []; + + $data['item'] = static::callHook($event->getName(), $item); + + $event->setArray($data); + } + /** * Map the OEMBED_FETCH_END event to `oembed_fetch_url` hook */ diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 51719e7de9..f29acad952 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -34,6 +34,26 @@ final class ArrayFilterEvent extends Event public const INSERT_POST_REMOTE_END = 'friendica.data.insert_post_remote_end'; + /** + * item array before any work + */ + public const PREPARE_POST_START = 'friendica.data.prepare_post_start'; + + /** + * before first bbcode to html + */ + public const PREPARE_POST_FILTER_CONTENT = 'friendica.data.prepare_post_filter_content'; + + /** + * after first bbcode to html + */ + public const PREPARE_POST = 'friendica.data.prepare_post'; + + /** + * after attach icons and blockquote special case handling (spoiler, author) + */ + public const PREPARE_POST_END = 'friendica.data.prepare_post_end'; + public const PHOTO_UPLOAD_FORM = 'friendica.data.photo_upload_form'; public const NETWORK_TO_NAME = 'friendica.data.network_to_name'; diff --git a/src/Model/Item.php b/src/Model/Item.php index d2169d3156..6c8be7528e 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3058,16 +3058,22 @@ class Item * @return string item body html * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException - * @hook prepare_body_init item array before any work - * @hook prepare_body_content_filter ('item'=>item array, 'filter_reasons'=>string array) before first bbcode to html - * @hook prepare_body ('item'=>item array, 'html'=>body string, 'is_preview'=>boolean, 'filter_reasons'=>string array) after first bbcode to html - * @hook prepare_body_final ('item'=>item array, 'html'=>body string) after attach icons and blockquote special case handling (spoiler, author) */ public static function prepareBody(array &$item, bool $attach = false, bool $is_preview = false, bool $only_cache = false): string { - $appHelper = DI::appHelper(); - $uid = DI::userSession()->getLocalUserId(); - Hook::callAll('prepare_body_init', $item); + $appHelper = DI::appHelper(); + $uid = DI::userSession()->getLocalUserId(); + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = [ + 'item' => $item, + ]; + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PREPARE_POST_START, $hook_data), + )->getArray(); + + $item = $hook_data['item'] ?? $item; // In order to provide theme developers more possibilities, event items // are treated differently. @@ -3186,7 +3192,11 @@ class Item 'item' => $item, 'filter_reasons' => $filter_reasons ]; - Hook::callAll('prepare_body_content_filter', $hook_data); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT, $hook_data), + )->getArray(); + $filter_reasons = $hook_data['filter_reasons']; unset($hook_data); } @@ -3205,7 +3215,11 @@ class Item 'preview' => $is_preview, 'filter_reasons' => $filter_reasons ]; - Hook::callAll('prepare_body', $hook_data); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PREPARE_POST, $hook_data), + )->getArray(); + $s = $hook_data['html']; unset($hook_data); @@ -3257,9 +3271,16 @@ class Item $s = HTML::applyContentFilter($s, $filter_reasons); - $hook_data = ['item' => $item, 'html' => $s]; - Hook::callAll('prepare_body_final', $hook_data); - return $hook_data['html']; + $hook_data = [ + 'item' => $item, + 'html' => $s, + ]; + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PREPARE_POST_END, $hook_data), + )->getArray(); + + return (string) $hook_data['html'] ?? $s; } /** diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 325aefb742..17291539a7 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -37,6 +37,10 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', + ArrayFilterEvent::PREPARE_POST_START => 'onPreparePostStartEvent', + ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT => 'onArrayFilterEvent', + ArrayFilterEvent::PREPARE_POST => 'onArrayFilterEvent', + ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', @@ -183,6 +187,28 @@ class HookEventBridgeTest extends TestCase HookEventBridge::onCollectRoutesEvent($event); } + public function testOnPreparePostStartEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::PREPARE_POST_START, ['item' => ['id' => -1]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, array $data): array { + $this->assertSame('prepare_body_init', $name); + $this->assertSame(['id' => -1], $data); + + return ['id' => 123]; + }); + + HookEventBridge::onPreparePostStartEvent($event); + + $this->assertSame( + ['item' => ['id' => 123]], + $event->getArray(), + ); + } + public function testOnOembedFetchEndEventCallsHookWithCorrectValue(): void { $event = new ArrayFilterEvent(ArrayFilterEvent::OEMBED_FETCH_END, ['url' => 'original_url']); @@ -318,6 +344,9 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::INSERT_POST_LOCAL_END, 'post_local_end'], [ArrayFilterEvent::INSERT_POST_REMOTE, 'post_remote'], [ArrayFilterEvent::INSERT_POST_REMOTE_END, 'post_remote_end'], + [ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT, 'prepare_body_content_filter'], + [ArrayFilterEvent::PREPARE_POST, 'prepare_body'], + [ArrayFilterEvent::PREPARE_POST_END, 'prepare_body_final'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'conversation_start'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 7c124f0b33..5af49e9fb8 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -34,6 +34,10 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::INSERT_POST_LOCAL_END, 'friendica.data.insert_post_local_end'], [ArrayFilterEvent::INSERT_POST_REMOTE, 'friendica.data.insert_post_remote'], [ArrayFilterEvent::INSERT_POST_REMOTE_END, 'friendica.data.insert_post_remote_end'], + [ArrayFilterEvent::PREPARE_POST_START, 'friendica.data.prepare_post_start'], + [ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT, 'friendica.data.prepare_post_filter_content'], + [ArrayFilterEvent::PREPARE_POST, 'friendica.data.prepare_post'], + [ArrayFilterEvent::PREPARE_POST_END, 'friendica.data.prepare_post_end'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'], From 84148663e265ac2400b6dd6af23c5ed0fca5412f Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 17 Mar 2025 09:17:13 +0000 Subject: [PATCH 59/91] Create event for detect_languages hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Model/Item.php | 11 ++++++++--- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 8d53df417f..2406fb7037 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -56,6 +56,7 @@ final class HookEventBridge ArrayFilterEvent::NETWORK_TO_NAME => 'network_to_name', ArrayFilterEvent::CONVERSATION_START => 'conversation_start', ArrayFilterEvent::DISPLAY_ITEM => 'display_item', + ArrayFilterEvent::DETECT_LANGUAGES => 'detect_languages', ArrayFilterEvent::RENDER_LOCATION => 'render_location', ArrayFilterEvent::ITEM_PHOTO_MENU => 'item_photo_menu', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'contact_photo_menu', @@ -118,6 +119,7 @@ final class HookEventBridge ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', + ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index f29acad952..44aa403b18 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -62,6 +62,8 @@ final class ArrayFilterEvent extends Event public const DISPLAY_ITEM = 'friendica.data.display_item'; + public const DETECT_LANGUAGES = 'friendica.data.detect_languages'; + public const RENDER_LOCATION = 'friendica.data.render_location'; public const ITEM_PHOTO_MENU = 'friendica.data.item_photo_menu'; diff --git a/src/Model/Item.php b/src/Model/Item.php index 6c8be7528e..954c0ce11c 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -1903,18 +1903,23 @@ class Item $result = []; + $eventDispatcher = DI::eventDispatcher(); + foreach (self::splitByBlocks($searchtext) as $block) { $languages = $ld->detect($block)->close() ?: []; - $data = [ + $hook_data = [ 'text' => $block, 'detected' => $languages, 'uri-id' => $uri_id, 'author-id' => $author_id, ]; - Hook::callAll('detect_languages', $data); - foreach ($data['detected'] as $language => $quality) { + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::DETECT_LANGUAGES, $hook_data), + )->getArray(); + + foreach ($hook_data['detected'] as $language => $quality) { $result[$language] = max($result[$language] ?? 0, $quality * (strlen($block) / strlen($searchtext))); } } diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 17291539a7..e0e9a3eb8e 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -45,6 +45,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', + ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', @@ -351,6 +352,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'conversation_start'], [ArrayFilterEvent::DISPLAY_ITEM, 'display_item'], + [ArrayFilterEvent::DETECT_LANGUAGES, 'detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 5af49e9fb8..d079cacdec 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -42,6 +42,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'], [ArrayFilterEvent::DISPLAY_ITEM, 'friendica.data.display_item'], + [ArrayFilterEvent::DETECT_LANGUAGES, 'friendica.data.detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'friendica.data.item_photo_menu'], [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'friendica.data.contact_photo_menu'], From 4a1a1d3ca3eef458fd6f9db6ce93f26859e45268 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 17 Mar 2025 09:29:49 +0000 Subject: [PATCH 60/91] create event for tagged hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Model/Item.php | 11 +++++++++-- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 2406fb7037..95ecad13bf 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -55,6 +55,7 @@ final class HookEventBridge ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'photo_upload_form', ArrayFilterEvent::NETWORK_TO_NAME => 'network_to_name', ArrayFilterEvent::CONVERSATION_START => 'conversation_start', + ArrayFilterEvent::ITEM_TAGGED => 'tagged', ArrayFilterEvent::DISPLAY_ITEM => 'display_item', ArrayFilterEvent::DETECT_LANGUAGES => 'detect_languages', ArrayFilterEvent::RENDER_LOCATION => 'render_location', @@ -118,6 +119,7 @@ final class HookEventBridge ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', + ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 44aa403b18..84c1d4cff6 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -60,6 +60,8 @@ final class ArrayFilterEvent extends Event public const CONVERSATION_START = 'friendica.data.conversation_start'; + public const ITEM_TAGGED = 'friendica.data.item_tagged'; + public const DISPLAY_ITEM = 'friendica.data.display_item'; public const DETECT_LANGUAGES = 'friendica.data.detect_languages'; diff --git a/src/Model/Item.php b/src/Model/Item.php index 954c0ce11c..9be9f2b27a 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -2285,9 +2285,16 @@ class Item return true; } - $arr = ['item' => $item, 'user' => $owner]; + $eventDispatcher = DI::eventDispatcher(); - Hook::callAll('tagged', $arr); + $arr = [ + 'item' => $item, + 'user' => $owner, + ]; + + $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ITEM_TAGGED, $arr), + ); } else { if (Tag::isMentioned($item['parent-uri-id'], $owner['url'])) { DI::logger()->info('Mention found in parent tag.', ['uri' => $item['uri'], 'uid' => $uid, 'id' => $item_id, 'uri-id' => $item['uri-id'], 'guid' => $item['guid']]); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index e0e9a3eb8e..ac33ba4280 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -44,6 +44,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', + ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', @@ -351,6 +352,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'conversation_start'], + [ArrayFilterEvent::ITEM_TAGGED, 'tagged'], [ArrayFilterEvent::DISPLAY_ITEM, 'display_item'], [ArrayFilterEvent::DETECT_LANGUAGES, 'detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index d079cacdec..806e8ad014 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -41,6 +41,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'], + [ArrayFilterEvent::ITEM_TAGGED, 'friendica.data.item_tagged'], [ArrayFilterEvent::DISPLAY_ITEM, 'friendica.data.display_item'], [ArrayFilterEvent::DETECT_LANGUAGES, 'friendica.data.detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'], From 2276bdcd7e7c32c09db3c6b5003c93acf071789b Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 17 Mar 2025 09:40:27 +0000 Subject: [PATCH 61/91] Create event for put_item_in_cache hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Model/Item.php | 14 ++++++++++++-- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 95ecad13bf..f59a267230 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -57,6 +57,7 @@ final class HookEventBridge ArrayFilterEvent::CONVERSATION_START => 'conversation_start', ArrayFilterEvent::ITEM_TAGGED => 'tagged', ArrayFilterEvent::DISPLAY_ITEM => 'display_item', + ArrayFilterEvent::CACHE_ITEM => 'put_item_in_cache', ArrayFilterEvent::DETECT_LANGUAGES => 'detect_languages', ArrayFilterEvent::RENDER_LOCATION => 'render_location', ArrayFilterEvent::ITEM_PHOTO_MENU => 'item_photo_menu', @@ -121,6 +122,7 @@ final class HookEventBridge ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', + ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 84c1d4cff6..db57babfda 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -64,6 +64,8 @@ final class ArrayFilterEvent extends Event public const DISPLAY_ITEM = 'friendica.data.display_item'; + public const CACHE_ITEM = 'friendica.data.cache_item'; + public const DETECT_LANGUAGES = 'friendica.data.detect_languages'; public const RENDER_LOCATION = 'friendica.data.render_location'; diff --git a/src/Model/Item.php b/src/Model/Item.php index 9be9f2b27a..d93ab1768d 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3038,8 +3038,18 @@ class Item $item['rendered-html'] = BBCode::convertForUriId($item['uri-id'], $item['body']); $item['rendered-hash'] = hash('md5', BBCode::VERSION . '::' . $body); - $hook_data = ['item' => $item, 'rendered-html' => $item['rendered-html'], 'rendered-hash' => $item['rendered-hash']]; - Hook::callAll('put_item_in_cache', $hook_data); + $hook_data = [ + 'rendered-html' => $item['rendered-html'], + 'rendered-hash' => $item['rendered-hash'], + 'item' => $item, + ]; + + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::CACHE_ITEM, $hook_data), + )->getArray(); + $item['rendered-html'] = $hook_data['rendered-html']; $item['rendered-hash'] = $hook_data['rendered-hash']; unset($hook_data); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index ac33ba4280..0e4afb2448 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -46,6 +46,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', + ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', @@ -354,6 +355,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::CONVERSATION_START, 'conversation_start'], [ArrayFilterEvent::ITEM_TAGGED, 'tagged'], [ArrayFilterEvent::DISPLAY_ITEM, 'display_item'], + [ArrayFilterEvent::CACHE_ITEM, 'put_item_in_cache'], [ArrayFilterEvent::DETECT_LANGUAGES, 'detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 806e8ad014..e087856178 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -43,6 +43,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'], [ArrayFilterEvent::ITEM_TAGGED, 'friendica.data.item_tagged'], [ArrayFilterEvent::DISPLAY_ITEM, 'friendica.data.display_item'], + [ArrayFilterEvent::CACHE_ITEM, 'friendica.data.cache_item'], [ArrayFilterEvent::DETECT_LANGUAGES, 'friendica.data.detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'friendica.data.item_photo_menu'], From ac8ca35b2b078ead4143170df8220a258d1c5b48 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 17 Mar 2025 10:52:37 +0000 Subject: [PATCH 62/91] Create event for item_by_link hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Model/Item.php | 15 +++++++++------ tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index f59a267230..83a075c7d5 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -55,6 +55,7 @@ final class HookEventBridge ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'photo_upload_form', ArrayFilterEvent::NETWORK_TO_NAME => 'network_to_name', ArrayFilterEvent::CONVERSATION_START => 'conversation_start', + ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'item_by_link', ArrayFilterEvent::ITEM_TAGGED => 'tagged', ArrayFilterEvent::DISPLAY_ITEM => 'display_item', ArrayFilterEvent::CACHE_ITEM => 'put_item_in_cache', @@ -120,6 +121,7 @@ final class HookEventBridge ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', + ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index db57babfda..ee36b2d983 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -60,6 +60,8 @@ final class ArrayFilterEvent extends Event public const CONVERSATION_START = 'friendica.data.conversation_start'; + public const FETCH_ITEM_BY_LINK = 'friendica.data.fetch_item_by_link'; + public const ITEM_TAGGED = 'friendica.data.item_tagged'; public const DISPLAY_ITEM = 'friendica.data.display_item'; diff --git a/src/Model/Item.php b/src/Model/Item.php index d93ab1768d..3edd6950e7 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -14,7 +14,6 @@ use Friendica\Content\Post\Collection\PostMedias; use Friendica\Content\Post\Entity\PostMedia; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Renderer; @@ -3951,17 +3950,21 @@ class Item return 0; } - $hookData = [ + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = [ 'uri' => $uri, 'uid' => $uid, 'item_id' => null, ]; - Hook::callAll('item_by_link', $hookData); + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::FETCH_ITEM_BY_LINK, $hook_data) + )->getArray(); - if (isset($hookData['item_id'])) { - DI::logger()->info('Hook link fetched', ['uid' => $uid, 'uri' => $uri, 'id' => $hookData['item_id']]); - return is_numeric($hookData['item_id']) ? $hookData['item_id'] : 0; + if (isset($hook_data['item_id'])) { + DI::logger()->info('Hook link fetched', ['uid' => $uid, 'uri' => $uri, 'id' => $hook_data['item_id']]); + return is_numeric($hook_data['item_id']) ? $hook_data['item_id'] : 0; } if (!$mimetype) { diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 0e4afb2448..c6b7ac7a5c 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -44,6 +44,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', + ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent', @@ -353,6 +354,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'conversation_start'], + [ArrayFilterEvent::FETCH_ITEM_BY_LINK, 'item_by_link'], [ArrayFilterEvent::ITEM_TAGGED, 'tagged'], [ArrayFilterEvent::DISPLAY_ITEM, 'display_item'], [ArrayFilterEvent::CACHE_ITEM, 'put_item_in_cache'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index e087856178..7a72faf758 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -41,6 +41,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'], [ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'], + [ArrayFilterEvent::FETCH_ITEM_BY_LINK, 'friendica.data.fetch_item_by_link'], [ArrayFilterEvent::ITEM_TAGGED, 'friendica.data.item_tagged'], [ArrayFilterEvent::DISPLAY_ITEM, 'friendica.data.display_item'], [ArrayFilterEvent::CACHE_ITEM, 'friendica.data.cache_item'], From 59359f7d9d4341732844668f8c942c1e4d3da951 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 17 Mar 2025 12:20:25 +0000 Subject: [PATCH 63/91] Create hook for profile_sidebar hooks --- src/Core/Hooks/HookEventBridge.php | 18 +++++++++++ src/Event/ArrayFilterEvent.php | 4 +++ src/Model/Profile.php | 30 ++++++++++++++----- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 26 ++++++++++++++++ tests/Unit/Event/ArrayFilterEventTest.php | 2 ++ 5 files changed, 72 insertions(+), 8 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 83a075c7d5..e287cdd767 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -63,6 +63,8 @@ final class HookEventBridge ArrayFilterEvent::RENDER_LOCATION => 'render_location', ArrayFilterEvent::ITEM_PHOTO_MENU => 'item_photo_menu', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'contact_photo_menu', + ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'profile_sidebar_enter', + ArrayFilterEvent::PROFILE_SIDEBAR => 'profile_sidebar', ArrayFilterEvent::OEMBED_FETCH_END => 'oembed_fetch_url', ArrayFilterEvent::PAGE_INFO => 'page_info_data', ArrayFilterEvent::SMILEY_LIST => 'smilie', @@ -129,6 +131,8 @@ final class HookEventBridge ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', + ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', + ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', @@ -193,6 +197,20 @@ final class HookEventBridge $event->setArray($data); } + /** + * Map the PROFILE_SIDEBAR_ENTRY event to `profile_sidebar_enter` hook + */ + public static function onProfileSidebarEntryEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $profile = (array) $data['profile'] ?? []; + + $data['profile'] = static::callHook($event->getName(), $profile); + + $event->setArray($data); + } + /** * Map the OEMBED_FETCH_END event to `oembed_fetch_url` hook */ diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index ee36b2d983..12105decc9 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -76,6 +76,10 @@ final class ArrayFilterEvent extends Event public const CONTACT_PHOTO_MENU = 'friendica.data.contact_photo_menu'; + public const PROFILE_SIDEBAR_ENTRY = 'friendica.data.profile_sidebar_entry'; + + public const PROFILE_SIDEBAR = 'friendica.data.profile_sidebar'; + public const OEMBED_FETCH_END = 'friendica.data.oembed_fetch_end'; public const PAGE_INFO = 'friendica.data.page_info'; diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 8217b2a96a..7a900b9bc4 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -19,6 +19,7 @@ use Friendica\Core\Search; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Network\HTTPException; use Friendica\Protocol\Activity; use Friendica\Protocol\Diaspora; @@ -258,11 +259,6 @@ class Profile * @throws \Friendica\Network\HTTPException\InternalServerErrorException * @throws \ImagickException * @note Returns empty string if passed $profile is wrong type or not populated - * - * @hooks 'profile_sidebar_enter' - * array $profile - profile data - * @hooks 'profile_sidebar' - * array $arr */ public static function getVCardHtml(array $profile, bool $block, bool $show_contacts): string { @@ -282,7 +278,17 @@ class Profile $profile['network_link'] = ''; - Hook::callAll('profile_sidebar_enter', $profile); + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = [ + 'profile' => $profile, + ]; + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, $hook_data), + )->getArray(); + + $profile = $hook_data['profile'] ?? $profile; $profile_url = $profile['url']; @@ -473,9 +479,17 @@ class Profile '$network_url' => $network_url, ]); - $arr = ['profile' => &$profile, 'entry' => &$o]; + $hook_data = [ + 'profile' => &$profile, + 'entry' => &$o, + ]; - Hook::callAll('profile_sidebar', $arr); + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PROFILE_SIDEBAR, $hook_data), + )->getArray(); + + $profile = $hook_data['profile'] ?? $profile; + $o = $hook_data['entry'] ?? $o; return $o; } diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index c6b7ac7a5c..1a28e09161 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -52,6 +52,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', + ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', + ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', @@ -213,6 +215,28 @@ class HookEventBridgeTest extends TestCase ); } + public function testOnProfileSidebarEntryEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, ['profile' => ['uid' => 0, 'name' => 'original']]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, array $data): array { + $this->assertSame('profile_sidebar_enter', $name); + $this->assertSame(['uid' => 0, 'name' => 'original'], $data); + + return ['uid' => 0, 'name' => 'changed']; + }); + + HookEventBridge::onProfileSidebarEntryEvent($event); + + $this->assertSame( + ['profile' => ['uid' => 0, 'name' => 'changed']], + $event->getArray(), + ); + } + public function testOnOembedFetchEndEventCallsHookWithCorrectValue(): void { $event = new ArrayFilterEvent(ArrayFilterEvent::OEMBED_FETCH_END, ['url' => 'original_url']); @@ -362,6 +386,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'], + [ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, 'profile_sidebar_enter'], + [ArrayFilterEvent::PROFILE_SIDEBAR, 'profile_sidebar'], [ArrayFilterEvent::PAGE_INFO, 'page_info_data'], [ArrayFilterEvent::SMILEY_LIST, 'smilie'], [ArrayFilterEvent::JOT_NETWORKS, 'jot_networks'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 7a72faf758..85d90ba132 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -49,6 +49,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'friendica.data.item_photo_menu'], [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'friendica.data.contact_photo_menu'], + [ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, 'friendica.data.profile_sidebar_entry'], + [ArrayFilterEvent::PROFILE_SIDEBAR, 'friendica.data.profile_sidebar'], [ArrayFilterEvent::OEMBED_FETCH_END, 'friendica.data.oembed_fetch_end'], [ArrayFilterEvent::PAGE_INFO, 'friendica.data.page_info'], [ArrayFilterEvent::SMILEY_LIST, 'friendica.data.smiley_list'], From 1ddd5674e1993b1dff129aac10fe936f7f23280c Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 17 Mar 2025 13:08:20 +0000 Subject: [PATCH 64/91] Wrap item in INSERT_POST_LOCAL in separate array --- mod/item.php | 10 ++++++-- src/Core/Hooks/HookEventBridge.php | 16 ++++++++++++- src/Model/Item.php | 10 ++++++-- src/Model/Profile.php | 1 - tests/Unit/Core/Hooks/HookEventBridgeTest.php | 24 ++++++++++++++++++- 5 files changed, 54 insertions(+), 7 deletions(-) diff --git a/mod/item.php b/mod/item.php index e6b2cb93f4..e416126a4a 100644 --- a/mod/item.php +++ b/mod/item.php @@ -281,10 +281,16 @@ function item_process(array $post, array $request, bool $preview, string $return $eventDispatcher = DI::eventDispatcher(); - $post = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, $post) + $hook_data = [ + 'item' => $post, + ]; + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, $hook_data) )->getArray(); + $post = $hook_data['item'] ?? $post; + unset($post['edit']); unset($post['self']); unset($post['api_source']); diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index e287cdd767..e5a7dd01ab 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -112,7 +112,7 @@ final class HookEventBridge ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent', - ArrayFilterEvent::INSERT_POST_LOCAL => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL => 'onInsertPostLocalEvent', ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', @@ -183,6 +183,20 @@ final class HookEventBridge ); } + /** + * Map the INSERT_POST_LOCAL event to `post_local` hook + */ + public static function onInsertPostLocalEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $item = (array) $data['item'] ?? []; + + $data['item'] = static::callHook($event->getName(), $item); + + $event->setArray($data); + } + /** * Map the PREPARE_POST_START event to `prepare_body_init` hook */ diff --git a/src/Model/Item.php b/src/Model/Item.php index 3edd6950e7..651b812f3d 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -845,10 +845,16 @@ class Item $dummy_session = false; } - $item = $eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, $item) + $hook_data = [ + 'item' => $item, + ]; + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, $hook_data) )->getArray(); + $item = $hook_data['item'] ?? $item; + if ($dummy_session) { unset($_SESSION['authenticated']); unset($_SESSION['uid']); diff --git a/src/Model/Profile.php b/src/Model/Profile.php index 7a900b9bc4..a647a58c78 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -12,7 +12,6 @@ use Friendica\AppHelper; use Friendica\Content\Text\BBCode; use Friendica\Content\Widget\ContactBlock; use Friendica\Core\Cache\Enum\Duration; -use Friendica\Core\Hook; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Search; diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 1a28e09161..17f9e1084d 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -33,7 +33,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent', - ArrayFilterEvent::INSERT_POST_LOCAL => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL => 'onInsertPostLocalEvent', ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', @@ -193,6 +193,28 @@ class HookEventBridgeTest extends TestCase HookEventBridge::onCollectRoutesEvent($event); } + public function testOnInsertPostLocalEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, ['item' => ['id' => -1]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, array $data): array { + $this->assertSame('post_local', $name); + $this->assertSame(['id' => -1], $data); + + return ['id' => 123]; + }); + + HookEventBridge::onInsertPostLocalEvent($event); + + $this->assertSame( + ['item' => ['id' => 123]], + $event->getArray(), + ); + } + public function testOnPreparePostStartEventCallsHookWithCorrectValue(): void { $event = new ArrayFilterEvent(ArrayFilterEvent::PREPARE_POST_START, ['item' => ['id' => -1]]); From 9822dd25d84198ea8cfff3127b0ad9dcb2c03341 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 18 Mar 2025 14:21:31 +0000 Subject: [PATCH 65/91] Wrap item in INSERT_POST_LOCAL_END into separate array --- src/Content/Item.php | 10 ++++++-- src/Core/Hooks/HookEventBridge.php | 16 +++++++++++- src/Module/Post/Tag/Add.php | 10 ++++++-- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 25 ++++++++++++++++--- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/src/Content/Item.php b/src/Content/Item.php index af26ebd8ed..901a2eac3d 100644 --- a/src/Content/Item.php +++ b/src/Content/Item.php @@ -1011,10 +1011,16 @@ class Item Tag::createImplicitMentions($post['uri-id'], $post['thr-parent-id']); } - $post = $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, $post) + $hook_data = [ + 'item' => $post, + ]; + + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, $hook_data) )->getArray(); + $post = $hook_data['item'] ?? $post; + $author = DBA::selectFirst('contact', ['thumb'], ['uid' => $post['uid'], 'self' => true]); foreach ($recipients as $recipient) { diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index e5a7dd01ab..82a11f1f55 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -113,7 +113,7 @@ final class HookEventBridge ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_LOCAL => 'onInsertPostLocalEvent', - ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onInsertPostLocalEndEvent', ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', ArrayFilterEvent::PREPARE_POST_START => 'onPreparePostStartEvent', @@ -197,6 +197,20 @@ final class HookEventBridge $event->setArray($data); } + /** + * Map the INSERT_POST_LOCAL_END event to `post_local_end` hook + */ + public static function onInsertPostLocalEndEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $item = (array) $data['item'] ?? []; + + $data['item'] = static::callHook($event->getName(), $item); + + $event->setArray($data); + } + /** * Map the PREPARE_POST_START event to `prepare_body_init` hook */ diff --git a/src/Module/Post/Tag/Add.php b/src/Module/Post/Tag/Add.php index e03bf215a3..a145c36e90 100644 --- a/src/Module/Post/Tag/Add.php +++ b/src/Module/Post/Tag/Add.php @@ -153,10 +153,16 @@ EOT; $post['id'] = $post_id; - $post = $this->eventDispatcher->dispatch( - new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, $post) + $hook_data = [ + 'item' => $post, + ]; + + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, $hook_data) )->getArray(); + $post = $hook_data['item'] ?? $post; + $post = Post::selectFirst(['uri-id', 'uid'], ['id' => $post_id]); Worker::add(Worker::PRIORITY_HIGH, 'Notifier', Delivery::POST, $post['uri-id'], $post['uid']); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 17f9e1084d..e6ec58a27c 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -34,7 +34,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_LOCAL => 'onInsertPostLocalEvent', - ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onArrayFilterEvent', + ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onInsertPostLocalEndEvent', ArrayFilterEvent::INSERT_POST_REMOTE => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_REMOTE_END => 'onArrayFilterEvent', ArrayFilterEvent::PREPARE_POST_START => 'onPreparePostStartEvent', @@ -214,6 +214,27 @@ class HookEventBridgeTest extends TestCase $event->getArray(), ); } + public function testOnInsertPostLocalEndEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, ['item' => ['id' => -1]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, array $data): array { + $this->assertSame('post_local_end', $name); + $this->assertSame(['id' => -1], $data); + + return ['id' => 123]; + }); + + HookEventBridge::onInsertPostLocalEndEvent($event); + + $this->assertSame( + ['item' => ['id' => 123]], + $event->getArray(), + ); + } public function testOnPreparePostStartEventCallsHookWithCorrectValue(): void { @@ -390,8 +411,6 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::FEATURE_ENABLED, 'isEnabled'], [ArrayFilterEvent::FEATURE_GET, 'get'], [ArrayFilterEvent::INSERT_POST_LOCAL_START, 'post_local_start'], - [ArrayFilterEvent::INSERT_POST_LOCAL, 'post_local'], - [ArrayFilterEvent::INSERT_POST_LOCAL_END, 'post_local_end'], [ArrayFilterEvent::INSERT_POST_REMOTE, 'post_remote'], [ArrayFilterEvent::INSERT_POST_REMOTE_END, 'post_remote_end'], [ArrayFilterEvent::PREPARE_POST_FILTER_CONTENT, 'prepare_body_content_filter'], From 90db7d2e65f449d5bbdf633f94a14128da032911 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 20 Mar 2025 14:59:47 +0000 Subject: [PATCH 66/91] Create events for authenticate, register_account and remove_user hooks --- src/Core/Hooks/HookEventBridge.php | 34 +++++++++++++++ src/Event/ArrayFilterEvent.php | 6 +++ src/Model/User.php | 33 ++++++++++++--- src/Security/BasicAuth.php | 17 +++++--- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 41 ++++++++++++++++++- tests/Unit/Event/ArrayFilterEventTest.php | 3 ++ 6 files changed, 122 insertions(+), 12 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 82a11f1f55..bc2262df55 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -81,6 +81,9 @@ final class HookEventBridge ArrayFilterEvent::BLOCK_CONTACT => 'block', ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', ArrayFilterEvent::AVATAR_LOOKUP => 'avatar_lookup', + ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'authenticate', + ArrayFilterEvent::ACCOUNT_REGISTER => 'register_account', + ArrayFilterEvent::ACCOUNT_REMOVE => 'remove_user', ArrayFilterEvent::EVENT_CREATED => 'event_created', ArrayFilterEvent::EVENT_UPDATED => 'event_updated', ArrayFilterEvent::ADD_WORKER_TASK => 'proc_run', @@ -149,6 +152,9 @@ final class HookEventBridge ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', + ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'onArrayFilterEvent', + ArrayFilterEvent::ACCOUNT_REGISTER => 'onAccountRegisterEvent', + ArrayFilterEvent::ACCOUNT_REMOVE => 'onAccountRemoveEvent', ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent', ArrayFilterEvent::EVENT_UPDATED => 'onEventUpdatedEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', @@ -295,6 +301,34 @@ final class HookEventBridge $event->setArray($data); } + /** + * Map the ACCOUNT_REGISTER event to `register_account` hook + */ + public static function onAccountRegisterEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $uid = (int) $data['uid'] ?? 0; + + $data['uid'] = static::callHook($event->getName(), $uid); + + $event->setArray($data); + } + + /** + * Map the ACCOUNT_REMOVE event to `remove_account` hook + */ + public static function onAccountRemoveEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $user = (array) $data['user'] ?? []; + + $data['user'] = static::callHook($event->getName(), $user); + + $event->setArray($data); + } + /** * Map the EVENT_CREATED event to `event_created` hook */ diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 12105decc9..02a516bf61 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -112,6 +112,12 @@ final class ArrayFilterEvent extends Event public const AVATAR_LOOKUP = 'friendica.data.avatar_lookup'; + public const ACCOUNT_AUTHENTICATE = 'friendica.data.account_authenticate'; + + public const ACCOUNT_REGISTER = 'friendica.data.account_register'; + + public const ACCOUNT_REMOVE = 'friendica.data.account_remove'; + public const EVENT_CREATED = 'friendica.data.event_created'; public const EVENT_UPDATED = 'friendica.data.event_updated'; diff --git a/src/Model/User.php b/src/Model/User.php index 927a1a82bd..5195fb77a3 100644 --- a/src/Model/User.php +++ b/src/Model/User.php @@ -13,7 +13,6 @@ use ErrorException; use Exception; use Friendica\App; use Friendica\Content\Pager; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Search; @@ -21,6 +20,7 @@ use Friendica\Core\System; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Module; use Friendica\Network\HTTPClient\Client\HttpClientAccept; use Friendica\Network\HTTPClient\Client\HttpClientOptions; @@ -758,12 +758,16 @@ class User 'user_record' => null ]; - /* + $eventDispatcher = DI::eventDispatcher(); + + /** * An addon indicates successful login by setting 'authenticated' to non-zero value and returning a user record * Addons should never set 'authenticated' except to indicate success - as hooks may be chained * and later addons should not interfere with an earlier one that succeeded. */ - Hook::callAll('authenticate', $addon_auth); + $addon_auth = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_AUTHENTICATE, $addon_auth), + )->getArray(); if ($addon_auth['authenticated'] && $addon_auth['user_record']) { return $addon_auth['user_record']['uid']; @@ -1460,11 +1464,20 @@ class User Contact::updateSelfFromUserID($uid, true); } - Hook::callAll('register_account', $uid); + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = [ + 'uid' => $uid, + ]; + + $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_REGISTER, $hook_data), + ); self::setRegisterMethodByUserCount(); $return['user'] = $user; + return $return; } @@ -1787,7 +1800,17 @@ class User throw new \RuntimeException(DI::l10n()->t("User with delegates can't be removed, please remove delegate users first")); } - Hook::callAll('remove_user', $user); + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = [ + 'user' => $user, + ]; + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_REMOVE, $hook_data), + )->getArray(); + + $user = $hook_data['user'] ?? $user; // save username (actually the nickname as it is guaranteed // unique), so it cannot be re-registered in the future. diff --git a/src/Security/BasicAuth.php b/src/Security/BasicAuth.php index fe89bf452e..52a0f75026 100644 --- a/src/Security/BasicAuth.php +++ b/src/Security/BasicAuth.php @@ -11,6 +11,7 @@ use Exception; use Friendica\Core\Hook; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\User; use Friendica\Network\HTTPException\UnauthorizedException; @@ -136,12 +137,16 @@ class BasicAuth 'user_record' => null, ]; - /* - * An addon indicates successful login by setting 'authenticated' to non-zero value and returning a user record - * Addons should never set 'authenticated' except to indicate success - as hooks may be chained - * and later addons should not interfere with an earlier one that succeeded. - */ - Hook::callAll('authenticate', $addon_auth); + $eventDispatcher = DI::eventDispatcher(); + + /** + * An addon indicates successful login by setting 'authenticated' to non-zero value and returning a user record + * Addons should never set 'authenticated' except to indicate success - as hooks may be chained + * and later addons should not interfere with an earlier one that succeeded. + */ + $addon_auth = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_AUTHENTICATE, $addon_auth), + )->getArray(); if ($addon_auth['authenticated'] && !empty($addon_auth['user_record'])) { $record = $addon_auth['user_record']; diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index e6ec58a27c..d47ea1cbf7 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -70,6 +70,9 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', + ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'onArrayFilterEvent', + ArrayFilterEvent::ACCOUNT_REGISTER => 'onAccountRegisterEvent', + ArrayFilterEvent::ACCOUNT_REMOVE => 'onAccountRemoveEvent', ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent', ArrayFilterEvent::EVENT_UPDATED => 'onEventUpdatedEvent', ArrayFilterEvent::ADD_WORKER_TASK => 'onArrayFilterEvent', @@ -385,6 +388,40 @@ class HookEventBridgeTest extends TestCase HookEventBridge::onEventCreatedEvent($event); } + public function testOnAccountRegisterEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_REGISTER, ['uid' => 123]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, int $data): int { + $this->assertSame('register_account', $name); + $this->assertSame(123, $data); + + return $data; + }); + + HookEventBridge::onAccountRegisterEvent($event); + } + + public function testOnAccountRemoveEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_REMOVE, ['user' => ['uid' => 123]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, array $data): array { + $this->assertSame('remove_user', $name); + $this->assertSame(['uid' => 123], $data); + + return $data; + }); + + HookEventBridge::onAccountRemoveEvent($event); + } + public function testOnEventUpdatedEventCallsHookWithCorrectValue(): void { $event = new ArrayFilterEvent(ArrayFilterEvent::EVENT_UPDATED, ['event' => ['id' => 123]]); @@ -427,7 +464,6 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'], - [ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, 'profile_sidebar_enter'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'profile_sidebar'], [ArrayFilterEvent::PAGE_INFO, 'page_info_data'], [ArrayFilterEvent::SMILEY_LIST, 'smilie'], @@ -441,6 +477,9 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::BLOCK_CONTACT, 'block'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], [ArrayFilterEvent::AVATAR_LOOKUP, 'avatar_lookup'], + [ArrayFilterEvent::ACCOUNT_AUTHENTICATE, 'authenticate'], + [ArrayFilterEvent::ACCOUNT_REGISTER, 'register_account'], + [ArrayFilterEvent::ACCOUNT_REMOVE, 'remove_user'], [ArrayFilterEvent::EVENT_CREATED, 'event_created'], [ArrayFilterEvent::EVENT_UPDATED, 'event_updated'], [ArrayFilterEvent::ADD_WORKER_TASK, 'proc_run'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 85d90ba132..5bc71084c3 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -67,6 +67,9 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], [ArrayFilterEvent::AVATAR_LOOKUP, 'friendica.data.avatar_lookup'], + [ArrayFilterEvent::ACCOUNT_AUTHENTICATE, 'friendica.data.account_authenticate'], + [ArrayFilterEvent::ACCOUNT_REGISTER, 'friendica.data.account_register'], + [ArrayFilterEvent::ACCOUNT_REMOVE, 'friendica.data.account_remove'], [ArrayFilterEvent::EVENT_CREATED, 'friendica.data.event_created'], [ArrayFilterEvent::EVENT_UPDATED, 'friendica.data.event_updated'], [ArrayFilterEvent::ADD_WORKER_TASK, 'friendica.data.add_worker_task'], From 76c3eeb96e47000f5dfa1e4d88d1e2c6f4b56b2b Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 24 Mar 2025 08:54:38 +0000 Subject: [PATCH 67/91] Register hooks as event listener in API tests --- tests/ApiTestCase.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/ApiTestCase.php b/tests/ApiTestCase.php index 6124bf9f32..45a84c280a 100644 --- a/tests/ApiTestCase.php +++ b/tests/ApiTestCase.php @@ -11,6 +11,7 @@ use Friendica\Capabilities\ICanCreateResponses; use Friendica\Core\Addon\AddonHelper; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\Hook; +use Friendica\Core\Hooks\HookEventBridge; use Friendica\DI; use Friendica\Module\Special\HTTPException; use Friendica\Security\Authentication; @@ -159,6 +160,13 @@ abstract class ApiTestCase extends FixtureTestCase ; DI::init($this->dice); + /** @var \Friendica\Event\EventDispatcher */ + $eventDispatcher = DI::eventDispatcher(); + + foreach (HookEventBridge::getStaticSubscribedEvents() as $eventName => $methodName) { + $eventDispatcher->addListener($eventName, [HookEventBridge::class, $methodName]); + } + $this->httpExceptionMock = $this->dice->create(HTTPException::class); AuthTestConfig::$authenticated = true; From f0273a618c5d9db7ddd845f22a0603c333190ab1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 24 Mar 2025 12:28:22 +0000 Subject: [PATCH 68/91] Create event for check_item_notification hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Model/Post/UserNotification.php | 9 +++++++-- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index bc2262df55..356dfe7e9c 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -59,6 +59,7 @@ final class HookEventBridge ArrayFilterEvent::ITEM_TAGGED => 'tagged', ArrayFilterEvent::DISPLAY_ITEM => 'display_item', ArrayFilterEvent::CACHE_ITEM => 'put_item_in_cache', + ArrayFilterEvent::CHECK_ITEM_NOTIFICATION => 'check_item_notification', ArrayFilterEvent::DETECT_LANGUAGES => 'detect_languages', ArrayFilterEvent::RENDER_LOCATION => 'render_location', ArrayFilterEvent::ITEM_PHOTO_MENU => 'item_photo_menu', @@ -130,6 +131,7 @@ final class HookEventBridge ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent', + ArrayFilterEvent::CHECK_ITEM_NOTIFICATION => 'onArrayFilterEvent', ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 02a516bf61..0313520060 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -68,6 +68,8 @@ final class ArrayFilterEvent extends Event public const CACHE_ITEM = 'friendica.data.cache_item'; + public const CHECK_ITEM_NOTIFICATION = 'friendica.data.check_item_notification'; + public const DETECT_LANGUAGES = 'friendica.data.detect_languages'; public const RENDER_LOCATION = 'friendica.data.render_location'; diff --git a/src/Model/Post/UserNotification.php b/src/Model/Post/UserNotification.php index 95c578f486..d212b07b2f 100644 --- a/src/Model/Post/UserNotification.php +++ b/src/Model/Post/UserNotification.php @@ -9,10 +9,10 @@ namespace Friendica\Model\Post; use BadMethodCallException; use Exception; -use Friendica\Core\Hook; use Friendica\Database\Database; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Model\Post; @@ -396,7 +396,12 @@ class UserNotification $profiles = [$owner['nurl']]; $notification_data = ['uid' => $uid, 'profiles' => []]; - Hook::callAll('check_item_notification', $notification_data); + + $eventDispatcher = DI::eventDispatcher(); + + $notification_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::CHECK_ITEM_NOTIFICATION, $notification_data), + )->getArray(); // Normalize the connector profiles foreach ($notification_data['profiles'] as $profile) { diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index d47ea1cbf7..f00e803ba1 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -48,6 +48,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent', + ArrayFilterEvent::CHECK_ITEM_NOTIFICATION => 'onArrayFilterEvent', ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', @@ -460,6 +461,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::ITEM_TAGGED, 'tagged'], [ArrayFilterEvent::DISPLAY_ITEM, 'display_item'], [ArrayFilterEvent::CACHE_ITEM, 'put_item_in_cache'], + [ArrayFilterEvent::CHECK_ITEM_NOTIFICATION, 'check_item_notification'], [ArrayFilterEvent::DETECT_LANGUAGES, 'detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 5bc71084c3..91d611a33b 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -45,6 +45,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::ITEM_TAGGED, 'friendica.data.item_tagged'], [ArrayFilterEvent::DISPLAY_ITEM, 'friendica.data.display_item'], [ArrayFilterEvent::CACHE_ITEM, 'friendica.data.cache_item'], + [ArrayFilterEvent::CHECK_ITEM_NOTIFICATION, 'friendica.data.check_item_notification'], [ArrayFilterEvent::DETECT_LANGUAGES, 'friendica.data.detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'friendica.data.item_photo_menu'], From 20a1d2262019f5a906a92fcd87c898a76a1cc16f Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 24 Mar 2025 12:41:40 +0000 Subject: [PATCH 69/91] Create event for profile_tabs hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Module/BaseProfile.php | 12 ++++++++---- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 356dfe7e9c..3d2d6d62f5 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -66,6 +66,7 @@ final class HookEventBridge ArrayFilterEvent::CONTACT_PHOTO_MENU => 'contact_photo_menu', ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'profile_sidebar_enter', ArrayFilterEvent::PROFILE_SIDEBAR => 'profile_sidebar', + ArrayFilterEvent::PROFILE_TABS => 'profile_tabs', ArrayFilterEvent::OEMBED_FETCH_END => 'oembed_fetch_url', ArrayFilterEvent::PAGE_INFO => 'page_info_data', ArrayFilterEvent::SMILEY_LIST => 'smilie', @@ -138,6 +139,7 @@ final class HookEventBridge ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', + ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 0313520060..06ada45a22 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -82,6 +82,8 @@ final class ArrayFilterEvent extends Event public const PROFILE_SIDEBAR = 'friendica.data.profile_sidebar'; + public const PROFILE_TABS = 'friendica.data.profile_tabs'; + public const OEMBED_FETCH_END = 'friendica.data.oembed_fetch_end'; public const PAGE_INFO = 'friendica.data.page_info'; diff --git a/src/Module/BaseProfile.php b/src/Module/BaseProfile.php index 4a73408bc9..ce5d276861 100644 --- a/src/Module/BaseProfile.php +++ b/src/Module/BaseProfile.php @@ -9,9 +9,9 @@ namespace Friendica\Module; use Friendica\BaseModule; use Friendica\Content\Feature; -use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\User; class BaseProfile extends BaseModule @@ -128,12 +128,16 @@ class BaseProfile extends BaseModule ]; } - $arr = ['is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => $current, 'tabs' => $tabs]; + $hook_data = ['is_owner' => $is_owner, 'nickname' => $nickname, 'tab' => $current, 'tabs' => $tabs]; - Hook::callAll('profile_tabs', $arr); + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PROFILE_TABS, $hook_data), + )->getArray(); $tpl = Renderer::getMarkupTemplate('common_tabs.tpl'); - return Renderer::replaceMacros($tpl, ['$tabs' => $arr['tabs'], '$more' => DI::l10n()->t('More')]); + return Renderer::replaceMacros($tpl, ['$tabs' => $hook_data['tabs'], '$more' => DI::l10n()->t('More')]); } } diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index f00e803ba1..874fc9b25e 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -55,6 +55,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', + ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', @@ -467,6 +468,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'profile_sidebar'], + [ArrayFilterEvent::PROFILE_TABS, 'profile_tabs'], [ArrayFilterEvent::PAGE_INFO, 'page_info_data'], [ArrayFilterEvent::SMILEY_LIST, 'smilie'], [ArrayFilterEvent::JOT_NETWORKS, 'jot_networks'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 91d611a33b..ea495110c3 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -52,6 +52,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'friendica.data.contact_photo_menu'], [ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, 'friendica.data.profile_sidebar_entry'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'friendica.data.profile_sidebar'], + [ArrayFilterEvent::PROFILE_TABS, 'friendica.data.profile_tabs'], [ArrayFilterEvent::OEMBED_FETCH_END, 'friendica.data.oembed_fetch_end'], [ArrayFilterEvent::PAGE_INFO, 'friendica.data.page_info'], [ArrayFilterEvent::SMILEY_LIST, 'friendica.data.smiley_list'], From 88929bb307423337b3c8f37784e466c4c0174d10 Mon Sep 17 00:00:00 2001 From: Art4 Date: Mon, 24 Mar 2025 13:31:53 +0000 Subject: [PATCH 70/91] Create event for directory_item hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Module/Directory.php | 16 +++++++++++++--- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 3d2d6d62f5..e208901a82 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -63,6 +63,7 @@ final class HookEventBridge ArrayFilterEvent::DETECT_LANGUAGES => 'detect_languages', ArrayFilterEvent::RENDER_LOCATION => 'render_location', ArrayFilterEvent::ITEM_PHOTO_MENU => 'item_photo_menu', + ArrayFilterEvent::DIRECTORY_ITEM => 'directory_item', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'contact_photo_menu', ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'profile_sidebar_enter', ArrayFilterEvent::PROFILE_SIDEBAR => 'profile_sidebar', @@ -136,6 +137,7 @@ final class HookEventBridge ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', + ArrayFilterEvent::DIRECTORY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 06ada45a22..de92599ee3 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -76,6 +76,8 @@ final class ArrayFilterEvent extends Event public const ITEM_PHOTO_MENU = 'friendica.data.item_photo_menu'; + public const DIRECTORY_ITEM = 'friendica.data.directory_item'; + public const CONTACT_PHOTO_MENU = 'friendica.data.contact_photo_menu'; public const PROFILE_SIDEBAR_ENTRY = 'friendica.data.profile_sidebar_entry'; diff --git a/src/Module/Directory.php b/src/Module/Directory.php index ad95b49524..d63bbc13e3 100644 --- a/src/Module/Directory.php +++ b/src/Module/Directory.php @@ -15,6 +15,7 @@ use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\Core\Search; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model; use Friendica\Model\Profile; use Friendica\Network\HTTPException; @@ -161,13 +162,22 @@ class Directory extends BaseModule ]; - $hook = ['contact' => $contact, 'entry' => $entry]; + $eventDispatcher = DI::eventDispatcher(); - Hook::callAll('directory_item', $hook); + $hook_data = [ + 'contact' => $contact, + 'entry' => $entry, + ]; + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::DIRECTORY_ITEM, $hook_data), + )->getArray(); + + $entry = $hook_data['entry'] ?? $entry; unset($profile); unset($location); - return $hook['entry']; + return $entry; } } diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 874fc9b25e..69e37c0b9c 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -52,6 +52,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', + ArrayFilterEvent::DIRECTORY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CONTACT_PHOTO_MENU => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', @@ -466,6 +467,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::DETECT_LANGUAGES, 'detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], + [ArrayFilterEvent::DIRECTORY_ITEM, 'directory_item'], [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'profile_sidebar'], [ArrayFilterEvent::PROFILE_TABS, 'profile_tabs'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index ea495110c3..881deacd43 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -49,6 +49,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::DETECT_LANGUAGES, 'friendica.data.detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'friendica.data.item_photo_menu'], + [ArrayFilterEvent::DIRECTORY_ITEM, 'friendica.data.directory_item'], [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'friendica.data.contact_photo_menu'], [ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, 'friendica.data.profile_sidebar_entry'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'friendica.data.profile_sidebar'], From a9f02bfef5453e0005a63f490a7f81a677883e4c Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Mar 2025 12:26:40 +0000 Subject: [PATCH 71/91] Create event for about_hook hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/HtmlFilterEvent.php | 2 ++ src/Module/Friendica.php | 26 ++++++++++++++++--- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/HtmlFilterEventTest.php | 4 +++ 5 files changed, 32 insertions(+), 4 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index e208901a82..24d15606ea 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -99,6 +99,7 @@ final class HookEventBridge HtmlFilterEvent::PAGE_HEADER => 'page_header', HtmlFilterEvent::PAGE_CONTENT_TOP => 'page_content_top', HtmlFilterEvent::PAGE_END => 'page_end', + HtmlFilterEvent::ABOUT_CONTENT => 'about_hook', HtmlFilterEvent::JOT_TOOL => 'jot_tool', HtmlFilterEvent::CONTACT_BLOCK_END => 'contact_block_end', ]; @@ -173,6 +174,7 @@ final class HookEventBridge HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_CONTENT_TOP => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent', + HtmlFilterEvent::ABOUT_CONTENT => 'onHtmlFilterEvent', HtmlFilterEvent::JOT_TOOL => 'onHtmlFilterEvent', HtmlFilterEvent::CONTACT_BLOCK_END => 'onHtmlFilterEvent', ]; diff --git a/src/Event/HtmlFilterEvent.php b/src/Event/HtmlFilterEvent.php index cb8a3992df..2f68d864bf 100644 --- a/src/Event/HtmlFilterEvent.php +++ b/src/Event/HtmlFilterEvent.php @@ -26,6 +26,8 @@ final class HtmlFilterEvent extends Event public const PAGE_END = 'friendica.html.page_end'; + public const ABOUT_CONTENT = 'friendica.html.about_content'; + public const JOT_TOOL = 'friendica.html.jot_tool'; public const CONTACT_BLOCK_END = 'friendica.html.contact_block_end'; diff --git a/src/Module/Friendica.php b/src/Module/Friendica.php index 1a741b890c..0ace0707dd 100644 --- a/src/Module/Friendica.php +++ b/src/Module/Friendica.php @@ -13,16 +13,17 @@ use Friendica\App\BaseURL; use Friendica\BaseModule; use Friendica\Core\Addon\AddonHelper; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Hook; use Friendica\Core\KeyValueStorage\Capability\IManageKeyValuePairs; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Database\PostUpdate; +use Friendica\Event\HtmlFilterEvent; use Friendica\Model\User; use Friendica\Network\HTTPException; use Friendica\Protocol\ActivityPub; use Friendica\Util\Profiler; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -32,6 +33,7 @@ use Psr\Log\LoggerInterface; class Friendica extends BaseModule { private AddonHelper $addonHelper; + private EventDispatcherInterface $eventDispatcher; /** @var IManageConfigValues */ private $config; /** @var IManageKeyValuePairs */ @@ -39,13 +41,27 @@ class Friendica extends BaseModule /** @var IHandleUserSessions */ private $session; - public function __construct(AddonHelper $addonHelper, IHandleUserSessions $session, IManageKeyValuePairs $keyValue, IManageConfigValues $config, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { + public function __construct( + AddonHelper $addonHelper, + EventDispatcherInterface $eventDispatcher, + IHandleUserSessions $session, + IManageKeyValuePairs $keyValue, + IManageConfigValues $config, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [], + ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->config = $config; $this->keyValue = $keyValue; $this->session = $session; + $this->eventDispatcher = $eventDispatcher; $this->addonHelper = $addonHelper; } @@ -99,7 +115,9 @@ class Friendica extends BaseModule $hooked = ''; - Hook::callAll('about_hook', $hooked); + $hooked = $this->eventDispatcher->dispatch( + new HtmlFilterEvent(HtmlFilterEvent::ABOUT_CONTENT, $hooked), + )->getHtml(); $tpl = Renderer::getMarkupTemplate('friendica.tpl'); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 69e37c0b9c..ab6f5e2cf0 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -88,6 +88,7 @@ class HookEventBridgeTest extends TestCase HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_CONTENT_TOP => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent', + HtmlFilterEvent::ABOUT_CONTENT => 'onHtmlFilterEvent', HtmlFilterEvent::JOT_TOOL => 'onHtmlFilterEvent', HtmlFilterEvent::CONTACT_BLOCK_END => 'onHtmlFilterEvent', ]; @@ -525,6 +526,7 @@ class HookEventBridgeTest extends TestCase [HtmlFilterEvent::PAGE_HEADER, 'page_header'], [HtmlFilterEvent::PAGE_CONTENT_TOP, 'page_content_top'], [HtmlFilterEvent::PAGE_END, 'page_end'], + [HtmlFilterEvent::ABOUT_CONTENT, 'about_hook'], [HtmlFilterEvent::JOT_TOOL, 'jot_tool'], [HtmlFilterEvent::CONTACT_BLOCK_END, 'contact_block_end'], ]; diff --git a/tests/Unit/Event/HtmlFilterEventTest.php b/tests/Unit/Event/HtmlFilterEventTest.php index ae1d27a5ad..9d38cf097a 100644 --- a/tests/Unit/Event/HtmlFilterEventTest.php +++ b/tests/Unit/Event/HtmlFilterEventTest.php @@ -27,8 +27,12 @@ class HtmlFilterEventTest extends TestCase return [ [HtmlFilterEvent::HEAD, 'friendica.html.head'], [HtmlFilterEvent::FOOTER, 'friendica.html.footer'], + [HtmlFilterEvent::PAGE_HEADER, 'friendica.html.page_header'], [HtmlFilterEvent::PAGE_CONTENT_TOP, 'friendica.html.page_content_top'], [HtmlFilterEvent::PAGE_END, 'friendica.html.page_end'], + [HtmlFilterEvent::ABOUT_CONTENT, 'friendica.html.about_content'], + [HtmlFilterEvent::JOT_TOOL, 'friendica.html.jot_tool'], + [HtmlFilterEvent::CONTACT_BLOCK_END, 'friendica.html.contact_block_end'], ]; } From a9b36f55c95d94d408f7cf37aa5fec631d2b419b Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 25 Mar 2025 15:57:26 +0000 Subject: [PATCH 72/91] Create event for home_content hook --- src/Core/Hooks/HookEventBridge.php | 6 ++++-- src/Event/HtmlFilterEvent.php | 4 +++- src/Module/Friendica.php | 2 +- src/Module/Home.php | 7 +++++-- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 6 ++++-- tests/Unit/Event/HtmlFilterEventTest.php | 3 ++- 6 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 24d15606ea..84835dc780 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -99,7 +99,8 @@ final class HookEventBridge HtmlFilterEvent::PAGE_HEADER => 'page_header', HtmlFilterEvent::PAGE_CONTENT_TOP => 'page_content_top', HtmlFilterEvent::PAGE_END => 'page_end', - HtmlFilterEvent::ABOUT_CONTENT => 'about_hook', + HtmlFilterEvent::MOD_HOME_CONTENT => 'home_content', + HtmlFilterEvent::MOD_ABOUT_CONTENT => 'about_hook', HtmlFilterEvent::JOT_TOOL => 'jot_tool', HtmlFilterEvent::CONTACT_BLOCK_END => 'contact_block_end', ]; @@ -174,7 +175,8 @@ final class HookEventBridge HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_CONTENT_TOP => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent', - HtmlFilterEvent::ABOUT_CONTENT => 'onHtmlFilterEvent', + HtmlFilterEvent::MOD_HOME_CONTENT => 'onHtmlFilterEvent', + HtmlFilterEvent::MOD_ABOUT_CONTENT => 'onHtmlFilterEvent', HtmlFilterEvent::JOT_TOOL => 'onHtmlFilterEvent', HtmlFilterEvent::CONTACT_BLOCK_END => 'onHtmlFilterEvent', ]; diff --git a/src/Event/HtmlFilterEvent.php b/src/Event/HtmlFilterEvent.php index 2f68d864bf..9e30d6d656 100644 --- a/src/Event/HtmlFilterEvent.php +++ b/src/Event/HtmlFilterEvent.php @@ -26,7 +26,9 @@ final class HtmlFilterEvent extends Event public const PAGE_END = 'friendica.html.page_end'; - public const ABOUT_CONTENT = 'friendica.html.about_content'; + public const MOD_HOME_CONTENT = 'friendica.html.mod_home_content'; + + public const MOD_ABOUT_CONTENT = 'friendica.html.mod_about_content'; public const JOT_TOOL = 'friendica.html.jot_tool'; diff --git a/src/Module/Friendica.php b/src/Module/Friendica.php index 0ace0707dd..314152abca 100644 --- a/src/Module/Friendica.php +++ b/src/Module/Friendica.php @@ -116,7 +116,7 @@ class Friendica extends BaseModule $hooked = ''; $hooked = $this->eventDispatcher->dispatch( - new HtmlFilterEvent(HtmlFilterEvent::ABOUT_CONTENT, $hooked), + new HtmlFilterEvent(HtmlFilterEvent::MOD_ABOUT_CONTENT, $hooked), )->getHtml(); $tpl = Renderer::getMarkupTemplate('friendica.tpl'); diff --git a/src/Module/Home.php b/src/Module/Home.php index 7e7d59d760..9a6a4a4730 100644 --- a/src/Module/Home.php +++ b/src/Module/Home.php @@ -8,10 +8,10 @@ namespace Friendica\Module; use Friendica\BaseModule; -use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\DI; use Friendica\Event\Event; +use Friendica\Event\HtmlFilterEvent; use Friendica\Model\User; use Friendica\Module\Security\Login; use Friendica\Protocol\ActivityPub; @@ -66,7 +66,10 @@ class Home extends BaseModule $login = Login::form(DI::args()->getQueryString(), Register::getPolicy() !== Register::CLOSED); $content = ''; - Hook::callAll('home_content', $content); + + $content = $eventDispatcher->dispatch( + new HtmlFilterEvent(HtmlFilterEvent::MOD_HOME_CONTENT, $content), + )->getHtml(); $tpl = Renderer::getMarkupTemplate('home.tpl'); return Renderer::replaceMacros($tpl, [ diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index ab6f5e2cf0..075630da1c 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -88,7 +88,8 @@ class HookEventBridgeTest extends TestCase HtmlFilterEvent::PAGE_HEADER => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_CONTENT_TOP => 'onHtmlFilterEvent', HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent', - HtmlFilterEvent::ABOUT_CONTENT => 'onHtmlFilterEvent', + HtmlFilterEvent::MOD_HOME_CONTENT => 'onHtmlFilterEvent', + HtmlFilterEvent::MOD_ABOUT_CONTENT => 'onHtmlFilterEvent', HtmlFilterEvent::JOT_TOOL => 'onHtmlFilterEvent', HtmlFilterEvent::CONTACT_BLOCK_END => 'onHtmlFilterEvent', ]; @@ -526,7 +527,8 @@ class HookEventBridgeTest extends TestCase [HtmlFilterEvent::PAGE_HEADER, 'page_header'], [HtmlFilterEvent::PAGE_CONTENT_TOP, 'page_content_top'], [HtmlFilterEvent::PAGE_END, 'page_end'], - [HtmlFilterEvent::ABOUT_CONTENT, 'about_hook'], + [HtmlFilterEvent::MOD_HOME_CONTENT, 'home_content'], + [HtmlFilterEvent::MOD_ABOUT_CONTENT, 'about_hook'], [HtmlFilterEvent::JOT_TOOL, 'jot_tool'], [HtmlFilterEvent::CONTACT_BLOCK_END, 'contact_block_end'], ]; diff --git a/tests/Unit/Event/HtmlFilterEventTest.php b/tests/Unit/Event/HtmlFilterEventTest.php index 9d38cf097a..47a2d2596d 100644 --- a/tests/Unit/Event/HtmlFilterEventTest.php +++ b/tests/Unit/Event/HtmlFilterEventTest.php @@ -30,7 +30,8 @@ class HtmlFilterEventTest extends TestCase [HtmlFilterEvent::PAGE_HEADER, 'friendica.html.page_header'], [HtmlFilterEvent::PAGE_CONTENT_TOP, 'friendica.html.page_content_top'], [HtmlFilterEvent::PAGE_END, 'friendica.html.page_end'], - [HtmlFilterEvent::ABOUT_CONTENT, 'friendica.html.about_content'], + [HtmlFilterEvent::MOD_HOME_CONTENT, 'friendica.html.mod_home_content'], + [HtmlFilterEvent::MOD_ABOUT_CONTENT, 'friendica.html.mod_about_content'], [HtmlFilterEvent::JOT_TOOL, 'friendica.html.jot_tool'], [HtmlFilterEvent::CONTACT_BLOCK_END, 'friendica.html.contact_block_end'], ]; From 27e474c83c3b626b220b0f815ef5d64d35b20c98 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 26 Mar 2025 08:30:20 +0000 Subject: [PATCH 73/91] create event for parse_link hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Module/ParseUrl.php | 24 +++++++++++++------ tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 84835dc780..0beeec8667 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -54,6 +54,7 @@ final class HookEventBridge ArrayFilterEvent::PREPARE_POST_END => 'prepare_body_final', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'photo_upload_form', ArrayFilterEvent::NETWORK_TO_NAME => 'network_to_name', + ArrayFilterEvent::PARSE_LINK => 'parse_link', ArrayFilterEvent::CONVERSATION_START => 'conversation_start', ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'item_by_link', ArrayFilterEvent::ITEM_TAGGED => 'tagged', @@ -130,6 +131,7 @@ final class HookEventBridge ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', + ArrayFilterEvent::PARSE_LINK => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index de92599ee3..c9ae0fabe1 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -58,6 +58,8 @@ final class ArrayFilterEvent extends Event public const NETWORK_TO_NAME = 'friendica.data.network_to_name'; + public const PARSE_LINK = 'friendica.data.parse_link'; + public const CONVERSATION_START = 'friendica.data.conversation_start'; public const FETCH_ITEM_BY_LINK = 'friendica.data.fetch_item_by_link'; diff --git a/src/Module/ParseUrl.php b/src/Module/ParseUrl.php index 8da72c742c..508e5d987d 100644 --- a/src/Module/ParseUrl.php +++ b/src/Module/ParseUrl.php @@ -11,12 +11,13 @@ use Friendica\App\Arguments; use Friendica\App\BaseURL; use Friendica\BaseModule; use Friendica\Content\Text\BBCode; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Session\Capability\IHandleUserSessions; +use Friendica\Event\ArrayFilterEvent; use Friendica\Network\HTTPException\BadRequestException; use Friendica\Util; use Friendica\Util\Profiler; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; class ParseUrl extends BaseModule @@ -24,11 +25,14 @@ class ParseUrl extends BaseModule /** @var IHandleUserSessions */ protected $userSession; - public function __construct(L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $userSession, $server, array $parameters = []) + private EventDispatcherInterface $eventDispatcher; + + public function __construct(L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IHandleUserSessions $userSession, EventDispatcherInterface $eventDispatcher, $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->userSession = $userSession; + $this->eventDispatcher = $eventDispatcher; } protected function rawContent(array $request = []) @@ -80,15 +84,21 @@ class ParseUrl extends BaseModule } } - $arr = ['url' => $url, 'format' => $format, 'text' => null]; + $hook_data = [ + 'url' => $url, + 'format' => $format, + 'text' => null, + ]; - Hook::callAll('parse_link', $arr); + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PARSE_LINK, $hook_data), + )->getArray(); - if ($arr['text']) { + if ($hook_data['text']) { if ($format == 'json') { - $this->jsonExit($arr['text']); + $this->jsonExit($hook_data['text']); } else { - $this->httpExit($arr['text']); + $this->httpExit($hook_data['text']); } } diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 075630da1c..bdfe5d5508 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -43,6 +43,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', + ArrayFilterEvent::PARSE_LINK => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_TAGGED => 'onArrayFilterEvent', @@ -460,6 +461,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::PREPARE_POST_END, 'prepare_body_final'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'], + [ArrayFilterEvent::PARSE_LINK, 'parse_link'], [ArrayFilterEvent::CONVERSATION_START, 'conversation_start'], [ArrayFilterEvent::FETCH_ITEM_BY_LINK, 'item_by_link'], [ArrayFilterEvent::ITEM_TAGGED, 'tagged'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 881deacd43..fafd1a66e0 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -40,6 +40,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PREPARE_POST_END, 'friendica.data.prepare_post_end'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'], + [ArrayFilterEvent::PARSE_LINK, 'friendica.data.parse_link'], [ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'], [ArrayFilterEvent::FETCH_ITEM_BY_LINK, 'friendica.data.fetch_item_by_link'], [ArrayFilterEvent::ITEM_TAGGED, 'friendica.data.item_tagged'], From e4cb372760d04b9d346148010cac40d0af7da984 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 26 Mar 2025 08:58:23 +0000 Subject: [PATCH 74/91] Create events for register_form and register_post hook --- src/Core/Hooks/HookEventBridge.php | 4 +++ src/Event/ArrayFilterEvent.php | 4 +++ src/Module/Register.php | 27 ++++++++++++++----- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 4 +++ tests/Unit/Event/ArrayFilterEventTest.php | 2 ++ 5 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 0beeec8667..8b6c69c2c2 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -86,6 +86,8 @@ final class HookEventBridge ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', ArrayFilterEvent::AVATAR_LOOKUP => 'avatar_lookup', ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'authenticate', + ArrayFilterEvent::ACCOUNT_REGISTER_FORM => 'register_form', + ArrayFilterEvent::ACCOUNT_REGISTER_POST => 'register_post', ArrayFilterEvent::ACCOUNT_REGISTER => 'register_account', ArrayFilterEvent::ACCOUNT_REMOVE => 'remove_user', ArrayFilterEvent::EVENT_CREATED => 'event_created', @@ -163,6 +165,8 @@ final class HookEventBridge ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'onArrayFilterEvent', + ArrayFilterEvent::ACCOUNT_REGISTER_FORM => 'onArrayFilterEvent', + ArrayFilterEvent::ACCOUNT_REGISTER_POST => 'onArrayFilterEvent', ArrayFilterEvent::ACCOUNT_REGISTER => 'onAccountRegisterEvent', ArrayFilterEvent::ACCOUNT_REMOVE => 'onAccountRemoveEvent', ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index c9ae0fabe1..40433328a3 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -122,6 +122,10 @@ final class ArrayFilterEvent extends Event public const ACCOUNT_AUTHENTICATE = 'friendica.data.account_authenticate'; + public const ACCOUNT_REGISTER_FORM = 'friendica.data.account_register_form'; + + public const ACCOUNT_REGISTER_POST = 'friendica.data.account_register_post'; + public const ACCOUNT_REGISTER = 'friendica.data.account_register'; public const ACCOUNT_REMOVE = 'friendica.data.account_remove'; diff --git a/src/Module/Register.php b/src/Module/Register.php index 1cea2ba9a4..6f641355e3 100644 --- a/src/Module/Register.php +++ b/src/Module/Register.php @@ -12,18 +12,19 @@ use Friendica\App\BaseURL; use Friendica\BaseModule; use Friendica\Content\Text\BBCode; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model; use Friendica\Model\User; use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; use Friendica\Util\Proxy; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -41,13 +42,16 @@ class Register extends BaseModule /** @var IHandleUserSessions */ private $session; - public function __construct(IHandleUserSessions $session, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IManageConfigValues $config, array $server, array $parameters = []) + private EventDispatcherInterface $eventDispatcher; + + public function __construct(IHandleUserSessions $session, EventDispatcherInterface $eventDispatcher, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, IManageConfigValues $config, array $server, array $parameters = []) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->tos = new Tos($l10n, $baseUrl, $args, $logger, $profiler, $response, $config, $server, $parameters); $this->session = $session; + $this->eventDispatcher = $eventDispatcher; } /** @@ -129,11 +133,15 @@ class Register extends BaseModule $tpl = Renderer::getMarkupTemplate('register.tpl'); - $arr = ['template' => $tpl]; + $hook_data = [ + 'template' => $tpl, + ]; - Hook::callAll('register_form', $arr); + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_REGISTER_FORM, $hook_data), + )->getArray(); - $tpl = $arr['template']; + $tpl = $hook_data['template'] ?? $tpl; $o = Renderer::replaceMacros($tpl, [ '$invitations' => DI::config()->get('system', 'invitation_only'), @@ -190,8 +198,13 @@ class Register extends BaseModule { BaseModule::checkFormSecurityTokenRedirectOnError('/register', 'register'); - $arr = ['post' => $_POST]; - Hook::callAll('register_post', $arr); + $arr = [ + 'post' => $_POST, + ]; + + $arr = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ACCOUNT_REGISTER_POST, $arr), + )->getArray(); $additional_account = false; diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index bdfe5d5508..7660a9d2a1 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -75,6 +75,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'onArrayFilterEvent', + ArrayFilterEvent::ACCOUNT_REGISTER_FORM => 'onArrayFilterEvent', + ArrayFilterEvent::ACCOUNT_REGISTER_POST => 'onArrayFilterEvent', ArrayFilterEvent::ACCOUNT_REGISTER => 'onAccountRegisterEvent', ArrayFilterEvent::ACCOUNT_REMOVE => 'onAccountRemoveEvent', ArrayFilterEvent::EVENT_CREATED => 'onEventCreatedEvent', @@ -488,6 +490,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], [ArrayFilterEvent::AVATAR_LOOKUP, 'avatar_lookup'], [ArrayFilterEvent::ACCOUNT_AUTHENTICATE, 'authenticate'], + [ArrayFilterEvent::ACCOUNT_REGISTER_FORM, 'register_form'], + [ArrayFilterEvent::ACCOUNT_REGISTER_POST, 'register_post'], [ArrayFilterEvent::ACCOUNT_REGISTER, 'register_account'], [ArrayFilterEvent::ACCOUNT_REMOVE, 'remove_user'], [ArrayFilterEvent::EVENT_CREATED, 'event_created'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index fafd1a66e0..b0c40e5129 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -72,6 +72,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], [ArrayFilterEvent::AVATAR_LOOKUP, 'friendica.data.avatar_lookup'], [ArrayFilterEvent::ACCOUNT_AUTHENTICATE, 'friendica.data.account_authenticate'], + [ArrayFilterEvent::ACCOUNT_REGISTER_FORM, 'friendica.data.account_register_form'], + [ArrayFilterEvent::ACCOUNT_REGISTER_POST, 'friendica.data.account_register_post'], [ArrayFilterEvent::ACCOUNT_REGISTER, 'friendica.data.account_register'], [ArrayFilterEvent::ACCOUNT_REMOVE, 'friendica.data.account_remove'], [ArrayFilterEvent::EVENT_CREATED, 'friendica.data.event_created'], From 584e7e05b028f0a31b007d2b34d5519feaffdaf0 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 28 Mar 2025 08:31:18 +0000 Subject: [PATCH 75/91] Create events for contact_edit and contact_edit_post hooks --- src/Core/Hooks/HookEventBridge.php | 4 + src/Event/ArrayFilterEvent.php | 4 + src/Module/Contact/Profile.php | 159 +++++++++++------- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 4 + tests/Unit/Event/ArrayFilterEventTest.php | 2 + 5 files changed, 109 insertions(+), 64 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 8b6c69c2c2..c74b0a8df2 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -84,6 +84,8 @@ final class HookEventBridge ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'revoke_follow', ArrayFilterEvent::BLOCK_CONTACT => 'block', ArrayFilterEvent::UNBLOCK_CONTACT => 'unblock', + ArrayFilterEvent::EDIT_CONTACT_FORM => 'contact_edit', + ArrayFilterEvent::EDIT_CONTACT_POST => 'contact_edit_post', ArrayFilterEvent::AVATAR_LOOKUP => 'avatar_lookup', ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'authenticate', ArrayFilterEvent::ACCOUNT_REGISTER_FORM => 'register_form', @@ -163,6 +165,8 @@ final class HookEventBridge ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::EDIT_CONTACT_FORM => 'onArrayFilterEvent', + ArrayFilterEvent::EDIT_CONTACT_POST => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'onArrayFilterEvent', ArrayFilterEvent::ACCOUNT_REGISTER_FORM => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 40433328a3..9435ab37b6 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -118,6 +118,10 @@ final class ArrayFilterEvent extends Event public const UNBLOCK_CONTACT = 'friendica.data.unblock_contact'; + public const EDIT_CONTACT_FORM = 'friendica.data.edit_contact_form'; + + public const EDIT_CONTACT_POST = 'friendica.data.edit_contact_post'; + public const AVATAR_LOOKUP = 'friendica.data.avatar_lookup'; public const ACCOUNT_AUTHENTICATE = 'friendica.data.account_authenticate'; diff --git a/src/Module/Contact/Profile.php b/src/Module/Contact/Profile.php index a176a20684..39029a25a8 100644 --- a/src/Module/Contact/Profile.php +++ b/src/Module/Contact/Profile.php @@ -7,31 +7,37 @@ namespace Friendica\Module\Contact; -use Friendica\App; +use Friendica\App\Arguments; +use Friendica\App\BaseURL; +use Friendica\App\Page; use Friendica\BaseModule; -use Friendica\Contact\LocalRelationship; use Friendica\Contact\LocalRelationship\Entity\LocalRelationship as LocalRelationshipEntity; +use Friendica\Contact\LocalRelationship\Repository\LocalRelationship as LocalRelationshipRepository; use Friendica\Content\ContactSelector; use Friendica\Content\Nav; use Friendica\Content\Text\BBCode; use Friendica\Content\Widget; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Database\Database; use Friendica\Database\DBA; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Circle; -use Friendica\Model\Contact; -use Friendica\Module; +use Friendica\Model\Contact as ContactModel; +use Friendica\Model\Contact\User as UserContact; +use Friendica\Module\Contact as ContactModule; use Friendica\Module\Response; +use Friendica\Module\Security\Login; use Friendica\Navigation\SystemMessages; -use Friendica\Network\HTTPException; -use Friendica\User\Settings; +use Friendica\Network\HTTPException\InternalServerErrorException; +use Friendica\Network\HTTPException\NotFoundException; +use Friendica\User\Settings\Repository\UserGServer as UserGServerRepository; use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -39,9 +45,9 @@ use Psr\Log\LoggerInterface; */ class Profile extends BaseModule { - /** @var LocalRelationship\Repository\LocalRelationship */ + /** @var LocalRelationshipRepository */ private $localRelationship; - /** @var App\Page */ + /** @var Page */ private $page; /** @var IManageConfigValues */ private $config; @@ -51,11 +57,28 @@ class Profile extends BaseModule private $systemMessages; /** @var Database */ private $db; - /** @var Settings\Repository\UserGServer */ + /** @var UserGServerRepository */ private $userGServer; + private EventDispatcherInterface $eventDispatcher; - public function __construct(Settings\Repository\UserGServer $userGServer, Database $db, SystemMessages $systemMessages, IHandleUserSessions $session, L10n $l10n, LocalRelationship\Repository\LocalRelationship $localRelationship, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, App\Page $page, IManageConfigValues $config, array $server, array $parameters = []) - { + public function __construct( + UserGServerRepository $userGServer, + EventDispatcherInterface $eventDispatcher, + Database $db, + SystemMessages $systemMessages, + IHandleUserSessions $session, + L10n $l10n, + LocalRelationshipRepository $localRelationship, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + Page $page, + IManageConfigValues $config, + array $server, + array $parameters = [], + ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->localRelationship = $localRelationship; @@ -65,6 +88,7 @@ class Profile extends BaseModule $this->systemMessages = $systemMessages; $this->db = $db; $this->userGServer = $userGServer; + $this->eventDispatcher = $eventDispatcher; } protected function post(array $request = []) @@ -77,12 +101,14 @@ class Profile extends BaseModule // Backward compatibility: The update still needs a user-specific contact ID // Change to user-contact table check by version 2022.03 - $ucid = Contact::getUserContactId($contact_id, $this->session->getLocalUserId()); + $ucid = ContactModel::getUserContactId($contact_id, $this->session->getLocalUserId()); if (!$ucid || !$this->db->exists('contact', ['id' => $ucid, 'deleted' => false])) { return; } - Hook::callAll('contact_edit_post', $request); + $request = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::EDIT_CONTACT_POST, $request), + )->getArray(); $fields = []; @@ -120,14 +146,14 @@ class Profile extends BaseModule } if (isset($request['channel_frequency'])) { - Contact\User::setChannelFrequency($ucid, $this->session->getLocalUserId(), $request['channel_frequency']); + UserContact::setChannelFrequency($ucid, $this->session->getLocalUserId(), $request['channel_frequency']); } if (isset($request['channel_only'])) { - Contact\User::setChannelOnly($ucid, $this->session->getLocalUserId(), $request['channel_only']); + UserContact::setChannelOnly($ucid, $this->session->getLocalUserId(), $request['channel_only']); } - if (!Contact::update($fields, ['id' => $ucid, 'uid' => $this->session->getLocalUserId()])) { + if (!ContactModel::update($fields, ['id' => $ucid, 'uid' => $this->session->getLocalUserId()])) { $this->systemMessages->addNotice($this->t('Failed to update contact record.')); } $this->baseUrl->redirect('contact/' . $contact_id); @@ -136,43 +162,43 @@ class Profile extends BaseModule protected function content(array $request = []): string { if (!$this->session->getLocalUserId()) { - return Module\Security\Login::form($_SERVER['REQUEST_URI']); + return Login::form($_SERVER['REQUEST_URI']); } // Backward compatibility: Ensure to use the public contact when the user contact is provided // Remove by version 2022.03 - $data = Contact::getPublicAndUserContactID(intval($this->parameters['id']), $this->session->getLocalUserId()); + $data = ContactModel::getPublicAndUserContactID(intval($this->parameters['id']), $this->session->getLocalUserId()); if (empty($data)) { - throw new HTTPException\NotFoundException($this->t('Contact not found.')); + throw new NotFoundException($this->t('Contact not found.')); } - $contact = Contact::getById($data['public']); + $contact = ContactModel::getById($data['public']); if (!$this->db->isResult($contact)) { - throw new HTTPException\NotFoundException($this->t('Contact not found.')); + throw new NotFoundException($this->t('Contact not found.')); } // Fetch the protocol from the user's contact. if ($data['user']) { - $usercontact = Contact::getById($data['user'], ['network', 'protocol']); + $usercontact = ContactModel::getById($data['user'], ['network', 'protocol']); if ($this->db->isResult($usercontact)) { $contact['network'] = $usercontact['network']; $contact['protocol'] = $usercontact['protocol']; } } - if (empty($contact['network']) && Contact::isLocal($contact['url']) ) { + if (empty($contact['network']) && ContactModel::isLocal($contact['url']) ) { $contact['network'] = Protocol::DFRN; $contact['protocol'] = Protocol::ACTIVITYPUB; } // Don't display contacts that are about to be deleted if ($contact['deleted'] || $contact['network'] == Protocol::PHANTOM) { - throw new HTTPException\NotFoundException($this->t('Contact not found.')); + throw new NotFoundException($this->t('Contact not found.')); } $localRelationship = $this->localRelationship->getForUserContact($this->session->getLocalUserId(), $contact['id']); - if ($localRelationship->rel === Contact::SELF) { + if ($localRelationship->rel === ContactModel::SELF) { $this->baseUrl->redirect('profile/' . $contact['nick'] . '/profile'); } @@ -180,8 +206,8 @@ class Profile extends BaseModule self::checkFormSecurityTokenRedirectOnError('contact/' . $contact['id'], 'contact_action', 't'); $cmd = $this->parameters['action']; - if ($cmd === 'update' && $localRelationship->rel !== Contact::NOTHING) { - Module\Contact::updateContactFromPoll($contact['id']); + if ($cmd === 'update' && $localRelationship->rel !== ContactModel::NOTHING) { + ContactModule::updateContactFromPoll($contact['id']); } if ($cmd === 'updateprofile') { @@ -191,12 +217,12 @@ class Profile extends BaseModule if ($cmd === 'block') { if ($localRelationship->blocked) { // @TODO Backward compatibility, replace with $localRelationship->unblock() - Contact\User::setBlocked($contact['id'], $this->session->getLocalUserId(), false); + UserContact::setBlocked($contact['id'], $this->session->getLocalUserId(), false); $message = $this->t('Contact has been unblocked'); } else { // @TODO Backward compatibility, replace with $localRelationship->block() - Contact\User::setBlocked($contact['id'], $this->session->getLocalUserId(), true); + UserContact::setBlocked($contact['id'], $this->session->getLocalUserId(), true); $message = $this->t('Contact has been blocked'); } @@ -207,12 +233,12 @@ class Profile extends BaseModule if ($cmd === 'ignore') { if ($localRelationship->ignored) { // @TODO Backward compatibility, replace with $localRelationship->unblock() - Contact\User::setIgnored($contact['id'], $this->session->getLocalUserId(), false); + UserContact::setIgnored($contact['id'], $this->session->getLocalUserId(), false); $message = $this->t('Contact has been unignored'); } else { // @TODO Backward compatibility, replace with $localRelationship->block() - Contact\User::setIgnored($contact['id'], $this->session->getLocalUserId(), true); + UserContact::setIgnored($contact['id'], $this->session->getLocalUserId(), true); $message = $this->t('Contact has been ignored'); } @@ -223,12 +249,12 @@ class Profile extends BaseModule if ($cmd === 'collapse') { if ($localRelationship->collapsed) { // @TODO Backward compatibility, replace with $localRelationship->unblock() - Contact\User::setCollapsed($contact['id'], $this->session->getLocalUserId(), false); + UserContact::setCollapsed($contact['id'], $this->session->getLocalUserId(), false); $message = $this->t('Contact has been uncollapsed'); } else { // @TODO Backward compatibility, replace with $localRelationship->block() - Contact\User::setCollapsed($contact['id'], $this->session->getLocalUserId(), true); + UserContact::setCollapsed($contact['id'], $this->session->getLocalUserId(), true); $message = $this->t('Contact has been collapsed'); } @@ -242,7 +268,7 @@ class Profile extends BaseModule $vcard_widget = Widget\VCard::getHTML($contact); $circles_widget = ''; - if (!in_array($localRelationship->rel, [Contact::NOTHING, Contact::SELF])) { + if (!in_array($localRelationship->rel, [ContactModel::NOTHING, ContactModel::SELF])) { $circles_widget = Circle::sidebarWidget('contact', 'circle', 'full', 'everyone', $data['user']); } @@ -257,9 +283,9 @@ class Profile extends BaseModule ]); switch ($localRelationship->rel) { - case Contact::FRIEND: $relation_text = $this->t('You are mutual friends with %s', $contact['name']); break; - case Contact::FOLLOWER: $relation_text = $this->t('You are sharing with %s', $contact['name']); break; - case Contact::SHARING: $relation_text = $this->t('%s is sharing with you', $contact['name']); break; + case ContactModel::FRIEND: $relation_text = $this->t('You are mutual friends with %s', $contact['name']); break; + case ContactModel::FOLLOWER: $relation_text = $this->t('You are sharing with %s', $contact['name']); break; + case ContactModel::SHARING: $relation_text = $this->t('%s is sharing with you', $contact['name']); break; default: $relation_text = ''; } @@ -268,7 +294,7 @@ class Profile extends BaseModule $relation_text = ''; } - $url = Contact::magicLinkByContact($contact); + $url = ContactModel::magicLinkByContact($contact); if (strpos($url, 'contact/redir/') === 0) { $sparkle = ' class="sparkle" '; } else { @@ -300,7 +326,7 @@ class Profile extends BaseModule $nettype = $this->t('Network type: %s', ContactSelector::networkToName($contact['network'], $contact['protocol'], $contact['gsid'])); // tabs - $tab_str = Module\Contact::getTabsHTML($contact, Module\Contact::TAB_PROFILE); + $tab_str = ContactModule::getTabsHTML($contact, ContactModule::TAB_PROFILE); $lost_contact = (($contact['archive'] && $contact['term-date'] > DBA::NULL_DATETIME && $contact['term-date'] < DateTimeFormat::utcNow()) ? $this->t('Communications lost with this contact!') : ''); @@ -312,10 +338,10 @@ class Profile extends BaseModule $localRelationship->fetchFurtherInformation, $this->t('Fetch information like preview pictures, title and teaser from the feed item. You can activate this if the feed doesn\'t contain much text. Keywords are taken from the meta header in the feed item and are posted as hash tags.'), [ - LocalRelationship\Entity\LocalRelationship::FFI_NONE => $this->t('Disabled'), - LocalRelationship\Entity\LocalRelationship::FFI_INFORMATION => $this->t('Fetch information'), - LocalRelationship\Entity\LocalRelationship::FFI_KEYWORD => $this->t('Fetch keywords'), - LocalRelationship\Entity\LocalRelationship::FFI_BOTH => $this->t('Fetch information and keywords') + LocalRelationshipEntity::FFI_NONE => $this->t('Disabled'), + LocalRelationshipEntity::FFI_INFORMATION => $this->t('Fetch information'), + LocalRelationshipEntity::FFI_KEYWORD => $this->t('Fetch keywords'), + LocalRelationshipEntity::FFI_BOTH => $this->t('Fetch information and keywords') ] ]; } @@ -346,8 +372,8 @@ class Profile extends BaseModule ]; } - $channel_frequency = Contact\User::getChannelFrequency($contact['id'], $this->session->getLocalUserId()); - $channel_only = Contact\User::getChannelOnly($contact['id'], $this->session->getLocalUserId()); + $channel_frequency = UserContact::getChannelFrequency($contact['id'], $this->session->getLocalUserId()); + $channel_only = UserContact::getChannelOnly($contact['id'], $this->session->getLocalUserId()); $poll_interval = null; if ((($contact['network'] == Protocol::FEED) && !$this->config->get('system', 'adjust_poll_frequency')) || ($contact['network'] == Protocol::MAIL)) { @@ -356,12 +382,12 @@ class Profile extends BaseModule $contact_actions = $this->getContactActions($contact, $localRelationship); - if (Contact\User::isIsBlocked($contact['id'], $this->session->getLocalUserId())) { + if (UserContact::isIsBlocked($contact['id'], $this->session->getLocalUserId())) { $relation_text = $this->t('%s has blocked you', $contact['name'] ?: $contact['nick']); unset($contact_actions['follow']); } - if ($localRelationship->rel !== Contact::NOTHING) { + if ($localRelationship->rel !== ContactModel::NOTHING) { $lbl_info1 = $this->t('Contact Information / Notes'); $contact_settings_label = $this->t('Contact Settings'); } else { @@ -407,13 +433,13 @@ class Profile extends BaseModule '$notify_new_posts' => ['notify_new_posts', $this->t('Notification for new posts'), ($localRelationship->notifyNewPosts), $this->t('Send a notification of every new post of this contact')], '$fetch_further_information' => $fetch_further_information, '$ffi_keyword_denylist' => ['ffi_keyword_denylist', $this->t('Keyword Deny List'), $localRelationship->ffiKeywordDenylist, $this->t('Comma separated list of keywords that should not be converted to hashtags, when "Fetch information and keywords" is selected')], - '$photo' => Contact::getPhoto($contact), + '$photo' => ContactModel::getPhoto($contact), '$name' => $contact['name'], '$sparkle' => $sparkle, '$url' => $url, '$profileurllabel' => $this->t('Profile URL'), '$profileurl' => $contact['url'], - '$account_type' => Contact::getAccountType($contact['contact-type']), + '$account_type' => ContactModel::getAccountType($contact['contact-type']), '$location' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['location']), '$location_label' => $this->t('Location:'), '$xmpp' => BBCode::convertForUriId($contact['uri-id'] ?? 0, $contact['xmpp']), @@ -440,18 +466,23 @@ class Profile extends BaseModule '$channel_settings_label' => $this->t('Channel Settings'), '$frequency_label' => $this->t('Frequency of this contact in relevant channels'), '$frequency_description' => $this->t("Depending on the type of the channel not all posts from this contact are displayed. By default, posts need to have a minimum amount of interactions (comments, likes) to show in your channels. On the other hand there can be contacts who flood the channel, so you might want to see only some of their posts. Or you don't want to see their content at all, but you don't want to block or hide the contact completely."), - '$frequency_default' => ['channel_frequency', $this->t('Default frequency'), Contact\User::FREQUENCY_DEFAULT, $this->t('Posts by this contact are displayed in the "for you" channel if you interact often with this contact or if a post reached some level of interaction.'), $channel_frequency == Contact\User::FREQUENCY_DEFAULT], - '$frequency_always' => ['channel_frequency', $this->t('Display all posts of this contact'), Contact\User::FREQUENCY_ALWAYS, $this->t('All posts from this contact will appear on the "for you" channel'), $channel_frequency == Contact\User::FREQUENCY_ALWAYS], - '$frequency_reduced' => ['channel_frequency', $this->t('Display only few posts'), Contact\User::FREQUENCY_REDUCED, $this->t('When a contact creates a lot of posts in a short period, this setting reduces the number of displayed posts in every channel.'), $channel_frequency == Contact\User::FREQUENCY_REDUCED], - '$frequency_never' => ['channel_frequency', $this->t('Never display posts'), Contact\User::FREQUENCY_NEVER, $this->t('Posts from this contact will never be displayed in any channel'), $channel_frequency == Contact\User::FREQUENCY_NEVER], + '$frequency_default' => ['channel_frequency', $this->t('Default frequency'), UserContact::FREQUENCY_DEFAULT, $this->t('Posts by this contact are displayed in the "for you" channel if you interact often with this contact or if a post reached some level of interaction.'), $channel_frequency == UserContact::FREQUENCY_DEFAULT], + '$frequency_always' => ['channel_frequency', $this->t('Display all posts of this contact'), UserContact::FREQUENCY_ALWAYS, $this->t('All posts from this contact will appear on the "for you" channel'), $channel_frequency == UserContact::FREQUENCY_ALWAYS], + '$frequency_reduced' => ['channel_frequency', $this->t('Display only few posts'), UserContact::FREQUENCY_REDUCED, $this->t('When a contact creates a lot of posts in a short period, this setting reduces the number of displayed posts in every channel.'), $channel_frequency == UserContact::FREQUENCY_REDUCED], + '$frequency_never' => ['channel_frequency', $this->t('Never display posts'), UserContact::FREQUENCY_NEVER, $this->t('Posts from this contact will never be displayed in any channel'), $channel_frequency == UserContact::FREQUENCY_NEVER], '$channel_only' => ['channel_only', $this->t('Channel Only'), $channel_only, $this->t('If enabled, posts from this contact will only appear in channels and network streams in circles, but not in the general network stream.')], ]); - $arr = ['contact' => $contact, 'output' => $o]; + $hook_data = [ + 'contact' => $contact, + 'output' => $o, + ]; - Hook::callAll('contact_edit', $arr); + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::EDIT_CONTACT_FORM, $hook_data), + )->getArray(); - return $arr['output']; + return $hook_data['output'] ?? $o; } /** @@ -460,18 +491,18 @@ class Profile extends BaseModule * This includes actions like e.g. 'block', 'hide', 'delete' and others * * @param array $contact Public contact row - * @param LocalRelationship\Entity\LocalRelationship $localRelationship + * * @return array with contact related actions - * @throws HTTPException\InternalServerErrorException + * @throws InternalServerErrorException */ - private function getContactActions(array $contact, LocalRelationship\Entity\LocalRelationship $localRelationship): array + private function getContactActions(array $contact, LocalRelationshipEntity $localRelationship): array { $poll_enabled = in_array($contact['network'], [Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::FEED, Protocol::MAIL]); $contact_actions = []; $formSecurityToken = self::getFormSecurityToken('contact_action'); - if ($localRelationship->rel & Contact::SHARING) { + if ($localRelationship->rel & ContactModel::SHARING) { $contact_actions['unfollow'] = [ 'label' => $this->t('Unfollow'), 'url' => 'contact/unfollow?url=' . urlencode($contact['url']) . '&auto=1', @@ -544,7 +575,7 @@ class Profile extends BaseModule 'id' => 'toggle-collapse', ]; - if (Protocol::supportsRevokeFollow($contact['network']) && in_array($localRelationship->rel, [Contact::FOLLOWER, Contact::FRIEND])) { + if (Protocol::supportsRevokeFollow($contact['network']) && in_array($localRelationship->rel, [ContactModel::FOLLOWER, ContactModel::FRIEND])) { $contact_actions['revoke_follow'] = [ 'label' => $this->t('Revoke Follow'), 'url' => 'contact/' . $contact['id'] . '/revoke', @@ -562,7 +593,7 @@ class Profile extends BaseModule * * @param int $contact_id Id of the contact with uid != 0 * @return void - * @throws HTTPException\InternalServerErrorException + * @throws InternalServerErrorException * @throws \ImagickException */ private function updateContactFromProbe(int $contact_id) @@ -572,6 +603,6 @@ class Profile extends BaseModule } // Update the entry in the contact table - Contact::updateFromProbe($contact_id); + ContactModel::updateFromProbe($contact_id); } } diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 7660a9d2a1..348124b389 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -73,6 +73,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::REVOKE_FOLLOW_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::BLOCK_CONTACT => 'onArrayFilterEvent', ArrayFilterEvent::UNBLOCK_CONTACT => 'onArrayFilterEvent', + ArrayFilterEvent::EDIT_CONTACT_FORM => 'onArrayFilterEvent', + ArrayFilterEvent::EDIT_CONTACT_POST => 'onArrayFilterEvent', ArrayFilterEvent::AVATAR_LOOKUP => 'onArrayFilterEvent', ArrayFilterEvent::ACCOUNT_AUTHENTICATE => 'onArrayFilterEvent', ArrayFilterEvent::ACCOUNT_REGISTER_FORM => 'onArrayFilterEvent', @@ -488,6 +490,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'revoke_follow'], [ArrayFilterEvent::BLOCK_CONTACT, 'block'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'unblock'], + [ArrayFilterEvent::EDIT_CONTACT_FORM, 'contact_edit'], + [ArrayFilterEvent::EDIT_CONTACT_POST, 'contact_edit_post'], [ArrayFilterEvent::AVATAR_LOOKUP, 'avatar_lookup'], [ArrayFilterEvent::ACCOUNT_AUTHENTICATE, 'authenticate'], [ArrayFilterEvent::ACCOUNT_REGISTER_FORM, 'register_form'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index b0c40e5129..a64080198e 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -70,6 +70,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::REVOKE_FOLLOW_CONTACT, 'friendica.data.revoke_follow_contact'], [ArrayFilterEvent::BLOCK_CONTACT, 'friendica.data.block_contact'], [ArrayFilterEvent::UNBLOCK_CONTACT, 'friendica.data.unblock_contact'], + [ArrayFilterEvent::EDIT_CONTACT_FORM, 'friendica.data.edit_contact_form'], + [ArrayFilterEvent::EDIT_CONTACT_POST, 'friendica.data.edit_contact_post'], [ArrayFilterEvent::AVATAR_LOOKUP, 'friendica.data.avatar_lookup'], [ArrayFilterEvent::ACCOUNT_AUTHENTICATE, 'friendica.data.account_authenticate'], [ArrayFilterEvent::ACCOUNT_REGISTER_FORM, 'friendica.data.account_register_form'], From a34a93c0b98c9e3c4890c21b25a3d68bd007206a Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 2 Apr 2025 12:41:22 +0000 Subject: [PATCH 76/91] Create events for networt_tabs and network_content_init hooks --- src/Core/Hooks/HookEventBridge.php | 4 + src/Event/ArrayFilterEvent.php | 4 + src/Module/Conversation/Network.php | 73 ++++++++++++++++--- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 4 + tests/Unit/Event/ArrayFilterEventTest.php | 2 + 5 files changed, 78 insertions(+), 9 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index c74b0a8df2..72204ab11e 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -54,6 +54,8 @@ final class HookEventBridge ArrayFilterEvent::PREPARE_POST_END => 'prepare_body_final', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'photo_upload_form', ArrayFilterEvent::NETWORK_TO_NAME => 'network_to_name', + ArrayFilterEvent::NETWORK_CONTENT_START => 'network_content_init', + ArrayFilterEvent::NETWORK_CONTENT_TABS => 'network_tabs', ArrayFilterEvent::PARSE_LINK => 'parse_link', ArrayFilterEvent::CONVERSATION_START => 'conversation_start', ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'item_by_link', @@ -135,6 +137,8 @@ final class HookEventBridge ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', + ArrayFilterEvent::NETWORK_CONTENT_START => 'onArrayFilterEvent', + ArrayFilterEvent::NETWORK_CONTENT_TABS => 'onArrayFilterEvent', ArrayFilterEvent::PARSE_LINK => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 9435ab37b6..01a9a90675 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -58,6 +58,10 @@ final class ArrayFilterEvent extends Event public const NETWORK_TO_NAME = 'friendica.data.network_to_name'; + public const NETWORK_CONTENT_START = 'friendica.data.network_content_start'; + + public const NETWORK_CONTENT_TABS = 'friendica.data.network_content_tabs'; + public const PARSE_LINK = 'friendica.data.parse_link'; public const CONVERSATION_START = 'friendica.data.conversation_start'; diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index 86c2fcf736..e50d2f4d61 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -39,6 +39,7 @@ use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Worker; use Friendica\Database\DBA; use Friendica\Database\Database; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Contact; use Friendica\Model\Circle; use Friendica\Model\Post; @@ -49,6 +50,7 @@ use Friendica\Network\HTTPException; use Friendica\Navigation\SystemMessages; use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; class Network extends Timeline @@ -90,12 +92,55 @@ class Network extends Timeline protected $community; /** @var NetworkFactory */ protected $networkFactory; + private EventDispatcherInterface $eventDispatcher; - public function __construct(UserDefinedChannelFactory $userDefinedChannel, NetworkFactory $network, CommunityFactory $community, ChannelFactory $channelFactory, UserDefinedChannel $channel, AppHelper $appHelper, TimelineFactory $timeline, SystemMessages $systemMessages, Mode $mode, Conversation $conversation, Page $page, IHandleUserSessions $session, Database $database, IManagePersonalConfigValues $pConfig, IManageConfigValues $config, ICanCache $cache, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { - parent::__construct($channel, $mode, $session, $database, $pConfig, $config, $cache, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + public function __construct( + UserDefinedChannelFactory $userDefinedChannel, + NetworkFactory $network, + CommunityFactory $community, + ChannelFactory $channelFactory, + UserDefinedChannel $channel, + AppHelper $appHelper, + EventDispatcherInterface $eventDispatcher, + TimelineFactory $timeline, + SystemMessages $systemMessages, + Mode $mode, + Conversation $conversation, + Page $page, + IHandleUserSessions $session, + Database $database, + IManagePersonalConfigValues $pConfig, + IManageConfigValues $config, + ICanCache $cache, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [] + ) { + parent::__construct( + $channel, + $mode, + $session, + $database, + $pConfig, + $config, + $cache, + $l10n, + $baseUrl, + $args, + $logger, + $profiler, + $response, + $server, + $parameters, + ); $this->appHelper = $appHelper; + $this->eventDispatcher = $eventDispatcher; $this->timeline = $timeline; $this->systemMessages = $systemMessages; $this->conversation = $conversation; @@ -116,8 +161,13 @@ class Network extends Timeline $module = 'network'; - $arr = ['query' => $this->args->getQueryString()]; - Hook::callAll('network_content_init', $arr); + $hook_data = [ + 'query' => $this->args->getQueryString(), + ]; + + $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_START, $hook_data) + ); $o = ''; @@ -275,19 +325,24 @@ class Network extends Timeline $tabs = array_merge($tabs, $this->getTabArray($this->community->getTimelines(true), 'network', 'channel')); } - $arr = ['tabs' => $tabs]; - Hook::callAll('network_tabs', $arr); + $hook_data = [ + 'tabs' => $tabs, + ]; + + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::NETWORK_CONTENT_TABS, $hook_data) + )->getArray(); if (!empty($network_timelines)) { $tabs = []; - foreach ($arr['tabs'] as $tab) { + foreach ($hook_data['tabs'] as $tab) { if (in_array($tab['code'], $network_timelines)) { $tabs[] = $tab; } } } else { - $tabs = $arr['tabs']; + $tabs = $hook_data['tabs']; } $tpl = Renderer::getMarkupTemplate('common_tabs.tpl'); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 348124b389..7b97e76a02 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -43,6 +43,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', + ArrayFilterEvent::NETWORK_CONTENT_START => 'onArrayFilterEvent', + ArrayFilterEvent::NETWORK_CONTENT_TABS => 'onArrayFilterEvent', ArrayFilterEvent::PARSE_LINK => 'onArrayFilterEvent', ArrayFilterEvent::CONVERSATION_START => 'onArrayFilterEvent', ArrayFilterEvent::FETCH_ITEM_BY_LINK => 'onArrayFilterEvent', @@ -465,6 +467,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::PREPARE_POST_END, 'prepare_body_final'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'], + [ArrayFilterEvent::NETWORK_CONTENT_START, 'network_content_init'], + [ArrayFilterEvent::NETWORK_CONTENT_TABS, 'network_tabs'], [ArrayFilterEvent::PARSE_LINK, 'parse_link'], [ArrayFilterEvent::CONVERSATION_START, 'conversation_start'], [ArrayFilterEvent::FETCH_ITEM_BY_LINK, 'item_by_link'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index a64080198e..4e1a800435 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -40,6 +40,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PREPARE_POST_END, 'friendica.data.prepare_post_end'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'], [ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'], + [ArrayFilterEvent::NETWORK_CONTENT_START, 'friendica.data.network_content_start'], + [ArrayFilterEvent::NETWORK_CONTENT_TABS, 'friendica.data.network_content_tabs'], [ArrayFilterEvent::PARSE_LINK, 'friendica.data.parse_link'], [ArrayFilterEvent::CONVERSATION_START, 'friendica.data.conversation_start'], [ArrayFilterEvent::FETCH_ITEM_BY_LINK, 'friendica.data.fetch_item_by_link'], From 2a7ebc860c5640aaea8b9d8e52affad3f85ce858 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 9 Apr 2025 14:25:00 +0000 Subject: [PATCH 77/91] Create event for moderation_users_tabs hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/ArrayFilterEvent.php | 2 ++ src/Module/Moderation/BaseUsers.php | 20 ++++++++++++++++--- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 72204ab11e..6dc6aeb667 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -71,6 +71,7 @@ final class HookEventBridge ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'profile_sidebar_enter', ArrayFilterEvent::PROFILE_SIDEBAR => 'profile_sidebar', ArrayFilterEvent::PROFILE_TABS => 'profile_tabs', + ArrayFilterEvent::MODERATION_USERS_TABS => 'moderation_users_tabs', ArrayFilterEvent::OEMBED_FETCH_END => 'oembed_fetch_url', ArrayFilterEvent::PAGE_INFO => 'page_info_data', ArrayFilterEvent::SMILEY_LIST => 'smilie', @@ -154,6 +155,7 @@ final class HookEventBridge ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent', + ArrayFilterEvent::MODERATION_USERS_TABS => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 01a9a90675..cb14052bb2 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -92,6 +92,8 @@ final class ArrayFilterEvent extends Event public const PROFILE_TABS = 'friendica.data.profile_tabs'; + public const MODERATION_USERS_TABS = 'friendica.data.moderation_users_tabs'; + public const OEMBED_FETCH_END = 'friendica.data.oembed_fetch_end'; public const PAGE_INFO = 'friendica.data.page_info'; diff --git a/src/Module/Moderation/BaseUsers.php b/src/Module/Moderation/BaseUsers.php index fcf4b4aa16..6f9e4a800d 100644 --- a/src/Module/Moderation/BaseUsers.php +++ b/src/Module/Moderation/BaseUsers.php @@ -16,6 +16,8 @@ use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Database\Database; +use Friendica\DI; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Register; use Friendica\Model\User; use Friendica\Module\BaseModeration; @@ -95,11 +97,23 @@ abstract class BaseUsers extends BaseModeration 'accesskey' => 'd', ], ]; - $tabs_arr = ['tabs' => $tabs, 'selectedTab' => $selectedTab]; - Hook::callAll('moderation_users_tabs', $tabs_arr); + + $hook_data = [ + 'tabs' => $tabs, + 'selectedTab' => $selectedTab, + ]; + + $eventDispatcher = DI::eventDispatcher(); + + $hook_data = $eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::MODERATION_USERS_TABS, $hook_data), + )->getArray(); + + $tabs = $hook_data['tabs'] ?? $tabs; $tpl = Renderer::getMarkupTemplate('common_tabs.tpl'); - return Renderer::replaceMacros($tpl, ['$tabs' => $tabs_arr['tabs'], '$more' => $this->t('More')]); + + return Renderer::replaceMacros($tpl, ['$tabs' => $tabs, '$more' => $this->t('More')]); } protected function setupUserCallback(): \Closure diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 7b97e76a02..ae98a2fc0e 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -60,6 +60,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent', + ArrayFilterEvent::MODERATION_USERS_TABS => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', @@ -483,6 +484,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'profile_sidebar'], [ArrayFilterEvent::PROFILE_TABS, 'profile_tabs'], + [ArrayFilterEvent::MODERATION_USERS_TABS, 'moderation_users_tabs'], [ArrayFilterEvent::PAGE_INFO, 'page_info_data'], [ArrayFilterEvent::SMILEY_LIST, 'smilie'], [ArrayFilterEvent::JOT_NETWORKS, 'jot_networks'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 4e1a800435..4f20c37543 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -57,6 +57,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, 'friendica.data.profile_sidebar_entry'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'friendica.data.profile_sidebar'], [ArrayFilterEvent::PROFILE_TABS, 'friendica.data.profile_tabs'], + [ArrayFilterEvent::MODERATION_USERS_TABS, 'friendica.data.moderation_users_tabs'], [ArrayFilterEvent::OEMBED_FETCH_END, 'friendica.data.oembed_fetch_end'], [ArrayFilterEvent::PAGE_INFO, 'friendica.data.page_info'], [ArrayFilterEvent::SMILEY_LIST, 'friendica.data.smiley_list'], From f08aef86f181c2cfa1a7571ef68ee463c1101347 Mon Sep 17 00:00:00 2001 From: Art4 Date: Wed, 9 Apr 2025 14:38:54 +0000 Subject: [PATCH 78/91] set EventDispatcher via constructor injection --- src/Module/Moderation/BaseUsers.php | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Module/Moderation/BaseUsers.php b/src/Module/Moderation/BaseUsers.php index 6f9e4a800d..283fa74ec2 100644 --- a/src/Module/Moderation/BaseUsers.php +++ b/src/Module/Moderation/BaseUsers.php @@ -11,12 +11,10 @@ use Friendica\App\Arguments; use Friendica\App\BaseURL; use Friendica\App\Page; use Friendica\AppHelper; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Database\Database; -use Friendica\DI; use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Register; use Friendica\Model\User; @@ -26,6 +24,7 @@ use Friendica\Navigation\SystemMessages; use Friendica\Network\HTTPException\ServiceUnavailableException; use Friendica\Util\Profiler; use Friendica\Util\Temporal; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; abstract class BaseUsers extends BaseModeration @@ -33,11 +32,28 @@ abstract class BaseUsers extends BaseModeration /** @var Database */ protected $database; - public function __construct(Database $database, Page $page, AppHelper $appHelper, SystemMessages $systemMessages, IHandleUserSessions $session, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { + private EventDispatcherInterface $eventDispatcher; + + public function __construct( + Database $database, + EventDispatcherInterface $eventDispatcher, + Page $page, + AppHelper $appHelper, + SystemMessages $systemMessages, + IHandleUserSessions $session, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [], + ) { parent::__construct($page, $appHelper, $systemMessages, $session, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->database = $database; + $this->eventDispatcher = $eventDispatcher; } /** @@ -103,9 +119,7 @@ abstract class BaseUsers extends BaseModeration 'selectedTab' => $selectedTab, ]; - $eventDispatcher = DI::eventDispatcher(); - - $hook_data = $eventDispatcher->dispatch( + $hook_data = $this->eventDispatcher->dispatch( new ArrayFilterEvent(ArrayFilterEvent::MODERATION_USERS_TABS, $hook_data), )->getArray(); From ff3c4046e0e4b58a30ce1f3c78e22947329e99cc Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 10 Apr 2025 11:04:10 +0000 Subject: [PATCH 79/91] Create event for lockview_content hook --- src/Core/Hooks/HookEventBridge.php | 16 ++++++++ src/Event/ArrayFilterEvent.php | 2 + src/Module/Privacy/PermissionTooltip.php | 40 +++++++++++++++---- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 24 +++++++++++ tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 76 insertions(+), 7 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 6dc6aeb667..03f8ced58c 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -43,6 +43,7 @@ final class HookEventBridge ArrayFilterEvent::NAV_INFO => 'nav_info', ArrayFilterEvent::FEATURE_ENABLED => 'isEnabled', ArrayFilterEvent::FEATURE_GET => 'get', + ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT => 'lockview_content', ArrayFilterEvent::INSERT_POST_LOCAL_START => 'post_local_start', ArrayFilterEvent::INSERT_POST_LOCAL => 'post_local', ArrayFilterEvent::INSERT_POST_LOCAL_END => 'post_local_end', @@ -127,6 +128,7 @@ final class HookEventBridge ArrayFilterEvent::NAV_INFO => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent', + ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT => 'onPermissionTooltipContentEvent', ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_LOCAL => 'onInsertPostLocalEvent', ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onInsertPostLocalEndEvent', @@ -215,6 +217,20 @@ final class HookEventBridge ); } + /** + * Map the PERMISSION_TOOLTIP_CONTENT event to `lockview_content` hook + */ + public static function onPermissionTooltipContentEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $model = (array) $data['model'] ?? []; + + $data['model'] = static::callHook($event->getName(), $model); + + $event->setArray($data); + } + /** * Map the INSERT_POST_LOCAL event to `post_local` hook */ diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index cb14052bb2..f1ba9887d9 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -24,6 +24,8 @@ final class ArrayFilterEvent extends Event public const FEATURE_GET = 'friendica.data.feature_get'; + public const PERMISSION_TOOLTIP_CONTENT = 'friendica.data.permission_tooltip_content'; + public const INSERT_POST_LOCAL_START = 'friendica.data.insert_post_local_start'; public const INSERT_POST_LOCAL = 'friendica.data.insert_post_local'; diff --git a/src/Module/Privacy/PermissionTooltip.php b/src/Module/Privacy/PermissionTooltip.php index ef4ba9f7bd..6f77daaec1 100644 --- a/src/Module/Privacy/PermissionTooltip.php +++ b/src/Module/Privacy/PermissionTooltip.php @@ -7,14 +7,16 @@ namespace Friendica\Module\Privacy; -use Friendica\App; +use Friendica\App\Arguments; +use Friendica\App\BaseURL; +use Friendica\BaseModule; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Database\Database; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model; use Friendica\Module\Response; use Friendica\Network\HTTPException; @@ -23,21 +25,37 @@ use Friendica\Privacy\Entity; use Friendica\Security\PermissionSet\Repository\PermissionSet; use Friendica\Util\ACLFormatter; use Friendica\Util\Profiler; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** * Outputs the permission tooltip HTML content for the provided item, photo or event id. */ -class PermissionTooltip extends \Friendica\BaseModule +class PermissionTooltip extends BaseModule { private Database $dba; private ACLFormatter $aclFormatter; private IHandleUserSessions $session; private IManageConfigValues $config; private PermissionSet $permissionSet; + private EventDispatcherInterface $eventDispatcher; - public function __construct(PermissionSet $permissionSet, IManageConfigValues $config, IHandleUserSessions $session, ACLFormatter $aclFormatter, Database $dba, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { + public function __construct( + PermissionSet $permissionSet, + IManageConfigValues $config, + IHandleUserSessions $session, + ACLFormatter $aclFormatter, + Database $dba, + EventDispatcherInterface $eventDispatcher, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [], + ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->dba = $dba; @@ -45,6 +63,7 @@ class PermissionTooltip extends \Friendica\BaseModule $this->session = $session; $this->config = $config; $this->permissionSet = $permissionSet; + $this->eventDispatcher = $eventDispatcher; } protected function rawContent(array $request = []) @@ -87,8 +106,15 @@ class PermissionTooltip extends \Friendica\BaseModule throw new HttpException\NotFoundException($this->t('Model not found')); } - // Kept for backwards compatibility - Hook::callAll('lockview_content', $model); + $hook_data = [ + 'model' => $model, + ]; + + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT, $hook_data), + )->getArray(); + + $model = $hook_data['model'] ?? $model; $aclReceivers = new Entity\AclReceivers(); $addressedReceivers = new Entity\AddressedReceivers(); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index ae98a2fc0e..a07907e427 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -32,6 +32,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::NAV_INFO => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_ENABLED => 'onArrayFilterEvent', ArrayFilterEvent::FEATURE_GET => 'onArrayFilterEvent', + ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT => 'onPermissionTooltipContentEvent', ArrayFilterEvent::INSERT_POST_LOCAL_START => 'onArrayFilterEvent', ArrayFilterEvent::INSERT_POST_LOCAL => 'onInsertPostLocalEvent', ArrayFilterEvent::INSERT_POST_LOCAL_END => 'onInsertPostLocalEndEvent', @@ -209,6 +210,28 @@ class HookEventBridgeTest extends TestCase HookEventBridge::onCollectRoutesEvent($event); } + public function testOnPermissionTooltipContentEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT, ['model' => ['uid' => -1]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, array $data): array { + $this->assertSame('lockview_content', $name); + $this->assertSame(['uid' => -1], $data); + + return ['uid' => 123]; + }); + + HookEventBridge::onPermissionTooltipContentEvent($event); + + $this->assertSame( + ['model' => ['uid' => 123]], + $event->getArray(), + ); + } + public function testOnInsertPostLocalEventCallsHookWithCorrectValue(): void { $event = new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL, ['item' => ['id' => -1]]); @@ -230,6 +253,7 @@ class HookEventBridgeTest extends TestCase $event->getArray(), ); } + public function testOnInsertPostLocalEndEventCallsHookWithCorrectValue(): void { $event = new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_LOCAL_END, ['item' => ['id' => -1]]); diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 4f20c37543..69a8d6829d 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -29,6 +29,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::NAV_INFO, 'friendica.data.nav_info'], [ArrayFilterEvent::FEATURE_ENABLED, 'friendica.data.feature_enabled'], [ArrayFilterEvent::FEATURE_GET, 'friendica.data.feature_get'], + [ArrayFilterEvent::PERMISSION_TOOLTIP_CONTENT, 'friendica.data.permission_tooltip_content'], [ArrayFilterEvent::INSERT_POST_LOCAL_START, 'friendica.data.insert_post_local_start'], [ArrayFilterEvent::INSERT_POST_LOCAL, 'friendica.data.insert_post_local'], [ArrayFilterEvent::INSERT_POST_LOCAL_END, 'friendica.data.insert_post_local_end'], From 39439fe26b3bf299344d3079af9ef70c1d4da6bb Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 10 Apr 2025 11:13:43 +0000 Subject: [PATCH 80/91] Fix missing dependency for EventDispatcher --- src/Module/Ping/Network.php | 59 +++++++++++++++++++++++++++++++++++-- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/src/Module/Ping/Network.php b/src/Module/Ping/Network.php index f8c41a2e1c..03c6b8eeac 100644 --- a/src/Module/Ping/Network.php +++ b/src/Module/Ping/Network.php @@ -31,6 +31,7 @@ use Friendica\Module\Conversation\Network as NetworkModule; use Friendica\Module\Response; use Friendica\Navigation\SystemMessages; use Friendica\Util\Profiler; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; class Network extends NetworkModule @@ -40,9 +41,61 @@ class Network extends NetworkModule */ private $lock; - public function __construct(ICanLock $lock, UserDefinedChannelFactory $userDefinedChannel, NetworkFactory $network, CommunityFactory $community, ChannelFactory $channelFactory, UserDefinedChannel $channel, AppHelper $appHelper, TimelineFactory $timeline, SystemMessages $systemMessages, Mode $mode, Conversation $conversation, Page $page, IHandleUserSessions $session, Database $database, IManagePersonalConfigValues $pConfig, IManageConfigValues $config, ICanCache $cache, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { - parent::__construct($userDefinedChannel, $network, $community, $channelFactory, $channel, $appHelper, $timeline, $systemMessages, $mode, $conversation, $page, $session, $database, $pConfig, $config, $cache, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); + public function __construct( + ICanLock $lock, + UserDefinedChannelFactory $userDefinedChannel, + NetworkFactory $network, + CommunityFactory $community, + ChannelFactory $channelFactory, + UserDefinedChannel $channel, + AppHelper $appHelper, + EventDispatcherInterface $eventDispatcher, + TimelineFactory $timeline, + SystemMessages $systemMessages, + Mode $mode, + Conversation $conversation, + Page $page, + IHandleUserSessions $session, + Database $database, + IManagePersonalConfigValues $pConfig, + IManageConfigValues $config, + ICanCache $cache, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [], + ) { + parent::__construct( + $userDefinedChannel, + $network, + $community, + $channelFactory, + $channel, + $appHelper, + $eventDispatcher, + $timeline, + $systemMessages, + $mode, + $conversation, + $page, + $session, + $database, + $pConfig, + $config, + $cache, + $l10n, + $baseUrl, + $args, + $logger, + $profiler, + $response, + $server, + $parameters + ); $this->lock = $lock; } From 86ebbecff5240319cf8cc8945bcfcdb1696720bf Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 10 Apr 2025 14:17:20 +0000 Subject: [PATCH 81/91] Create event for photo upload hooks --- src/Core/Hooks/HookEventBridge.php | 33 +++++++ src/Event/ArrayFilterEvent.php | 6 ++ src/Module/Profile/Photos.php | 93 ++++++++++++++----- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 43 +++++++++ tests/Unit/Event/ArrayFilterEventTest.php | 3 + 5 files changed, 155 insertions(+), 23 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 03f8ced58c..df2a17322e 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -54,6 +54,9 @@ final class HookEventBridge ArrayFilterEvent::PREPARE_POST => 'prepare_body', ArrayFilterEvent::PREPARE_POST_END => 'prepare_body_final', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'photo_upload_form', + ArrayFilterEvent::PHOTO_UPLOAD_START => 'photo_post_init', + ArrayFilterEvent::PHOTO_UPLOAD => 'photo_post_file', + ArrayFilterEvent::PHOTO_UPLOAD_END => 'photo_post_end', ArrayFilterEvent::NETWORK_TO_NAME => 'network_to_name', ArrayFilterEvent::NETWORK_CONTENT_START => 'network_content_init', ArrayFilterEvent::NETWORK_CONTENT_TABS => 'network_tabs', @@ -139,6 +142,9 @@ final class HookEventBridge ArrayFilterEvent::PREPARE_POST => 'onArrayFilterEvent', ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', + ArrayFilterEvent::PHOTO_UPLOAD_START => 'onPhotoUploadStartEvent', + ArrayFilterEvent::PHOTO_UPLOAD => 'onArrayFilterEvent', + ArrayFilterEvent::PHOTO_UPLOAD_END => 'onPhotoUploadEndEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_CONTENT_START => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_CONTENT_TABS => 'onArrayFilterEvent', @@ -273,6 +279,33 @@ final class HookEventBridge $event->setArray($data); } + /** + * Map the PHOTO_UPLOAD_START event to `photo_post_init` hook + */ + public static function onPhotoUploadStartEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $request = (array) $data['request'] ?? []; + + $data['request'] = static::callHook($event->getName(), $request); + + $event->setArray($data); + } + + /** + * Map the PHOTO_UPLOAD_END event to `photo_post_end` hook + */ + public static function onPhotoUploadEndEvent(ArrayFilterEvent $event): void + { + $data = $event->getArray(); + + $id = (int) $data['id'] ?? 0; + + // one-way-event: we don't care about the returned value + static::callHook($event->getName(), $id); + } + /** * Map the PROFILE_SIDEBAR_ENTRY event to `profile_sidebar_enter` hook */ diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index f1ba9887d9..7c772f4132 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -58,6 +58,12 @@ final class ArrayFilterEvent extends Event public const PHOTO_UPLOAD_FORM = 'friendica.data.photo_upload_form'; + public const PHOTO_UPLOAD_START = 'friendica.data.photo_upload_start'; + + public const PHOTO_UPLOAD = 'friendica.data.photo_upload'; + + public const PHOTO_UPLOAD_END = 'friendica.data.photo_upload_end'; + public const NETWORK_TO_NAME = 'friendica.data.network_to_name'; public const NETWORK_CONTENT_START = 'friendica.data.network_content_start'; diff --git a/src/Module/Profile/Photos.php b/src/Module/Profile/Photos.php index a377cd6dc3..29ece42ef9 100644 --- a/src/Module/Profile/Photos.php +++ b/src/Module/Profile/Photos.php @@ -14,12 +14,12 @@ use Friendica\AppHelper; use Friendica\Content\Feature; use Friendica\Content\Pager; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\System; use Friendica\Database\Database; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Contact; use Friendica\Model\Item; use Friendica\Model\Photo; @@ -34,6 +34,7 @@ use Friendica\Util\DateTimeFormat; use Friendica\Util\Images; use Friendica\Util\Profiler; use Friendica\Util\Strings; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; class Photos extends \Friendica\Module\BaseProfile @@ -52,11 +53,28 @@ class Photos extends \Friendica\Module\BaseProfile private $systemMessages; /** @var ACLFormatter */ private $aclFormatter; + private EventDispatcherInterface $eventDispatcher; /** @var array owner-view record */ private $owner; - public function __construct(ACLFormatter $aclFormatter, SystemMessages $systemMessages, Database $database, AppHelper $appHelper, IManageConfigValues $config, Page $page, IHandleUserSessions $session, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { + public function __construct( + ACLFormatter $aclFormatter, + SystemMessages $systemMessages, + Database $database, + AppHelper $appHelper, + IManageConfigValues $config, + Page $page, + IHandleUserSessions $session, + EventDispatcherInterface $eventDispatcher, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [], + ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->session = $session; @@ -66,6 +84,7 @@ class Photos extends \Friendica\Module\BaseProfile $this->database = $database; $this->systemMessages = $systemMessages; $this->aclFormatter = $aclFormatter; + $this->eventDispatcher = $eventDispatcher; $owner = Profile::load($this->appHelper, $this->parameters['nickname'] ?? '', false); if (!$owner || $owner['account_removed'] || $owner['account_expired']) { @@ -97,8 +116,16 @@ class Photos extends \Friendica\Module\BaseProfile $str_contact_allow .= $this->aclFormatter->toString(Contact::getPublicIdByUserId($this->owner['uid'])); } + $hook_data = [ + 'request' => $request, + ]; + // default post action - upload a photo - Hook::callAll('photo_post_init', $request); + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_START, $hook_data), + )->getArray(); + + $request = $hook_data['request'] ?? $request; // Determine the album to use $album = trim($request['album'] ?? ''); @@ -127,19 +154,27 @@ class Photos extends \Friendica\Module\BaseProfile $visible = 0; } - $ret = ['src' => '', 'filename' => '', 'filesize' => 0, 'type' => '']; + $hook_data = [ + 'src' => '', + 'filename' => '', + 'filesize' => 0, + 'type' => '', + ]; + + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD, $hook_data), + )->getArray(); + $src = null; $filename = ''; $filesize = 0; $type = ''; - Hook::callAll('photo_post_file', $ret); - - if (!empty($ret['src']) && !empty($ret['filesize'])) { - $src = $ret['src']; - $filename = $ret['filename']; - $filesize = $ret['filesize']; - $type = $ret['type']; + if (!empty($hook_data['src']) && !empty($hook_data['filesize'])) { + $src = $hook_data['src']; + $filename = $hook_data['filename']; + $filesize = $hook_data['filesize']; + $type = $hook_data['type']; $error = UPLOAD_ERR_OK; } elseif (!empty($_FILES['userfile'])) { $src = $_FILES['userfile']['tmp_name']; @@ -176,8 +211,10 @@ class Photos extends \Friendica\Module\BaseProfile @unlink($src); } - $foo = 0; - Hook::callAll('photo_post_end', $foo); + $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_END, ['id' => 0]), + ); + return; } @@ -188,16 +225,22 @@ class Photos extends \Friendica\Module\BaseProfile if ($maximagesize && ($filesize > $maximagesize)) { $this->systemMessages->addNotice($this->t('Image exceeds size limit of %s', Strings::formatBytes($maximagesize))); @unlink($src); - $foo = 0; - Hook::callAll('photo_post_end', $foo); + + $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_END, ['id' => 0]), + ); + return; } if (!$filesize) { $this->systemMessages->addNotice($this->t('Image file is empty.')); @unlink($src); - $foo = 0; - Hook::callAll('photo_post_end', $foo); + + $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_END, ['id' => 0]), + ); + return; } @@ -211,8 +254,11 @@ class Photos extends \Friendica\Module\BaseProfile $this->logger->notice('unable to process image'); $this->systemMessages->addNotice($this->t('Unable to process image.')); @unlink($src); - $foo = 0; - Hook::callAll('photo_post_end',$foo); + + $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_END, ['id' => 0]), + ); + return; } @@ -274,10 +320,11 @@ class Photos extends \Friendica\Module\BaseProfile // Update the photo albums cache Photo::clearAlbumCache($this->owner['uid']); - Hook::callAll('photo_post_end', $item_id); - - // addon uploaders should call "exit()" within the photo_post_end hook + // addon uploaders should call "exit()" within the PHOTO_UPLOAD_END event // if they do not wish to be redirected + $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_END, ['id' => $item_id]), + ); $this->baseUrl->redirect($this->session->get('photo_return') ?? 'profile/' . $this->owner['nickname'] . '/photos'); } diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index a07907e427..f30a1c2fef 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -43,6 +43,9 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PREPARE_POST => 'onArrayFilterEvent', ArrayFilterEvent::PREPARE_POST_END => 'onArrayFilterEvent', ArrayFilterEvent::PHOTO_UPLOAD_FORM => 'onArrayFilterEvent', + ArrayFilterEvent::PHOTO_UPLOAD_START => 'onPhotoUploadStartEvent', + ArrayFilterEvent::PHOTO_UPLOAD => 'onArrayFilterEvent', + ArrayFilterEvent::PHOTO_UPLOAD_END => 'onPhotoUploadEndEvent', ArrayFilterEvent::NETWORK_TO_NAME => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_CONTENT_START => 'onArrayFilterEvent', ArrayFilterEvent::NETWORK_CONTENT_TABS => 'onArrayFilterEvent', @@ -298,6 +301,45 @@ class HookEventBridgeTest extends TestCase ); } + public function testOnPhotoUploadStartEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_START, ['request' => ['album' => -1]]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, array $data): array { + $this->assertSame('photo_post_init', $name); + $this->assertSame(['album' => -1], $data); + + return ['album' => 123]; + }); + + HookEventBridge::onPhotoUploadStartEvent($event); + + $this->assertSame( + ['request' => ['album' => 123]], + $event->getArray(), + ); + } + + public function testOnPhotoUploadEndEventCallsHookWithCorrectValue(): void + { + $event = new ArrayFilterEvent(ArrayFilterEvent::PHOTO_UPLOAD_END, ['id' => -1]); + + $reflectionProperty = new \ReflectionProperty(HookEventBridge::class, 'mockedCallHook'); + $reflectionProperty->setAccessible(true); + + $reflectionProperty->setValue(null, function (string $name, int $data): int { + $this->assertSame('photo_post_end', $name); + $this->assertSame(-1, $data); + + return 123; + }); + + HookEventBridge::onPhotoUploadEndEvent($event); + } + public function testOnProfileSidebarEntryEventCallsHookWithCorrectValue(): void { $event = new ArrayFilterEvent(ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, ['profile' => ['uid' => 0, 'name' => 'original']]); @@ -491,6 +533,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::PREPARE_POST, 'prepare_body'], [ArrayFilterEvent::PREPARE_POST_END, 'prepare_body_final'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'photo_upload_form'], + [ArrayFilterEvent::PHOTO_UPLOAD, 'photo_post_file'], [ArrayFilterEvent::NETWORK_TO_NAME, 'network_to_name'], [ArrayFilterEvent::NETWORK_CONTENT_START, 'network_content_init'], [ArrayFilterEvent::NETWORK_CONTENT_TABS, 'network_tabs'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 69a8d6829d..9ecdb6feee 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -40,6 +40,9 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PREPARE_POST, 'friendica.data.prepare_post'], [ArrayFilterEvent::PREPARE_POST_END, 'friendica.data.prepare_post_end'], [ArrayFilterEvent::PHOTO_UPLOAD_FORM, 'friendica.data.photo_upload_form'], + [ArrayFilterEvent::PHOTO_UPLOAD_START, 'friendica.data.photo_upload_start'], + [ArrayFilterEvent::PHOTO_UPLOAD, 'friendica.data.photo_upload'], + [ArrayFilterEvent::PHOTO_UPLOAD_END, 'friendica.data.photo_upload_end'], [ArrayFilterEvent::NETWORK_TO_NAME, 'friendica.data.network_to_name'], [ArrayFilterEvent::NETWORK_CONTENT_START, 'friendica.data.network_content_start'], [ArrayFilterEvent::NETWORK_CONTENT_TABS, 'friendica.data.network_content_tabs'], From 3ea20e9eee97e1aa35d3dfa4bf3eeced5d114418 Mon Sep 17 00:00:00 2001 From: Art4 Date: Thu, 10 Apr 2025 14:36:57 +0000 Subject: [PATCH 82/91] create event for profile_advanced hook --- src/Core/Hooks/HookEventBridge.php | 2 ++ src/Event/HtmlFilterEvent.php | 2 ++ src/Module/Profile/Profile.php | 28 ++++++++++++++++--- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 ++ tests/Unit/Event/HtmlFilterEventTest.php | 1 + 5 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index df2a17322e..9d20a36e89 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -113,6 +113,7 @@ final class HookEventBridge HtmlFilterEvent::PAGE_END => 'page_end', HtmlFilterEvent::MOD_HOME_CONTENT => 'home_content', HtmlFilterEvent::MOD_ABOUT_CONTENT => 'about_hook', + HtmlFilterEvent::MOD_PROFILE_CONTENT => 'profile_advanced', HtmlFilterEvent::JOT_TOOL => 'jot_tool', HtmlFilterEvent::CONTACT_BLOCK_END => 'contact_block_end', ]; @@ -201,6 +202,7 @@ final class HookEventBridge HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent', HtmlFilterEvent::MOD_HOME_CONTENT => 'onHtmlFilterEvent', HtmlFilterEvent::MOD_ABOUT_CONTENT => 'onHtmlFilterEvent', + HtmlFilterEvent::MOD_PROFILE_CONTENT => 'onHtmlFilterEvent', HtmlFilterEvent::JOT_TOOL => 'onHtmlFilterEvent', HtmlFilterEvent::CONTACT_BLOCK_END => 'onHtmlFilterEvent', ]; diff --git a/src/Event/HtmlFilterEvent.php b/src/Event/HtmlFilterEvent.php index 9e30d6d656..1275e0791d 100644 --- a/src/Event/HtmlFilterEvent.php +++ b/src/Event/HtmlFilterEvent.php @@ -30,6 +30,8 @@ final class HtmlFilterEvent extends Event public const MOD_ABOUT_CONTENT = 'friendica.html.mod_about_content'; + public const MOD_PROFILE_CONTENT = 'friendica.html.mod_profile_content'; + public const JOT_TOOL = 'friendica.html.jot_tool'; public const CONTACT_BLOCK_END = 'friendica.html.contact_block_end'; diff --git a/src/Module/Profile/Profile.php b/src/Module/Profile/Profile.php index e84003e4dc..b3f15f5f44 100644 --- a/src/Module/Profile/Profile.php +++ b/src/Module/Profile/Profile.php @@ -17,13 +17,13 @@ use Friendica\Content\Nav; use Friendica\Content\Text\BBCode; use Friendica\Content\Text\HTML; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Database\Database; use Friendica\Database\DBA; +use Friendica\Event\HtmlFilterEvent; use Friendica\Model\Contact; use Friendica\Model\Profile as ProfileModel; use Friendica\Model\Tag; @@ -40,6 +40,7 @@ use Friendica\Util\Network; use Friendica\Util\Profiler; use Friendica\Util\Temporal; use GuzzleHttp\Psr7\Uri; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; class Profile extends BaseProfile @@ -56,9 +57,25 @@ class Profile extends BaseProfile private $page; /** @var ProfileField */ private $profileField; + private EventDispatcherInterface $eventDispatcher; - public function __construct(ProfileField $profileField, Page $page, IManageConfigValues $config, IHandleUserSessions $session, AppHelper $appHelper, Database $database, L10n $l10n, BaseURL $baseUrl, Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { + public function __construct( + ProfileField $profileField, + Page $page, + IManageConfigValues $config, + IHandleUserSessions $session, + AppHelper $appHelper, + Database $database, + EventDispatcherInterface $eventDispatcher, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [], + ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->database = $database; @@ -67,6 +84,7 @@ class Profile extends BaseProfile $this->config = $config; $this->page = $page; $this->profileField = $profileField; + $this->eventDispatcher = $eventDispatcher; } protected function rawContent(array $request = []) @@ -282,7 +300,9 @@ class Profile extends BaseProfile ], ]); - Hook::callAll('profile_advanced', $o); + $o = $this->eventDispatcher->dispatch( + new HTmlFilterEvent(HtmlFilterEvent::MOD_PROFILE_CONTENT, $o), + )->getHtml(); return $o; } diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index f30a1c2fef..6c5c5fecf8 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -102,6 +102,7 @@ class HookEventBridgeTest extends TestCase HtmlFilterEvent::PAGE_END => 'onHtmlFilterEvent', HtmlFilterEvent::MOD_HOME_CONTENT => 'onHtmlFilterEvent', HtmlFilterEvent::MOD_ABOUT_CONTENT => 'onHtmlFilterEvent', + HtmlFilterEvent::MOD_PROFILE_CONTENT => 'onHtmlFilterEvent', HtmlFilterEvent::JOT_TOOL => 'onHtmlFilterEvent', HtmlFilterEvent::CONTACT_BLOCK_END => 'onHtmlFilterEvent', ]; @@ -612,6 +613,7 @@ class HookEventBridgeTest extends TestCase [HtmlFilterEvent::PAGE_END, 'page_end'], [HtmlFilterEvent::MOD_HOME_CONTENT, 'home_content'], [HtmlFilterEvent::MOD_ABOUT_CONTENT, 'about_hook'], + [HtmlFilterEvent::MOD_PROFILE_CONTENT, 'profile_advanced'], [HtmlFilterEvent::JOT_TOOL, 'jot_tool'], [HtmlFilterEvent::CONTACT_BLOCK_END, 'contact_block_end'], ]; diff --git a/tests/Unit/Event/HtmlFilterEventTest.php b/tests/Unit/Event/HtmlFilterEventTest.php index 47a2d2596d..bae1669ca0 100644 --- a/tests/Unit/Event/HtmlFilterEventTest.php +++ b/tests/Unit/Event/HtmlFilterEventTest.php @@ -32,6 +32,7 @@ class HtmlFilterEventTest extends TestCase [HtmlFilterEvent::PAGE_END, 'friendica.html.page_end'], [HtmlFilterEvent::MOD_HOME_CONTENT, 'friendica.html.mod_home_content'], [HtmlFilterEvent::MOD_ABOUT_CONTENT, 'friendica.html.mod_about_content'], + [HtmlFilterEvent::MOD_PROFILE_CONTENT, 'friendica.html.mod_profile_content'], [HtmlFilterEvent::JOT_TOOL, 'friendica.html.jot_tool'], [HtmlFilterEvent::CONTACT_BLOCK_END, 'friendica.html.contact_block_end'], ]; From 7531a2fb36019c423b740855b61bc540afd9123d Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 11 Apr 2025 06:55:51 +0000 Subject: [PATCH 83/91] Create event for acl_lookup_end hook --- src/Core/Hooks/HookEventBridge.php | 2 + src/Event/ArrayFilterEvent.php | 2 + src/Module/Search/Acl.php | 42 +++++++++++++------ tests/Unit/Core/Hooks/HookEventBridgeTest.php | 2 + tests/Unit/Event/ArrayFilterEventTest.php | 1 + 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 9d20a36e89..9b8c2350c4 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -76,6 +76,7 @@ final class HookEventBridge ArrayFilterEvent::PROFILE_SIDEBAR => 'profile_sidebar', ArrayFilterEvent::PROFILE_TABS => 'profile_tabs', ArrayFilterEvent::MODERATION_USERS_TABS => 'moderation_users_tabs', + ArrayFilterEvent::ACL_LOOKUP_END => 'acl_lookup_end', ArrayFilterEvent::OEMBED_FETCH_END => 'oembed_fetch_url', ArrayFilterEvent::PAGE_INFO => 'page_info_data', ArrayFilterEvent::SMILEY_LIST => 'smilie', @@ -165,6 +166,7 @@ final class HookEventBridge ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent', ArrayFilterEvent::MODERATION_USERS_TABS => 'onArrayFilterEvent', + ArrayFilterEvent::ACL_LOOKUP_END => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 7c772f4132..591250455f 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -102,6 +102,8 @@ final class ArrayFilterEvent extends Event public const MODERATION_USERS_TABS = 'friendica.data.moderation_users_tabs'; + public const ACL_LOOKUP_END = 'friendica.data.acl_lookup_end'; + public const OEMBED_FETCH_END = 'friendica.data.oembed_fetch_end'; public const PAGE_INFO = 'friendica.data.page_info'; diff --git a/src/Module/Search/Acl.php b/src/Module/Search/Acl.php index ad1dc180be..83e5a5dfff 100644 --- a/src/Module/Search/Acl.php +++ b/src/Module/Search/Acl.php @@ -7,22 +7,23 @@ namespace Friendica\Module\Search; -use Friendica\App; +use Friendica\App\Arguments; +use Friendica\App\BaseURL; use Friendica\BaseModule; use Friendica\Content\Widget; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Search; use Friendica\Core\Session\Capability\IHandleUserSessions; -use Friendica\Core\System; use Friendica\Database\Database; use Friendica\Database\DBA; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Contact; use Friendica\Model\Post; use Friendica\Module\Response; -use Friendica\Network\HTTPException; +use Friendica\Network\HTTPException\UnauthorizedException; use Friendica\Util\Profiler; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -44,13 +45,26 @@ class Acl extends BaseModule private $session; /** @var Database */ private $database; + private EventDispatcherInterface $eventDispatcher; - public function __construct(Database $database, IHandleUserSessions $session, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { + public function __construct( + Database $database, + IHandleUserSessions $session, + EventDispatcherInterface $eventDispatcher, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [], + ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->session = $session; $this->database = $database; + $this->eventDispatcher = $eventDispatcher; } protected function post(array $request = []) @@ -61,7 +75,7 @@ class Acl extends BaseModule protected function rawContent(array $request = []) { if (!$this->session->getLocalUserId()) { - throw new HTTPException\UnauthorizedException($this->t('You must be logged in to use this module.')); + throw new UnauthorizedException($this->t('You must be logged in to use this module.')); } $type = $request['type'] ?? self::TYPE_MENTION_CONTACT_CIRCLE; @@ -280,7 +294,7 @@ class Acl extends BaseModule $resultTotal += count($unknown_contacts); } - $results = [ + $hook_data = [ 'tot' => $resultTotal, 'start' => $start, 'count' => $count, @@ -291,13 +305,15 @@ class Acl extends BaseModule 'search' => $search, ]; - Hook::callAll('acl_lookup_end', $results); + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ACL_LOOKUP_END, $hook_data), + )->getArray(); $o = [ - 'tot' => $results['tot'], - 'start' => $results['start'], - 'count' => $results['count'], - 'items' => $results['items'], + 'tot' => $hook_data['tot'], + 'start' => $hook_data['start'], + 'count' => $hook_data['count'], + 'items' => $hook_data['items'], ]; $this->logger->info('ACL {action} - {subaction} - done', ['module' => 'acl', 'action' => 'content', 'subaction' => 'search', 'search' => $search, 'type' => $type, 'conversation' => $conv_id]); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 6c5c5fecf8..fc3752e977 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -65,6 +65,7 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent', ArrayFilterEvent::MODERATION_USERS_TABS => 'onArrayFilterEvent', + ArrayFilterEvent::ACL_LOOKUP_END => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', ArrayFilterEvent::PAGE_INFO => 'onArrayFilterEvent', ArrayFilterEvent::SMILEY_LIST => 'onArrayFilterEvent', @@ -553,6 +554,7 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::PROFILE_SIDEBAR, 'profile_sidebar'], [ArrayFilterEvent::PROFILE_TABS, 'profile_tabs'], [ArrayFilterEvent::MODERATION_USERS_TABS, 'moderation_users_tabs'], + [ArrayFilterEvent::ACL_LOOKUP_END, 'acl_lookup_end'], [ArrayFilterEvent::PAGE_INFO, 'page_info_data'], [ArrayFilterEvent::SMILEY_LIST, 'smilie'], [ArrayFilterEvent::JOT_NETWORKS, 'jot_networks'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 9ecdb6feee..771cd4fed7 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -62,6 +62,7 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PROFILE_SIDEBAR, 'friendica.data.profile_sidebar'], [ArrayFilterEvent::PROFILE_TABS, 'friendica.data.profile_tabs'], [ArrayFilterEvent::MODERATION_USERS_TABS, 'friendica.data.moderation_users_tabs'], + [ArrayFilterEvent::ACL_LOOKUP_END, 'friendica.data.acl_lookup_end'], [ArrayFilterEvent::OEMBED_FETCH_END, 'friendica.data.oembed_fetch_end'], [ArrayFilterEvent::PAGE_INFO, 'friendica.data.page_info'], [ArrayFilterEvent::SMILEY_LIST, 'friendica.data.smiley_list'], From c436f5249b80428163cb06aeee118145714129fc Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 11 Apr 2025 07:46:48 +0000 Subject: [PATCH 84/91] Create events for enotify hooks --- src/Core/Hooks/HookEventBridge.php | 6 ++ src/Event/ArrayFilterEvent.php | 6 ++ .../Notifications/Repository/Notify.php | 70 ++++++++++++------- tests/Unit/Core/Hooks/HookEventBridgeTest.php | 6 ++ tests/Unit/Event/ArrayFilterEventTest.php | 3 + 5 files changed, 67 insertions(+), 24 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index 9b8c2350c4..ae7a42c154 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -67,6 +67,9 @@ final class HookEventBridge ArrayFilterEvent::DISPLAY_ITEM => 'display_item', ArrayFilterEvent::CACHE_ITEM => 'put_item_in_cache', ArrayFilterEvent::CHECK_ITEM_NOTIFICATION => 'check_item_notification', + ArrayFilterEvent::ENOTIFY => 'enotify', + ArrayFilterEvent::ENOTIFY_STORE => 'enotify_store', + ArrayFilterEvent::ENOTIFY_MAIL => 'enotify_mail', ArrayFilterEvent::DETECT_LANGUAGES => 'detect_languages', ArrayFilterEvent::RENDER_LOCATION => 'render_location', ArrayFilterEvent::ITEM_PHOTO_MENU => 'item_photo_menu', @@ -157,6 +160,9 @@ final class HookEventBridge ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CHECK_ITEM_NOTIFICATION => 'onArrayFilterEvent', + ArrayFilterEvent::ENOTIFY => 'onArrayFilterEvent', + ArrayFilterEvent::ENOTIFY_STORE => 'onArrayFilterEvent', + ArrayFilterEvent::ENOTIFY_MAIL => 'onArrayFilterEvent', ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 591250455f..1f73eadf62 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -84,6 +84,12 @@ final class ArrayFilterEvent extends Event public const CHECK_ITEM_NOTIFICATION = 'friendica.data.check_item_notification'; + public const ENOTIFY = 'friendica.data.enotify'; + + public const ENOTIFY_STORE = 'friendica.data.enotify_store'; + + public const ENOTIFY_MAIL = 'friendica.data.enotify_mail'; + public const DETECT_LANGUAGES = 'friendica.data.detect_languages'; public const RENDER_LOCATION = 'friendica.data.render_location'; diff --git a/src/Navigation/Notifications/Repository/Notify.php b/src/Navigation/Notifications/Repository/Notify.php index 1c793faaee..c59eed92aa 100644 --- a/src/Navigation/Notifications/Repository/Notify.php +++ b/src/Navigation/Notifications/Repository/Notify.php @@ -17,6 +17,7 @@ use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Database\Database; use Friendica\Database\DBA; +use Friendica\Event\ArrayFilterEvent; use Friendica\Factory\Api\Mastodon\Notification as NotificationFactory; use Friendica\Model; use Friendica\Navigation\Notifications\Collection; @@ -28,6 +29,7 @@ use Friendica\Object\Api\Mastodon\Notification; use Friendica\Protocol\Activity; use Friendica\Util\DateTimeFormat; use Friendica\Util\Emailer; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; /** @@ -56,16 +58,29 @@ class Notify extends BaseRepository /** @var Factory\Notification */ protected $notification; + private EventDispatcherInterface $eventDispatcher; + protected static $table_name = 'notify'; - public function __construct(Database $database, LoggerInterface $logger, L10n $l10n, BaseURL $baseUrl, IManageConfigValues $config, IManagePersonalConfigValues $pConfig, Emailer $emailer, Factory\Notification $notification, Factory\Notify $factory = null) - { + public function __construct( + Database $database, + LoggerInterface $logger, + L10n $l10n, + BaseURL $baseUrl, + IManageConfigValues $config, + IManagePersonalConfigValues $pConfig, + Emailer $emailer, + Factory\Notification $notification, + EventDispatcherInterface $eventDispatcher, + Factory\Notify $factory = null, + ) { $this->l10n = $l10n; $this->baseUrl = $baseUrl; $this->config = $config; $this->pConfig = $pConfig; $this->emailer = $emailer; $this->notification = $notification; + $this->eventDispatcher = $eventDispatcher; parent::__construct($database, $logger, $factory ?? new Factory\Notify($logger)); } @@ -171,7 +186,10 @@ class Notify extends BaseRepository $this->db->update(self::$table_name, $fields, ['id' => $Notify->id]); } else { $fields['date'] = DateTimeFormat::utcNow(); - Hook::callAll('enotify_store', $fields); + + $fields = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ENOTIFY_STORE, $fields), + )->getArray(); $this->db->insert(self::$table_name, $fields); @@ -549,7 +567,7 @@ class Notify extends BaseRepository $subject .= " (".$nickname."@".$hostname.")"; - $h = [ + $hook_data = [ 'params' => $params, 'subject' => $subject, 'preamble' => $preamble, @@ -561,18 +579,20 @@ class Notify extends BaseRepository 'itemlink' => $itemlink ]; - Hook::callAll('enotify', $h); + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ENOTIFY, $hook_data), + )->getArray(); - $subject = $h['subject']; + $subject = $hook_data['subject']; - $preamble = $h['preamble']; - $epreamble = $h['epreamble']; + $preamble = $hook_data['preamble']; + $epreamble = $hook_data['epreamble']; - $body = $h['body']; + $body = $hook_data['body']; - $tsitelink = $h['tsitelink']; - $hsitelink = $h['hsitelink']; - $itemlink = $h['itemlink']; + $tsitelink = $hook_data['tsitelink']; + $hsitelink = $hook_data['hsitelink']; + $itemlink = $hook_data['itemlink']; $notify_id = 0; @@ -620,7 +640,7 @@ class Notify extends BaseRepository } } - $datarray = [ + $hook_data = [ 'preamble' => $preamble, 'type' => $params['type'], 'parent' => $parent_id, @@ -637,31 +657,33 @@ class Notify extends BaseRepository 'headers' => $emailBuilder->getHeaders(), ]; - Hook::callAll('enotify_mail', $datarray); + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::ENOTIFY_MAIL, $hook_data), + )->getArray(); $emailBuilder - ->withHeaders($datarray['headers']) + ->withHeaders($hook_data['headers']) ->withRecipient($params['to_email']) ->forUser([ - 'uid' => $datarray['uid'], + 'uid' => $hook_data['uid'], 'language' => $params['language'], ]) - ->withNotification($datarray['subject'], $datarray['preamble'], $datarray['title'], $datarray['body']) - ->withSiteLink($datarray['tsitelink'], $datarray['hsitelink']) - ->withItemLink($datarray['itemlink']); + ->withNotification($hook_data['subject'], $hook_data['preamble'], $hook_data['title'], $hook_data['body']) + ->withSiteLink($hook_data['tsitelink'], $hook_data['hsitelink']) + ->withItemLink($hook_data['itemlink']); // If a photo is present, add it to the email - if (!empty($datarray['source_photo'])) { + if (!empty($hook_data['source_photo'])) { $emailBuilder->withPhoto( - $datarray['source_photo'], - $datarray['source_link'] ?? $sitelink, - $datarray['source_name'] ?? $sitename + $hook_data['source_photo'], + $hook_data['source_link'] ?? $sitelink, + $hook_data['source_name'] ?? $sitename ); } $email = $emailBuilder->build(); - $this->logger->debug('Send mail', $datarray); + $this->logger->debug('Send mail', $hook_data); // use the Emailer class to send the message return $this->emailer->send($email); diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index fc3752e977..7b655ee0a1 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -56,6 +56,9 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::DISPLAY_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CACHE_ITEM => 'onArrayFilterEvent', ArrayFilterEvent::CHECK_ITEM_NOTIFICATION => 'onArrayFilterEvent', + ArrayFilterEvent::ENOTIFY => 'onArrayFilterEvent', + ArrayFilterEvent::ENOTIFY_STORE => 'onArrayFilterEvent', + ArrayFilterEvent::ENOTIFY_MAIL => 'onArrayFilterEvent', ArrayFilterEvent::DETECT_LANGUAGES => 'onArrayFilterEvent', ArrayFilterEvent::RENDER_LOCATION => 'onArrayFilterEvent', ArrayFilterEvent::ITEM_PHOTO_MENU => 'onArrayFilterEvent', @@ -546,6 +549,9 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::DISPLAY_ITEM, 'display_item'], [ArrayFilterEvent::CACHE_ITEM, 'put_item_in_cache'], [ArrayFilterEvent::CHECK_ITEM_NOTIFICATION, 'check_item_notification'], + [ArrayFilterEvent::ENOTIFY, 'enotify'], + [ArrayFilterEvent::ENOTIFY_STORE, 'enotify_store'], + [ArrayFilterEvent::ENOTIFY_MAIL, 'enotify_mail'], [ArrayFilterEvent::DETECT_LANGUAGES, 'detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'item_photo_menu'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index 771cd4fed7..aae225cd46 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -53,6 +53,9 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::DISPLAY_ITEM, 'friendica.data.display_item'], [ArrayFilterEvent::CACHE_ITEM, 'friendica.data.cache_item'], [ArrayFilterEvent::CHECK_ITEM_NOTIFICATION, 'friendica.data.check_item_notification'], + [ArrayFilterEvent::ENOTIFY, 'friendica.data.enotify'], + [ArrayFilterEvent::ENOTIFY_STORE, 'friendica.data.enotify_store'], + [ArrayFilterEvent::ENOTIFY_MAIL, 'friendica.data.enotify_mail'], [ArrayFilterEvent::DETECT_LANGUAGES, 'friendica.data.detect_languages'], [ArrayFilterEvent::RENDER_LOCATION, 'friendica.data.render_location'], [ArrayFilterEvent::ITEM_PHOTO_MENU, 'friendica.data.item_photo_menu'], From 2a7d329c524c67b0d1f24ba1e377249fe20f305c Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 11 Apr 2025 08:21:29 +0000 Subject: [PATCH 85/91] Create event for profile_edit and profile_post hooks --- src/Core/Hooks/HookEventBridge.php | 4 ++ src/Event/ArrayFilterEvent.php | 4 ++ src/Module/Settings/Profile/Index.php | 52 +++++++++++++++---- .../Notifications/Repository/Notify.php | 1 - tests/Unit/Core/Hooks/HookEventBridgeTest.php | 4 ++ tests/Unit/Event/ArrayFilterEventTest.php | 2 + 6 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/Core/Hooks/HookEventBridge.php b/src/Core/Hooks/HookEventBridge.php index ae7a42c154..06f918ea6d 100644 --- a/src/Core/Hooks/HookEventBridge.php +++ b/src/Core/Hooks/HookEventBridge.php @@ -78,6 +78,8 @@ final class HookEventBridge ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'profile_sidebar_enter', ArrayFilterEvent::PROFILE_SIDEBAR => 'profile_sidebar', ArrayFilterEvent::PROFILE_TABS => 'profile_tabs', + ArrayFilterEvent::PROFILE_SETTINGS_FORM => 'profile_edit', + ArrayFilterEvent::PROFILE_SETTINGS_POST => 'profile_post', ArrayFilterEvent::MODERATION_USERS_TABS => 'moderation_users_tabs', ArrayFilterEvent::ACL_LOOKUP_END => 'acl_lookup_end', ArrayFilterEvent::OEMBED_FETCH_END => 'oembed_fetch_url', @@ -171,6 +173,8 @@ final class HookEventBridge ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent', + ArrayFilterEvent::PROFILE_SETTINGS_FORM => 'onArrayFilterEvent', + ArrayFilterEvent::PROFILE_SETTINGS_POST => 'onArrayFilterEvent', ArrayFilterEvent::MODERATION_USERS_TABS => 'onArrayFilterEvent', ArrayFilterEvent::ACL_LOOKUP_END => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', diff --git a/src/Event/ArrayFilterEvent.php b/src/Event/ArrayFilterEvent.php index 1f73eadf62..864f269cdb 100644 --- a/src/Event/ArrayFilterEvent.php +++ b/src/Event/ArrayFilterEvent.php @@ -106,6 +106,10 @@ final class ArrayFilterEvent extends Event public const PROFILE_TABS = 'friendica.data.profile_tabs'; + public const PROFILE_SETTINGS_FORM = 'friendica.data.profile_settings_form'; + + public const PROFILE_SETTINGS_POST = 'friendica.data.profile_settings_post'; + public const MODERATION_USERS_TABS = 'friendica.data.moderation_users_tabs'; public const ACL_LOOKUP_END = 'friendica.data.acl_lookup_end'; diff --git a/src/Module/Settings/Profile/Index.php b/src/Module/Settings/Profile/Index.php index f63ae3b135..bf865667e4 100644 --- a/src/Module/Settings/Profile/Index.php +++ b/src/Module/Settings/Profile/Index.php @@ -7,30 +7,33 @@ namespace Friendica\Module\Settings\Profile; -use Friendica\App; +use Friendica\App\Arguments; +use Friendica\App\BaseURL; +use Friendica\App\Page; use Friendica\Core\ACL; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\Protocol; use Friendica\Core\Renderer; use Friendica\Core\Session\Capability\IHandleUserSessions; use Friendica\Core\Theme; +use Friendica\Core\Worker; use Friendica\Database\DBA; +use Friendica\Event\ArrayFilterEvent; use Friendica\Model\Contact; use Friendica\Model\Profile; use Friendica\Module\Response; -use Friendica\Navigation\SystemMessages; -use Friendica\Profile\ProfileField; use Friendica\Model\User; use Friendica\Module\BaseSettings; use Friendica\Module\Security\Login; +use Friendica\Navigation\SystemMessages; use Friendica\Network\HTTPException; +use Friendica\Profile\ProfileField; use Friendica\Security\PermissionSet; use Friendica\Util\ACLFormatter; use Friendica\Util\DateTimeFormat; use Friendica\Util\Profiler; use Friendica\Util\Temporal; -use Friendica\Core\Worker; +use Psr\EventDispatcher\EventDispatcherInterface; use Psr\Log\LoggerInterface; class Index extends BaseSettings @@ -47,9 +50,27 @@ class Index extends BaseSettings private $permissionSetFactory; /** @var ACLFormatter */ private $aclFormatter; + private EventDispatcherInterface $eventDispatcher; - public function __construct(ACLFormatter $aclFormatter, PermissionSet\Factory\PermissionSet $permissionSetFactory, PermissionSet\Repository\PermissionSet $permissionSetRepo, SystemMessages $systemMessages, ProfileField\Factory\ProfileField $profileFieldFactory, ProfileField\Repository\ProfileField $profileFieldRepo, IHandleUserSessions $session, App\Page $page, L10n $l10n, App\BaseURL $baseUrl, App\Arguments $args, LoggerInterface $logger, Profiler $profiler, Response $response, array $server, array $parameters = []) - { + public function __construct( + ACLFormatter $aclFormatter, + PermissionSet\Factory\PermissionSet $permissionSetFactory, + PermissionSet\Repository\PermissionSet $permissionSetRepo, + SystemMessages $systemMessages, + ProfileField\Factory\ProfileField $profileFieldFactory, + ProfileField\Repository\ProfileField $profileFieldRepo, + EventDispatcherInterface $eventDispatcher, + IHandleUserSessions $session, + Page $page, + L10n $l10n, + BaseURL $baseUrl, + Arguments $args, + LoggerInterface $logger, + Profiler $profiler, + Response $response, + array $server, + array $parameters = [], + ) { parent::__construct($session, $page, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); $this->profileFieldRepo = $profileFieldRepo; @@ -58,6 +79,7 @@ class Index extends BaseSettings $this->permissionSetRepo = $permissionSetRepo; $this->permissionSetFactory = $permissionSetFactory; $this->aclFormatter = $aclFormatter; + $this->eventDispatcher = $eventDispatcher; } protected function post(array $request = []) @@ -73,7 +95,9 @@ class Index extends BaseSettings self::checkFormSecurityTokenRedirectOnError('/settings/profile', 'settings_profile'); - Hook::callAll('profile_post', $request); + $request = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PROFILE_SETTINGS_POST, $request), + )->getArray(); $dob = trim($request['dob'] ?? ''); @@ -288,8 +312,16 @@ class Index extends BaseSettings '$custom_fields' => $custom_fields, ]); - $arr = ['profile' => $owner, 'entry' => $o]; - Hook::callAll('profile_edit', $arr); + $hook_data = [ + 'profile' => $owner, + 'entry' => $o, + ]; + + $hook_data = $this->eventDispatcher->dispatch( + new ArrayFilterEvent(ArrayFilterEvent::PROFILE_SETTINGS_FORM, $hook_data), + )->getArray(); + + $o = $hook_data['entry'] ?? $o; return $o; } diff --git a/src/Navigation/Notifications/Repository/Notify.php b/src/Navigation/Notifications/Repository/Notify.php index c59eed92aa..7f55fd1a48 100644 --- a/src/Navigation/Notifications/Repository/Notify.php +++ b/src/Navigation/Notifications/Repository/Notify.php @@ -13,7 +13,6 @@ use Friendica\Content\Text\BBCode; use Friendica\Content\Text\Plaintext; use Friendica\Core\Config\Capability\IManageConfigValues; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Database\Database; use Friendica\Database\DBA; diff --git a/tests/Unit/Core/Hooks/HookEventBridgeTest.php b/tests/Unit/Core/Hooks/HookEventBridgeTest.php index 7b655ee0a1..436e1435bc 100644 --- a/tests/Unit/Core/Hooks/HookEventBridgeTest.php +++ b/tests/Unit/Core/Hooks/HookEventBridgeTest.php @@ -67,6 +67,8 @@ class HookEventBridgeTest extends TestCase ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY => 'onProfileSidebarEntryEvent', ArrayFilterEvent::PROFILE_SIDEBAR => 'onArrayFilterEvent', ArrayFilterEvent::PROFILE_TABS => 'onArrayFilterEvent', + ArrayFilterEvent::PROFILE_SETTINGS_FORM => 'onArrayFilterEvent', + ArrayFilterEvent::PROFILE_SETTINGS_POST => 'onArrayFilterEvent', ArrayFilterEvent::MODERATION_USERS_TABS => 'onArrayFilterEvent', ArrayFilterEvent::ACL_LOOKUP_END => 'onArrayFilterEvent', ArrayFilterEvent::OEMBED_FETCH_END => 'onOembedFetchEndEvent', @@ -559,6 +561,8 @@ class HookEventBridgeTest extends TestCase [ArrayFilterEvent::CONTACT_PHOTO_MENU, 'contact_photo_menu'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'profile_sidebar'], [ArrayFilterEvent::PROFILE_TABS, 'profile_tabs'], + [ArrayFilterEvent::PROFILE_SETTINGS_FORM, 'profile_edit'], + [ArrayFilterEvent::PROFILE_SETTINGS_POST, 'profile_post'], [ArrayFilterEvent::MODERATION_USERS_TABS, 'moderation_users_tabs'], [ArrayFilterEvent::ACL_LOOKUP_END, 'acl_lookup_end'], [ArrayFilterEvent::PAGE_INFO, 'page_info_data'], diff --git a/tests/Unit/Event/ArrayFilterEventTest.php b/tests/Unit/Event/ArrayFilterEventTest.php index aae225cd46..85f9307a0d 100644 --- a/tests/Unit/Event/ArrayFilterEventTest.php +++ b/tests/Unit/Event/ArrayFilterEventTest.php @@ -64,6 +64,8 @@ class ArrayFilterEventTest extends TestCase [ArrayFilterEvent::PROFILE_SIDEBAR_ENTRY, 'friendica.data.profile_sidebar_entry'], [ArrayFilterEvent::PROFILE_SIDEBAR, 'friendica.data.profile_sidebar'], [ArrayFilterEvent::PROFILE_TABS, 'friendica.data.profile_tabs'], + [ArrayFilterEvent::PROFILE_SETTINGS_FORM, 'friendica.data.profile_settings_form'], + [ArrayFilterEvent::PROFILE_SETTINGS_POST, 'friendica.data.profile_settings_post'], [ArrayFilterEvent::MODERATION_USERS_TABS, 'friendica.data.moderation_users_tabs'], [ArrayFilterEvent::ACL_LOOKUP_END, 'friendica.data.acl_lookup_end'], [ArrayFilterEvent::OEMBED_FETCH_END, 'friendica.data.oembed_fetch_end'], From f1abd5735682c4d0df9c25b8c84a5cc142b8680a Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 11 Apr 2025 08:32:05 +0000 Subject: [PATCH 86/91] Fix compat with PHP 7.4 --- src/Navigation/Notifications/Repository/Notify.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Navigation/Notifications/Repository/Notify.php b/src/Navigation/Notifications/Repository/Notify.php index 7f55fd1a48..0e572e9c61 100644 --- a/src/Navigation/Notifications/Repository/Notify.php +++ b/src/Navigation/Notifications/Repository/Notify.php @@ -71,7 +71,7 @@ class Notify extends BaseRepository Emailer $emailer, Factory\Notification $notification, EventDispatcherInterface $eventDispatcher, - Factory\Notify $factory = null, + Factory\Notify $factory = null ) { $this->l10n = $l10n; $this->baseUrl = $baseUrl; From 2e672414b3813dc062b8c7c7de126e4737469d44 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 11 Apr 2025 08:38:30 +0000 Subject: [PATCH 87/91] Fix compat with PHP 7.4 --- src/Module/Contact/Profile.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Module/Contact/Profile.php b/src/Module/Contact/Profile.php index 39029a25a8..83ea318390 100644 --- a/src/Module/Contact/Profile.php +++ b/src/Module/Contact/Profile.php @@ -77,7 +77,7 @@ class Profile extends BaseModule Page $page, IManageConfigValues $config, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); From fa58d8b11ab5661aa7de5ced8f283a6c3d94d703 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 15 Apr 2025 06:11:17 +0000 Subject: [PATCH 88/91] Fix compat with PHP 7.4 --- src/Module/Friendica.php | 2 +- src/Module/Moderation/BaseUsers.php | 2 +- src/Module/Ping/Network.php | 2 +- src/Module/Privacy/PermissionTooltip.php | 2 +- src/Module/Profile/Photos.php | 2 +- src/Module/Profile/Profile.php | 2 +- src/Module/Search/Acl.php | 2 +- src/Module/Settings/Profile/Index.php | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Module/Friendica.php b/src/Module/Friendica.php index 314152abca..42a46d8278 100644 --- a/src/Module/Friendica.php +++ b/src/Module/Friendica.php @@ -54,7 +54,7 @@ class Friendica extends BaseModule Profiler $profiler, Response $response, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); diff --git a/src/Module/Moderation/BaseUsers.php b/src/Module/Moderation/BaseUsers.php index 283fa74ec2..698f4256a5 100644 --- a/src/Module/Moderation/BaseUsers.php +++ b/src/Module/Moderation/BaseUsers.php @@ -48,7 +48,7 @@ abstract class BaseUsers extends BaseModeration Profiler $profiler, Response $response, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct($page, $appHelper, $systemMessages, $session, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); diff --git a/src/Module/Ping/Network.php b/src/Module/Ping/Network.php index 03c6b8eeac..520a5e66a6 100644 --- a/src/Module/Ping/Network.php +++ b/src/Module/Ping/Network.php @@ -67,7 +67,7 @@ class Network extends NetworkModule Profiler $profiler, Response $response, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct( $userDefinedChannel, diff --git a/src/Module/Privacy/PermissionTooltip.php b/src/Module/Privacy/PermissionTooltip.php index 6f77daaec1..5541a49bd6 100644 --- a/src/Module/Privacy/PermissionTooltip.php +++ b/src/Module/Privacy/PermissionTooltip.php @@ -54,7 +54,7 @@ class PermissionTooltip extends BaseModule Profiler $profiler, Response $response, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); diff --git a/src/Module/Profile/Photos.php b/src/Module/Profile/Photos.php index 29ece42ef9..2c543f9449 100644 --- a/src/Module/Profile/Photos.php +++ b/src/Module/Profile/Photos.php @@ -73,7 +73,7 @@ class Photos extends \Friendica\Module\BaseProfile Profiler $profiler, Response $response, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); diff --git a/src/Module/Profile/Profile.php b/src/Module/Profile/Profile.php index b3f15f5f44..cb75b2fecc 100644 --- a/src/Module/Profile/Profile.php +++ b/src/Module/Profile/Profile.php @@ -74,7 +74,7 @@ class Profile extends BaseProfile Profiler $profiler, Response $response, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); diff --git a/src/Module/Search/Acl.php b/src/Module/Search/Acl.php index 83e5a5dfff..3419672b19 100644 --- a/src/Module/Search/Acl.php +++ b/src/Module/Search/Acl.php @@ -58,7 +58,7 @@ class Acl extends BaseModule Profiler $profiler, Response $response, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); diff --git a/src/Module/Settings/Profile/Index.php b/src/Module/Settings/Profile/Index.php index bf865667e4..7b05aceaa6 100644 --- a/src/Module/Settings/Profile/Index.php +++ b/src/Module/Settings/Profile/Index.php @@ -69,7 +69,7 @@ class Index extends BaseSettings Profiler $profiler, Response $response, array $server, - array $parameters = [], + array $parameters = [] ) { parent::__construct($session, $page, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); From ed5de437be7aa2172e8b392889e133684b6f37c1 Mon Sep 17 00:00:00 2001 From: Art4 Date: Fri, 9 May 2025 06:40:49 +0000 Subject: [PATCH 89/91] Fix PHPStan errors --- src/Core/Logger/Factory/SyslogLoggerFactory.php | 6 +++--- src/Module/Photo.php | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Core/Logger/Factory/SyslogLoggerFactory.php b/src/Core/Logger/Factory/SyslogLoggerFactory.php index 24a884a5f9..e71eb219f9 100644 --- a/src/Core/Logger/Factory/SyslogLoggerFactory.php +++ b/src/Core/Logger/Factory/SyslogLoggerFactory.php @@ -48,8 +48,8 @@ final class SyslogLoggerFactory implements LoggerFactory */ public function createLogger(string $logLevel, string $logChannel): LoggerInterface { - $logOpts = (string) $this->config->get('system', 'syslog_flags') ?? SyslogLogger::DEFAULT_FLAGS; - $logFacility = (string) $this->config->get('system', 'syslog_facility') ?? SyslogLogger::DEFAULT_FACILITY; + $logOpts = (int) $this->config->get('system', 'syslog_flags') ?? SyslogLogger::DEFAULT_FLAGS; + $logFacility = (int) $this->config->get('system', 'syslog_facility') ?? SyslogLogger::DEFAULT_FACILITY; if (!array_key_exists($logLevel, SyslogLogger::logLevels)) { throw new LogLevelException(sprintf('The log level "%s" is not supported by "%s".', $logLevel, SyslogLogger::class)); @@ -58,7 +58,7 @@ final class SyslogLoggerFactory implements LoggerFactory return new SyslogLogger( $logChannel, $this->introspection, - (string) SyslogLogger::logLevels[$logLevel], + SyslogLogger::logLevels[$logLevel], $logOpts, $logFacility ); diff --git a/src/Module/Photo.php b/src/Module/Photo.php index 8faef5aa6d..ddd7b1994d 100644 --- a/src/Module/Photo.php +++ b/src/Module/Photo.php @@ -308,7 +308,9 @@ class Photo extends BaseApi // For local users directly use the photo record that is marked as the profile if (DI::baseUrl()->isLocalUrl($contact['url'])) { - $contact = Contact::selectFirst($fields, ['nurl' => $contact['nurl'], 'self' => true]); + $nurl = $contact['nurl']; + $contact = Contact::selectFirst($fields, ['nurl' => $nurl, 'self' => true]); + if (!empty($contact)) { if ($customsize <= Proxy::PIXEL_MICRO) { $scale = 6; @@ -324,7 +326,7 @@ class Photo extends BaseApi $this->logger->notice('Profile photo was not loaded', ['scale' => $scale, 'uid' => $contact['uid']]); } } else { - $this->logger->notice('Local Contact was not found', ['url' => $contact['nurl']]); + $this->logger->notice('Local Contact was not found', ['url' => $nurl]); } } From b2bbcc496531194c0afe21d73353d3be4145693b Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 13 May 2025 06:12:16 +0000 Subject: [PATCH 90/91] Fix PHPStan errors --- src/Model/Item.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Model/Item.php b/src/Model/Item.php index 62e6aff96b..397b774fa6 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -864,6 +864,7 @@ class Item unset($_SESSION['uid']); } } elseif (!$notify) { + /** @var array */ $item = $eventDispatcher->dispatch( new ArrayFilterEvent(ArrayFilterEvent::INSERT_POST_REMOTE, $item) )->getArray(); From 02fae146e6007a36da9825d0e138e061df453075 Mon Sep 17 00:00:00 2001 From: Art4 Date: Tue, 13 May 2025 06:18:41 +0000 Subject: [PATCH 91/91] Fix code style --- .../Storage/Repository/StorageManager.php | 10 +-- src/Model/Item.php | 2 +- src/Model/Profile.php | 4 +- src/Module/Contact/Profile.php | 19 +++-- src/Module/Conversation/Network.php | 1 - src/Module/Directory.php | 7 +- src/Module/Friendica.php | 8 +-- src/Module/Moderation/BaseUsers.php | 4 +- src/Module/ParseUrl.php | 20 +++--- src/Module/Privacy/PermissionTooltip.php | 69 ++++++++++--------- src/Module/Profile/Photos.php | 26 +++---- src/Module/Profile/Profile.php | 18 ++--- src/Module/Register.php | 2 +- src/Module/Search/Acl.php | 37 ++++++---- src/Module/Settings/Profile/Index.php | 9 +-- .../Notifications/Repository/Notify.php | 12 ++-- .../Storage/Repository/StorageManagerTest.php | 4 +- 17 files changed, 134 insertions(+), 118 deletions(-) diff --git a/src/Core/Storage/Repository/StorageManager.php b/src/Core/Storage/Repository/StorageManager.php index 1de89dbddc..36efa3a1bf 100644 --- a/src/Core/Storage/Repository/StorageManager.php +++ b/src/Core/Storage/Repository/StorageManager.php @@ -76,12 +76,12 @@ class StorageManager */ public function __construct(Database $dba, IManageConfigValues $config, LoggerInterface $logger, EventDispatcherInterface $eventDispatcher, L10n $l10n, bool $includeAddon = true) { - $this->dba = $dba; - $this->config = $config; - $this->logger = $logger; + $this->dba = $dba; + $this->config = $config; + $this->logger = $logger; $this->eventDispatcher = $eventDispatcher; - $this->l10n = $l10n; - $this->validBackends = $config->get('storage', 'backends', self::DEFAULT_BACKENDS); + $this->l10n = $l10n; + $this->validBackends = $config->get('storage', 'backends', self::DEFAULT_BACKENDS); $currentName = $this->config->get('storage', 'name'); diff --git a/src/Model/Item.php b/src/Model/Item.php index 397b774fa6..3eb2b3b90b 100644 --- a/src/Model/Item.php +++ b/src/Model/Item.php @@ -3051,7 +3051,7 @@ class Item $hook_data = [ 'rendered-html' => $item['rendered-html'], 'rendered-hash' => $item['rendered-hash'], - 'item' => $item, + 'item' => $item, ]; $eventDispatcher = DI::eventDispatcher(); diff --git a/src/Model/Profile.php b/src/Model/Profile.php index a647a58c78..731a66cb2b 100644 --- a/src/Model/Profile.php +++ b/src/Model/Profile.php @@ -480,7 +480,7 @@ class Profile $hook_data = [ 'profile' => &$profile, - 'entry' => &$o, + 'entry' => &$o, ]; $hook_data = $eventDispatcher->dispatch( @@ -488,7 +488,7 @@ class Profile )->getArray(); $profile = $hook_data['profile'] ?? $profile; - $o = $hook_data['entry'] ?? $o; + $o = $hook_data['entry'] ?? $o; return $o; } diff --git a/src/Module/Contact/Profile.php b/src/Module/Contact/Profile.php index 83ea318390..dd7288e58c 100644 --- a/src/Module/Contact/Profile.php +++ b/src/Module/Contact/Profile.php @@ -265,7 +265,7 @@ class Profile extends BaseModule $this->baseUrl->redirect('contact/' . $contact['id']); } - $vcard_widget = Widget\VCard::getHTML($contact); + $vcard_widget = Widget\VCard::getHTML($contact); $circles_widget = ''; if (!in_array($localRelationship->rel, [ContactModel::NOTHING, ContactModel::SELF])) { @@ -283,9 +283,15 @@ class Profile extends BaseModule ]); switch ($localRelationship->rel) { - case ContactModel::FRIEND: $relation_text = $this->t('You are mutual friends with %s', $contact['name']); break; - case ContactModel::FOLLOWER: $relation_text = $this->t('You are sharing with %s', $contact['name']); break; - case ContactModel::SHARING: $relation_text = $this->t('%s is sharing with you', $contact['name']); break; + case ContactModel::FRIEND: + $relation_text = $this->t('You are mutual friends with %s', $contact['name']); + break; + case ContactModel::FOLLOWER: + $relation_text = $this->t('You are sharing with %s', $contact['name']); + break; + case ContactModel::SHARING: + $relation_text = $this->t('%s is sharing with you', $contact['name']); + break; default: $relation_text = ''; } @@ -308,8 +314,7 @@ class Profile extends BaseModule $this->logger->notice('Empty gsid for contact', ['contact' => $contact]); } - $serverIgnored = - $contact['gsid'] && + $serverIgnored = $contact['gsid'] && $this->userGServer->isIgnoredByUser($this->session->getLocalUserId(), $contact['gsid']) ? $this->t('This contact is on a server you ignored.') : ''; @@ -475,7 +480,7 @@ class Profile extends BaseModule $hook_data = [ 'contact' => $contact, - 'output' => $o, + 'output' => $o, ]; $hook_data = $this->eventDispatcher->dispatch( diff --git a/src/Module/Conversation/Network.php b/src/Module/Conversation/Network.php index f38c0d4b3f..ce4b8d9dd3 100644 --- a/src/Module/Conversation/Network.php +++ b/src/Module/Conversation/Network.php @@ -31,7 +31,6 @@ use Friendica\Content\Widget\TrendingTags; use Friendica\Core\ACL; use Friendica\Core\Cache\Capability\ICanCache; use Friendica\Core\Config\Capability\IManageConfigValues; -use Friendica\Core\Hook; use Friendica\Core\L10n; use Friendica\Core\PConfig\Capability\IManagePersonalConfigValues; use Friendica\Core\Renderer; diff --git a/src/Module/Directory.php b/src/Module/Directory.php index d63bbc13e3..786c92dcd0 100644 --- a/src/Module/Directory.php +++ b/src/Module/Directory.php @@ -11,7 +11,6 @@ use Friendica\BaseModule; use Friendica\Content\Nav; use Friendica\Content\Pager; use Friendica\Content\Widget; -use Friendica\Core\Hook; use Friendica\Core\Renderer; use Friendica\Core\Search; use Friendica\DI; @@ -40,7 +39,7 @@ class Directory extends BaseModule DI::page()['aside'] .= Widget::follow(); } - $output = ''; + $output = ''; $entries = []; Nav::setSelected('directory'); @@ -48,7 +47,7 @@ class Directory extends BaseModule $search = trim(rawurldecode($_REQUEST['search'] ?? '')); $gDirPath = ''; - $dirURL = Search::getGlobalDirectory(); + $dirURL = Search::getGlobalDirectory(); if (strlen($dirURL)) { $gDirPath = OpenWebAuth::getZrlUrl($dirURL, true); } @@ -166,7 +165,7 @@ class Directory extends BaseModule $hook_data = [ 'contact' => $contact, - 'entry' => $entry, + 'entry' => $entry, ]; $hook_data = $eventDispatcher->dispatch( diff --git a/src/Module/Friendica.php b/src/Module/Friendica.php index 42a46d8278..64064423d7 100644 --- a/src/Module/Friendica.php +++ b/src/Module/Friendica.php @@ -58,11 +58,11 @@ class Friendica extends BaseModule ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->config = $config; - $this->keyValue = $keyValue; - $this->session = $session; + $this->config = $config; + $this->keyValue = $keyValue; + $this->session = $session; $this->eventDispatcher = $eventDispatcher; - $this->addonHelper = $addonHelper; + $this->addonHelper = $addonHelper; } protected function content(array $request = []): string diff --git a/src/Module/Moderation/BaseUsers.php b/src/Module/Moderation/BaseUsers.php index 698f4256a5..8a12d2b0a1 100644 --- a/src/Module/Moderation/BaseUsers.php +++ b/src/Module/Moderation/BaseUsers.php @@ -52,7 +52,7 @@ abstract class BaseUsers extends BaseModeration ) { parent::__construct($page, $appHelper, $systemMessages, $session, $l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->database = $database; + $this->database = $database; $this->eventDispatcher = $eventDispatcher; } @@ -115,7 +115,7 @@ abstract class BaseUsers extends BaseModeration ]; $hook_data = [ - 'tabs' => $tabs, + 'tabs' => $tabs, 'selectedTab' => $selectedTab, ]; diff --git a/src/Module/ParseUrl.php b/src/Module/ParseUrl.php index 508e5d987d..d023368f10 100644 --- a/src/Module/ParseUrl.php +++ b/src/Module/ParseUrl.php @@ -31,7 +31,7 @@ class ParseUrl extends BaseModule { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->userSession = $userSession; + $this->userSession = $userSession; $this->eventDispatcher = $eventDispatcher; } @@ -41,10 +41,10 @@ class ParseUrl extends BaseModule throw new \Friendica\Network\HTTPException\ForbiddenException(); } - $format = ''; - $title = ''; + $format = ''; + $title = ''; $description = ''; - $ret = ['success' => false, 'contentType' => '']; + $ret = ['success' => false, 'contentType' => '']; if (!empty($_GET['binurl']) && Util\Strings::isHex($_GET['binurl'])) { $url = trim(hex2bin($_GET['binurl'])); @@ -85,9 +85,9 @@ class ParseUrl extends BaseModule } $hook_data = [ - 'url' => $url, + 'url' => $url, 'format' => $format, - 'text' => null, + 'text' => null, ]; $hook_data = $this->eventDispatcher->dispatch( @@ -119,14 +119,14 @@ class ParseUrl extends BaseModule } $ret['contentType'] = $content_type; - $ret['data'] = ['url' => $url]; - $ret['success'] = true; + $ret['data'] = ['url' => $url]; + $ret['success'] = true; } else { unset($siteinfo['keywords']); - $ret['data'] = $siteinfo; + $ret['data'] = $siteinfo; $ret['contentType'] = 'attachment'; - $ret['success'] = true; + $ret['success'] = true; } $this->jsonExit($ret); diff --git a/src/Module/Privacy/PermissionTooltip.php b/src/Module/Privacy/PermissionTooltip.php index 5541a49bd6..e6656b95e9 100644 --- a/src/Module/Privacy/PermissionTooltip.php +++ b/src/Module/Privacy/PermissionTooltip.php @@ -58,17 +58,17 @@ class PermissionTooltip extends BaseModule ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->dba = $dba; - $this->aclFormatter = $aclFormatter; - $this->session = $session; - $this->config = $config; - $this->permissionSet = $permissionSet; + $this->dba = $dba; + $this->aclFormatter = $aclFormatter; + $this->session = $session; + $this->config = $config; + $this->permissionSet = $permissionSet; $this->eventDispatcher = $eventDispatcher; } protected function rawContent(array $request = []) { - $type = $this->parameters['type']; + $type = $this->parameters['type']; $referenceId = $this->parameters['id']; $expectedTypes = ['item', 'photo', 'event']; @@ -79,10 +79,10 @@ class PermissionTooltip extends BaseModule $condition = ['id' => $referenceId, 'uid' => [0, $this->session->getLocalUserId()]]; if ($type == 'item') { $fields = ['uid', 'psid', 'private', 'uri-id', 'origin', 'network']; - $model = Model\Post::selectFirst($fields, $condition, ['order' => ['uid' => true]]); + $model = Model\Post::selectFirst($fields, $condition, ['order' => ['uid' => true]]); if ($model['origin'] || ($model['network'] != Protocol::ACTIVITYPUB)) { - $permissionSet = $this->permissionSet->selectOneById($model['psid'], $model['uid']); + $permissionSet = $this->permissionSet->selectOneById($model['psid'], $model['uid']); $model['allow_cid'] = $permissionSet->allow_cid; $model['allow_gid'] = $permissionSet->allow_gid; $model['deny_cid'] = $permissionSet->deny_cid; @@ -94,8 +94,8 @@ class PermissionTooltip extends BaseModule $model['deny_gid'] = []; } } else { - $fields = ['uid', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid']; - $model = $this->dba->selectFirst($type, $fields, $condition); + $fields = ['uid', 'allow_cid', 'allow_gid', 'deny_cid', 'deny_gid']; + $model = $this->dba->selectFirst($type, $fields, $condition); $model['allow_cid'] = $this->aclFormatter->expand($model['allow_cid']); $model['allow_gid'] = $this->aclFormatter->expand($model['allow_gid']); $model['deny_cid'] = $this->aclFormatter->expand($model['deny_cid']); @@ -116,7 +116,7 @@ class PermissionTooltip extends BaseModule $model = $hook_data['model'] ?? $model; - $aclReceivers = new Entity\AclReceivers(); + $aclReceivers = new Entity\AclReceivers(); $addressedReceivers = new Entity\AddressedReceivers(); if (!empty($model['allow_cid']) || !empty($model['allow_gid']) || !empty($model['deny_cid']) || !empty($model['deny_gid'])) { $aclReceivers = $this->fetchReceiversFromACL($model); @@ -126,30 +126,35 @@ class PermissionTooltip extends BaseModule $privacy = ''; switch ($model['private'] ?? null) { - case Model\Item::PUBLIC: $privacy = $this->t('Public'); break; - case Model\Item::UNLISTED: $privacy = $this->t('Unlisted'); break; - case Model\Item::PRIVATE: $privacy = $this->t('Limited/Private'); break; + case Model\Item::PUBLIC: + $privacy = $this->t('Public'); + break; + case Model\Item::UNLISTED: + $privacy = $this->t('Unlisted'); + break; + case Model\Item::PRIVATE: + $privacy = $this->t('Limited/Private'); + break; } - if ($aclReceivers->isEmpty() && $addressedReceivers->isEmpty() && empty($privacy)) - { + if ($aclReceivers->isEmpty() && $addressedReceivers->isEmpty() && empty($privacy)) { echo $this->t('Remote privacy information not available.'); exit; } - $tpl = Renderer::getMarkupTemplate('privacy/permission_tooltip.tpl'); + $tpl = Renderer::getMarkupTemplate('privacy/permission_tooltip.tpl'); $output = Renderer::replaceMacros($tpl, [ '$l10n' => [ 'visible_to' => $this->t('Visible to:'), - 'to' => $this->t('To:'), - 'cc' => $this->t('CC:'), - 'bcc' => $this->t('BCC:'), - 'audience' => $this->t('Audience:'), + 'to' => $this->t('To:'), + 'cc' => $this->t('CC:'), + 'bcc' => $this->t('BCC:'), + 'audience' => $this->t('Audience:'), 'attributed' => $this->t('Attributed To:'), ], - '$aclReceivers' => $aclReceivers, + '$aclReceivers' => $aclReceivers, '$addressedReceivers' => $addressedReceivers, - '$privacy' => $privacy, + '$privacy' => $privacy, ]); $this->httpExit($output); @@ -223,7 +228,7 @@ class PermissionTooltip extends BaseModule private function fetchAddressedReceivers(int $uriId): Entity\AddressedReceivers { $own_url = ''; - $uid = $this->session->getLocalUserId(); + $uid = $this->session->getLocalUserId(); if ($uid) { $owner = Model\User::getOwnerDataById($uid); if (!empty($owner['url'])) { @@ -246,11 +251,11 @@ class PermissionTooltip extends BaseModule $receivers[$receiver['type']][] = $this->t('Collection (%s)', $receiver['name']); break; case Model\Tag::FOLLOWER_COLLECTION: - $apcontact = $this->dba->selectFirst('apcontact', ['name'], ['followers' => $receiver['url']]); + $apcontact = $this->dba->selectFirst('apcontact', ['name'], ['followers' => $receiver['url']]); $receivers[$receiver['type']][] = $this->t('Followers (%s)', $apcontact['name'] ?? $receiver['name']); break; case Model\Tag::ACCOUNT: - $apcontact = Model\APContact::getByURL($receiver['url'], false); + $apcontact = Model\APContact::getByURL($receiver['url'], false); $receivers[$receiver['type']][] = $apcontact['name'] ?? $receiver['name']; break; default: @@ -260,19 +265,19 @@ class PermissionTooltip extends BaseModule } foreach ($receivers as $type => $receiver) { - $max = $this->config->get('system', 'max_receivers'); + $max = $this->config->get('system', 'max_receivers'); $total = count($receiver); if ($total > $max) { - $receivers[$type] = array_slice($receiver, 0, $max); + $receivers[$type] = array_slice($receiver, 0, $max); $receivers[$type][] = $this->t('%d more', $total - $max); } } return new Entity\AddressedReceivers( - $receivers[Model\Tag::TO] ?? [], - $receivers[Model\Tag::CC] ?? [], - $receivers[Model\Tag::BCC] ?? [], - $receivers[Model\Tag::AUDIENCE] ?? [], + $receivers[Model\Tag::TO] ?? [], + $receivers[Model\Tag::CC] ?? [], + $receivers[Model\Tag::BCC] ?? [], + $receivers[Model\Tag::AUDIENCE] ?? [], $receivers[Model\Tag::ATTRIBUTED] ?? [], ); } diff --git a/src/Module/Profile/Photos.php b/src/Module/Profile/Photos.php index 2c543f9449..6d9bca26e3 100644 --- a/src/Module/Profile/Photos.php +++ b/src/Module/Profile/Photos.php @@ -77,13 +77,13 @@ class Photos extends \Friendica\Module\BaseProfile ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->session = $session; - $this->page = $page; - $this->config = $config; - $this->appHelper = $appHelper; - $this->database = $database; - $this->systemMessages = $systemMessages; - $this->aclFormatter = $aclFormatter; + $this->session = $session; + $this->page = $page; + $this->config = $config; + $this->appHelper = $appHelper; + $this->database = $database; + $this->systemMessages = $systemMessages; + $this->aclFormatter = $aclFormatter; $this->eventDispatcher = $eventDispatcher; $owner = Profile::load($this->appHelper, $this->parameters['nickname'] ?? '', false); @@ -109,7 +109,7 @@ class Photos extends \Friendica\Module\BaseProfile if ($visibility === 'public') { // The ACL selector introduced in version 2019.12 sends ACL input data even when the Public visibility is selected $str_contact_allow = $str_circle_allow = $str_contact_deny = $str_circle_deny = ''; - } else if ($visibility === 'custom') { + } elseif ($visibility === 'custom') { // Since we know from the visibility parameter the item should be private, we have to prevent the empty ACL // case that would make it public. So we always append the author's contact id to the allowed contacts. // See https://github.com/friendica/friendica/issues/9672 @@ -155,10 +155,10 @@ class Photos extends \Friendica\Module\BaseProfile } $hook_data = [ - 'src' => '', + 'src' => '', 'filename' => '', 'filesize' => 0, - 'type' => '', + 'type' => '', ]; $hook_data = $this->eventDispatcher->dispatch( @@ -183,7 +183,7 @@ class Photos extends \Friendica\Module\BaseProfile $type = $_FILES['userfile']['type']; $error = $_FILES['userfile']['error']; } else { - $error = UPLOAD_ERR_NO_FILE; + $error = UPLOAD_ERR_NO_FILE; } if ($error !== UPLOAD_ERR_OK) { @@ -314,7 +314,7 @@ class Photos extends \Friendica\Module\BaseProfile $arr['visible'] = $visible; $arr['origin'] = 1; - $arr['body'] = Images::getBBCodeByResource($resource_id, $this->owner['nickname'], $preview, $image->getExt()); + $arr['body'] = Images::getBBCodeByResource($resource_id, $this->owner['nickname'], $preview, $image->getExt()); $item_id = Item::insert($arr); // Update the photo albums cache @@ -383,7 +383,7 @@ class Photos extends \Friendica\Module\BaseProfile $pager->getItemsPerPage() )); - $photos = array_map(function ($photo){ + $photos = array_map(function ($photo) { return [ 'id' => $photo['id'], 'link' => 'photos/' . $this->owner['nickname'] . '/image/' . $photo['resource-id'], diff --git a/src/Module/Profile/Profile.php b/src/Module/Profile/Profile.php index cb75b2fecc..58f829907e 100644 --- a/src/Module/Profile/Profile.php +++ b/src/Module/Profile/Profile.php @@ -78,12 +78,12 @@ class Profile extends BaseProfile ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->database = $database; - $this->appHelper = $appHelper; - $this->session = $session; - $this->config = $config; - $this->page = $page; - $this->profileField = $profileField; + $this->database = $database; + $this->appHelper = $appHelper; + $this->session = $session; + $this->config = $config; + $this->page = $page; + $this->profileField = $profileField; $this->eventDispatcher = $eventDispatcher; } @@ -273,7 +273,7 @@ class Profile extends BaseProfile } $tpl = Renderer::getMarkupTemplate('profile/profile.tpl'); - $o .= Renderer::replaceMacros($tpl, [ + $o .= Renderer::replaceMacros($tpl, [ '$title' => $this->t('Profile'), '$yourself' => $this->t('Yourself'), '$view_as_contacts' => $view_as_contacts, @@ -293,7 +293,7 @@ class Profile extends BaseProfile 'title' => '', 'label' => $this->t('Edit profile') ], - '$viewas_link' => [ + '$viewas_link' => [ 'url' => $this->args->getQueryString() . '#viewas', 'title' => '', 'label' => $this->t('View as') @@ -362,7 +362,7 @@ class Profile extends BaseProfile $htmlhead .= '' . "\n"; $htmlhead .= '' . "\n"; $htmlhead .= '' . "\n"; - $uri = urlencode('acct:' . $profile['nickname'] . '@' . $this->baseUrl->getHost() . ($this->baseUrl->getPath() ? '/' . $this->baseUrl->getPath() : '')); + $uri = urlencode('acct:' . $profile['nickname'] . '@' . $this->baseUrl->getHost() . ($this->baseUrl->getPath() ? '/' . $this->baseUrl->getPath() : '')); $htmlhead .= '' . "\n"; header('Link: <' . $this->baseUrl . '/xrd/?uri=' . $uri . '>; rel="lrdd"; type="application/xrd+xml"', false); diff --git a/src/Module/Register.php b/src/Module/Register.php index 6f641355e3..39ec42cd84 100644 --- a/src/Module/Register.php +++ b/src/Module/Register.php @@ -50,7 +50,7 @@ class Register extends BaseModule $this->tos = new Tos($l10n, $baseUrl, $args, $logger, $profiler, $response, $config, $server, $parameters); - $this->session = $session; + $this->session = $session; $this->eventDispatcher = $eventDispatcher; } diff --git a/src/Module/Search/Acl.php b/src/Module/Search/Acl.php index 3419672b19..410bae9a5e 100644 --- a/src/Module/Search/Acl.php +++ b/src/Module/Search/Acl.php @@ -62,8 +62,8 @@ class Acl extends BaseModule ) { parent::__construct($l10n, $baseUrl, $args, $logger, $profiler, $response, $server, $parameters); - $this->session = $session; - $this->database = $database; + $this->session = $session; + $this->database = $database; $this->eventDispatcher = $eventDispatcher; } @@ -118,9 +118,9 @@ class Acl extends BaseModule private function regularContactSearch(array $request, string $type): array { - $start = $request['start'] ?? 0; - $count = $request['count'] ?? 100; - $search = $request['search'] ?? ''; + $start = $request['start'] ?? 0; + $count = $request['count'] ?? 100; + $search = $request['search'] ?? ''; $conv_id = $request['conversation'] ?? null; // For use with jquery.textcomplete for private mail completion @@ -138,9 +138,9 @@ class Acl extends BaseModule $condition_circle = ["`uid` = ? AND NOT `deleted`", $this->session->getLocalUserId()]; if ($search != '') { - $sql_extra = "AND `name` LIKE '%%" . $this->database->escape($search) . "%%'"; - $condition = DBA::mergeConditions($condition, ["(`attag` LIKE ? OR `name` LIKE ? OR `nick` LIKE ?)", - '%' . $search . '%', '%' . $search . '%', '%' . $search . '%']); + $sql_extra = "AND `name` LIKE '%%" . $this->database->escape($search) . "%%'"; + $condition = DBA::mergeConditions($condition, ["(`attag` LIKE ? OR `name` LIKE ? OR `nick` LIKE ?)", + '%' . $search . '%', '%' . $search . '%', '%' . $search . '%']); $condition_circle = DBA::mergeConditions($condition_circle, ["`name` LIKE ?", '%' . $search . '%']); } @@ -156,21 +156,27 @@ class Acl extends BaseModule switch ($type) { case self::TYPE_MENTION_CONTACT_CIRCLE: case self::TYPE_MENTION_CONTACT: - $condition = DBA::mergeConditions($condition, + $condition = DBA::mergeConditions( + $condition, ["NOT `self` AND NOT `blocked`", - ]); + ] + ); break; case self::TYPE_MENTION_GROUP: - $condition = DBA::mergeConditions($condition, + $condition = DBA::mergeConditions( + $condition, ["NOT `self` AND NOT `blocked` AND (NOT `ap-posting-restricted` OR `ap-posting-restricted` IS NULL) AND `contact-type` = ?", Contact::TYPE_COMMUNITY - ]); + ] + ); break; case self::TYPE_PRIVATE_MESSAGE: - $condition = DBA::mergeConditions($condition, + $condition = DBA::mergeConditions( + $condition, ["NOT `self` AND NOT `blocked` AND `network` IN (?, ?, ?)", Protocol::ACTIVITYPUB, Protocol::DFRN, Protocol::DIASPORA - ]); + ] + ); break; } @@ -184,7 +190,8 @@ class Acl extends BaseModule if ($type == self::TYPE_MENTION_CONTACT_CIRCLE || $type == self::TYPE_MENTION_CIRCLE) { /// @todo We should cache this query. // This can be done when we can delete cache entries via wildcard - $circles = $this->database->toArray($this->database->p("SELECT `circle`.`id`, `circle`.`name`, GROUP_CONCAT(DISTINCT `circle_member`.`contact-id` SEPARATOR ',') AS uids + $circles = $this->database->toArray($this->database->p( + "SELECT `circle`.`id`, `circle`.`name`, GROUP_CONCAT(DISTINCT `circle_member`.`contact-id` SEPARATOR ',') AS uids FROM `group` AS `circle` INNER JOIN `group_member` AS `circle_member` ON `circle_member`.`gid` = `circle`.`id` WHERE NOT `circle`.`deleted` AND `circle`.`uid` = ? diff --git a/src/Module/Settings/Profile/Index.php b/src/Module/Settings/Profile/Index.php index 7b05aceaa6..6f7a3a6204 100644 --- a/src/Module/Settings/Profile/Index.php +++ b/src/Module/Settings/Profile/Index.php @@ -111,7 +111,7 @@ class Index extends BaseSettings if (strpos($dob, '0000-') === 0 || strpos($dob, '0001-') === 0) { $ignore_year = true; - $dob = substr($dob, 5); + $dob = substr($dob, 5); } if ($ignore_year) { @@ -245,7 +245,7 @@ class Index extends BaseSettings $this->session->getLocalUserId(), false, ['allow_cid' => []], - ['network' => Protocol::DFRN], + ['network' => Protocol::DFRN], 'profile_field[new]' ), ], @@ -278,7 +278,8 @@ class Index extends BaseSettings 'miscellaneous_section' => $this->t('Miscellaneous'), 'custom_fields_section' => $this->t('Custom Profile Fields'), 'profile_photo' => $this->t('Upload Profile Photo'), - 'custom_fields_description' => $this->t('

Custom fields appear on your profile page.

+ 'custom_fields_description' => $this->t( + '

Custom fields appear on your profile page.

You can use BBCodes in the field values.

Reorder by dragging the field title.

Empty the label field to remove a custom field.

@@ -314,7 +315,7 @@ class Index extends BaseSettings $hook_data = [ 'profile' => $owner, - 'entry' => $o, + 'entry' => $o, ]; $hook_data = $this->eventDispatcher->dispatch( diff --git a/src/Navigation/Notifications/Repository/Notify.php b/src/Navigation/Notifications/Repository/Notify.php index 17d3e81c44..40caa29437 100644 --- a/src/Navigation/Notifications/Repository/Notify.php +++ b/src/Navigation/Notifications/Repository/Notify.php @@ -74,12 +74,12 @@ class Notify extends BaseRepository EventDispatcherInterface $eventDispatcher, Factory\Notify $factory = null ) { - $this->l10n = $l10n; - $this->baseUrl = $baseUrl; - $this->config = $config; - $this->pConfig = $pConfig; - $this->emailer = $emailer; - $this->notification = $notification; + $this->l10n = $l10n; + $this->baseUrl = $baseUrl; + $this->config = $config; + $this->pConfig = $pConfig; + $this->emailer = $emailer; + $this->notification = $notification; $this->eventDispatcher = $eventDispatcher; parent::__construct($database, $logger, $factory ?? new Factory\Notify($logger)); diff --git a/tests/src/Core/Storage/Repository/StorageManagerTest.php b/tests/src/Core/Storage/Repository/StorageManagerTest.php index 14aa41f5a4..8af22c4b78 100644 --- a/tests/src/Core/Storage/Repository/StorageManagerTest.php +++ b/tests/src/Core/Storage/Repository/StorageManagerTest.php @@ -376,7 +376,7 @@ class StorageManagerTest extends DatabaseTestCase $this->l10n, false ); - $storage = $storageManager->getWritableStorageByName($name); + $storage = $storageManager->getWritableStorageByName($name); $storageManager->move($storage); $photos = $this->database->select('photo', ['backend-ref', 'backend-class', 'id', 'data']); @@ -407,7 +407,7 @@ class StorageManagerTest extends DatabaseTestCase $this->l10n, false ); - $storage = $storageManager->getWritableStorageByName(SystemResource::getName()); + $storage = $storageManager->getWritableStorageByName(SystemResource::getName()); $storageManager->move($storage); } }