Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
pull/1558/head
Maxence Lange 2023-01-04 22:38:23 -01:00
rodzic e63d7916f9
commit 0efe47743e
20 zmienionych plików z 85 dodań i 357 usunięć

Wyświetl plik

@ -50,7 +50,6 @@ use OCA\Social\Service\StreamQueueService;
use OCA\Social\Service\StreamService;
use OCA\Social\Tools\Traits\TAsync;
use OCA\Social\Tools\Traits\TNCDataResponse;
use OCA\Social\Tools\Traits\TNCLogger;
use OCA\Social\Tools\Traits\TStringTools;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
@ -63,7 +62,6 @@ class ActivityPubController extends Controller {
use TNCDataResponse;
use TStringTools;
use TAsync;
use TNCLogger;
private SocialPubController $socialPubController;
private FediverseService $fediverseService;

Wyświetl plik

@ -12,6 +12,9 @@ use OCP\EventDispatcher\IEventListener;
use OCP\Profile\BeforeTemplateRenderedEvent;
use OCP\Util;
/**
* * @template-implements IEventListener<\OCP\Profile\BeforeTemplateRenderedEvent>
*/
class ProfileSectionListener implements IEventListener {
public function handle(Event $event): void {
if (!($event instanceof BeforeTemplateRenderedEvent)) {

Wyświetl plik

@ -70,17 +70,12 @@ class ACore extends Item implements JsonSerializable {
private $parent = null;
private string $requestToken = '';
private array $entries = [];
private ?\OCA\Social\Model\ActivityPub\ACore $object = null;
private ?ACore $object = null;
private ?Document $icon = null;
private bool $displayW3ContextSecurity = false;
private ?LinkedDataSignature $signature = null;
private int $format = self::FORMAT_ACTIVITYPUB;
@ -151,9 +146,9 @@ class ACore extends Item implements JsonSerializable {
}
/**
* @return ACore
* @return null|self
*/
public function getObject(): ACore {
public function getObject(): ?ACore {
return $this->object;
}
@ -162,7 +157,7 @@ class ACore extends Item implements JsonSerializable {
*
* @return ACore
*/
public function setObject(ACore &$object): ACore {
public function setObject(ACore $object): self {
$object->setParent($this);
$this->object = $object;
@ -205,10 +200,7 @@ class ACore extends Item implements JsonSerializable {
return ($this->icon !== null);
}
/**
* @return Document
*/
public function getIcon(): Document {
public function getIcon(): ?Document {
return $this->icon;
}
@ -217,7 +209,7 @@ class ACore extends Item implements JsonSerializable {
*
* @return ACore
*/
public function setIcon(Document &$icon): ACore {
public function setIcon(Document $icon): ACore {
$icon->setParent($this);
$this->icon = $icon;
@ -255,14 +247,11 @@ class ACore extends Item implements JsonSerializable {
/**
* @return bool
*/
public function gotSignature(): bool {
public function hasSignature(): bool {
return ($this->signature !== null);
}
/**
* @return LinkedDataSignature
*/
public function getSignature(): LinkedDataSignature {
public function getSignature(): ?LinkedDataSignature {
return $this->signature;
}
@ -694,14 +683,14 @@ class ACore extends Item implements JsonSerializable {
* @return array
*/
public function exportAsActivityPub(): array {
if ($this->gotSignature()) {
if ($this->hasSignature()) {
$this->entries['signature'] = $this->getSignature();
}
if ($this->isRoot()) {
$context = [self::CONTEXT_ACTIVITYSTREAMS];
if ($this->gotSignature() || $this->isDisplayW3ContextSecurity()) {
if ($this->hasSignature() || $this->isDisplayW3ContextSecurity()) {
array_push($context, self::CONTEXT_SECURITY);
}

Wyświetl plik

@ -228,10 +228,7 @@ class Instance implements IQueryRow, JsonSerializable {
return ($this->contactAccount !== null);
}
/**
* @return Person
*/
public function getContactAccount(): Person {
public function getContactAccount(): ?Person {
return $this->contactAccount;
}

Wyświetl plik

@ -158,10 +158,7 @@ class RequestQueue implements JsonSerializable {
}
/**
* @return InstancePath
*/
public function getInstance(): InstancePath {
public function getInstance(): ?InstancePath {
return $this->instance;
}

Wyświetl plik

@ -30,7 +30,6 @@ declare(strict_types=1);
namespace OCA\Social\Search;
use OCA\Social\Tools\Traits\TNCLogger;
use OCA\Social\Tools\Traits\TArrayTools;
use Exception;
use OCA\Social\Exceptions\AccountDoesNotExistException;
@ -58,30 +57,17 @@ class UnifiedSearchProvider implements IProvider {
public const PROVIDER_ID = 'social';
public const ORDER = 12;
use TArrayTools;
use TNCLogger;
private IL10N $l10n;
private IURLGenerator $urlGenerator;
private StreamService $streamService;
private FollowService $followService;
private CacheActorService $cacheActorService;
private AccountService $accountService;
private SearchService $searchService;
private ConfigService $configService;
private MiscService $miscService;
private ?Person $viewer = null;

Wyświetl plik

@ -30,14 +30,6 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use OCA\Social\Tools\Exceptions\MalformedArrayException;
use OCA\Social\Tools\Exceptions\RequestContentException;
use OCA\Social\Tools\Exceptions\RequestNetworkException;
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
use OCA\Social\Tools\Exceptions\RequestServerException;
use OCA\Social\Tools\Traits\TNCLogger;
use OCA\Social\Tools\Traits\TArrayTools;
use Exception;
use OCA\Social\AP;
use OCA\Social\Db\CacheActorsRequest;
@ -51,7 +43,15 @@ use OCA\Social\Exceptions\RetrieveAccountFormatException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Exceptions\UnauthorizedFediverseException;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Tools\Exceptions\MalformedArrayException;
use OCA\Social\Tools\Exceptions\RequestContentException;
use OCA\Social\Tools\Exceptions\RequestNetworkException;
use OCA\Social\Tools\Exceptions\RequestResultNotJsonException;
use OCA\Social\Tools\Exceptions\RequestResultSizeException;
use OCA\Social\Tools\Exceptions\RequestServerException;
use OCA\Social\Tools\Traits\TArrayTools;
use OCP\IURLGenerator;
use Psr\Log\LoggerInterface;
/**
* Class CacheActorService
@ -60,28 +60,31 @@ use OCP\IURLGenerator;
*/
class CacheActorService {
use TArrayTools;
use TNCLogger;
private \OCP\IURLGenerator $urlGenerator;
private CacheActorsRequest $cacheActorsRequest;
private CurlService $curlService;
private FediverseService $fediverseService;
private ConfigService $configService;
private MiscService $miscService;
private LoggerInterface $logger;
/**
* CacheService constructor.
* CacheActorService constructor.
*/
public function __construct(
IUrlGenerator $urlGenerator, CacheActorsRequest $cacheActorsRequest, CurlService $curlService,
FediverseService $fediverseService, ConfigService $configService, MiscService $miscService
IUrlGenerator $urlGenerator,
CacheActorsRequest $cacheActorsRequest,
CurlService $curlService,
FediverseService $fediverseService,
ConfigService $configService,
LoggerInterface $logger
) {
$this->urlGenerator = $urlGenerator;
$this->cacheActorsRequest = $cacheActorsRequest;
$this->curlService = $curlService;
$this->fediverseService = $fediverseService;
$this->configService = $configService;
$this->miscService = $miscService;
$this->logger = $logger;
}
@ -127,7 +130,7 @@ class CacheActorService {
} catch (CacheActorDoesNotExistException $e) {
$object = $this->curlService->retrieveObject($id);
$this->debug('object retrieved', ['id' => $id, 'object' => $object]);
$this->logger->debug('object retrieved', ['id' => $id, 'object' => $object]);
/** @var Person $actor */
$actor = AP::$activityPub->getItemFromData($object);
@ -205,14 +208,14 @@ class CacheActorService {
} catch (CacheActorDoesNotExistException $e) {
}
$this->debug('getFromAccount', ['account' => $account, 'retrieve' => $retrieve]);
$this->logger->debug('getFromAccount', ['account' => $account, 'retrieve' => $retrieve]);
try {
$actor = $this->cacheActorsRequest->getFromAccount($account);
$this->debug('Found Actor', ['account' => $account, 'actor' => $actor]);
$this->logger->debug('Found Actor', ['account' => $account, 'actor' => $actor]);
} catch (CacheActorDoesNotExistException $e) {
$this->debug('Actor not found', ['account' => $account]);
$this->logger->debug('Actor not found', ['account' => $account]);
if (!$retrieve) {
throw new CacheActorDoesNotExistException();
@ -221,7 +224,7 @@ class CacheActorService {
$actor = $this->curlService->retrieveAccount($account);
$actor->setAccount($account);
try {
$this->warning('Saving Actor', false, ['actor' => $actor]);
$this->logger->debug('Saving Actor', ['actor' => $actor]);
$this->save($actor);
} catch (Exception $e) {

Wyświetl plik

@ -203,16 +203,19 @@ class CacheDocumentService {
/**
* @param $content
* @param string $content
*/
private function resizeImage(&$content) {
private function resizeImage(string &$content) {
try {
$image = ImageResize::createFromString($content);
$image->quality_jpg = 100;
$image->quality_png = 9;
$image->resizeToBestFit(self::RESIZED_WIDTH, self::RESIZED_HEIGHT);
$content = $image->getImageAsString();
$newContent = $image->getImageAsString();
if (!$newContent) {
$content = $newContent;
}
} catch (ImageResizeException $e) {
}
}

Wyświetl plik

@ -276,8 +276,10 @@ class ConfigService {
* @param $key
*
* @return mixed
*
* @psalm-param string $key
*/
public function getSystemValue($key) {
public function getSystemValue(string $key) {
return $this->config->getSystemValue($key, '');
}

Wyświetl plik

@ -238,7 +238,7 @@ class CurlService {
* @throws SocialAppConfigException
* @throws UnauthorizedFediverseException
*/
public function retrieveObject($id): array {
public function retrieveObject(string $id): array {
$this->logger->debug('retrieveObject id=' . $id);
$url = parse_url($id);
$this->mustContains(['path', 'host', 'scheme'], $url);
@ -430,8 +430,6 @@ class CurlService {
/**
* @param Request $request
*
* @return resource
*/
private function generateCurlRequest(Request $request) {
$url = $request->getUsedProtocol() . '://' . $request->getHost() . $request->getParsedUrl();

Wyświetl plik

@ -232,7 +232,9 @@ class FollowService {
/**
* @param Person $actor
*
* @return Person[]
* @return Follow[]
*
* @psalm-return array<Follow>
*/
public function getFollowers(Person $actor): array {
return $this->followsRequest->getFollowersByActorId($actor->getId());
@ -257,7 +259,9 @@ class FollowService {
/**
* @param Person $actor
*
* @return Person[]
* @return Follow[]
*
* @psalm-return array<Follow>
*/
public function getFollowing(Person $actor): array {
return $this->followsRequest->getFollowingByActorId($actor->getId());

Wyświetl plik

@ -39,7 +39,6 @@ use OCA\Social\Exceptions\HashtagDoesNotExistException;
use OCA\Social\Exceptions\ItemUnknownException;
use OCA\Social\Exceptions\SocialAppConfigException;
use OCA\Social\Model\ActivityPub\Object\Note;
use OCA\Social\Model\ActivityPub\Stream;
class HashtagService {
public const TREND_1H = 3600;
@ -155,10 +154,9 @@ class HashtagService {
/**
* @param int $timestamp
*
* @return Stream[]
* @return int[]
* @throws DateTimeException
* @throws ItemUnknownException
* @throws SocialAppConfigException
* @psalm-return array<int>
*/
private function getTrendSince(int $timestamp): array {
$result = [];

Wyświetl plik

@ -58,7 +58,7 @@ class MiscService {
* @param $message
* @param int $level
*/
public function log($message, $level = 2) {
public function log(string $message, $level = 2) {
$data = array(
'app' => Application::APP_NAME,
'level' => $level

Wyświetl plik

@ -97,7 +97,7 @@ class PostService {
* @throws StreamNotFoundException
* @throws UnauthorizedFediverseException
*/
public function createPost(Post $post, string &$token = ''): ACore {
public function createPost(Post $post, string &$token = ''): ?ACore {
$this->fixRecipientAndHashtags($post);
$note = new Note();
@ -130,10 +130,10 @@ class PostService {
private function generateDocumentsFromAttachments(Note $note, Post $post) {
$documents = [];
if (!isset($_FILES['attachments'])) {
return [];
return;
}
if (is_array($_FILES["attachments"]["error"])) {
foreach ($_FILES["attachments"]["error"] as $key => $error) {
if (is_array($_FILES['attachments']['error'])) {
foreach ($_FILES['attachments']['error'] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
try {
$document = $this->generateDocumentFromAttachment($note, $key);

Wyświetl plik

@ -31,10 +31,10 @@ declare(strict_types=1);
namespace OCA\Social\Service;
use OCA\Social\Tools\Traits\TNCLogger;
use OCA\Social\Tools\Traits\TArrayTools;
use Exception;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Tools\Traits\TArrayTools;
use Psr\Log\LoggerInterface;
/**
* Class SearchService
@ -43,7 +43,6 @@ use OCA\Social\Model\ActivityPub\Actor\Person;
*/
class SearchService {
use TArrayTools;
use TNCLogger;
public const SEARCH_ACCOUNTS = 1;
@ -51,14 +50,10 @@ class SearchService {
public const SEARCH_CONTENT = 4;
public const SEARCH_ALL = 7;
private CacheActorService $cacheActorService;
private HashtagService $hashtagService;
private ConfigService $configService;
private MiscService $miscService;
private LoggerInterface $logger;
/**
@ -67,16 +62,18 @@ class SearchService {
* @param CacheActorService $cacheActorService
* @param HashtagService $hashtagService
* @param ConfigService $configService
* @param MiscService $miscService
* @param LoggerInterface $logger
*/
public function __construct(
CacheActorService $cacheActorService, HashtagService $hashtagService,
ConfigService $configService, MiscService $miscService
CacheActorService $cacheActorService,
HashtagService $hashtagService,
ConfigService $configService,
LoggerInterface $logger
) {
$this->cacheActorService = $cacheActorService;
$this->hashtagService = $hashtagService;
$this->configService = $configService;
$this->miscService = $miscService;
$this->logger = $logger;
}
@ -100,7 +97,7 @@ class SearchService {
try {
$this->cacheActorService->getFromAccount($search);
} catch (Exception $e) {
$this->exception($e, self::$NOTICE, ['search' => $search]);
$this->logger->notice('searchAccounts', ['exception' => $e, 'search' => $search]);
}
return $this->cacheActorService->searchCachedAccounts($search);

Wyświetl plik

@ -451,7 +451,7 @@ class SignatureService {
*
* @return array
*/
private function parseSignatureHeader($signatureHeader) {
private function parseSignatureHeader(string $signatureHeader) {
$sign = [];
$entries = explode(',', $signatureHeader);
@ -504,7 +504,7 @@ class SignatureService {
* @return string
* @throws InvalidOriginException
*/
private function getKeyOrigin($id) {
private function getKeyOrigin(string $id) {
$host = parse_url($id, PHP_URL_HOST);
if (is_string($host) && ($host !== '')) {
return $host;

Wyświetl plik

@ -544,7 +544,7 @@ class StreamService {
* @throws RequestResultNotJsonException
* @throws UnauthorizedFediverseException
*/
public function getAuthorFromPostId($noteId) {
public function getAuthorFromPostId(string $noteId) {
$note = $this->streamRequest->getStreamById($noteId);
return $this->cacheActorService->getFromId($note->getAttributedTo());

Wyświetl plik

@ -455,7 +455,10 @@ class Request implements JsonSerializable {
}
public function addHeader($key, $value): Request {
/**
* @psalm-param string $key
*/
public function addHeader(string $key, string $value): Request {
$header = $this->get($key, $this->headers);
if ($header !== '') {
$header .= ', ' . $value;

Wyświetl plik

@ -1,200 +0,0 @@
<?php
declare(strict_types=1);
/**
* Some tools for myself.
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Maxence Lange <maxence@artificial-owl.com>
* @copyright 2020, Maxence Lange <maxence@artificial-owl.com>
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Social\Tools\Traits;
use Exception;
use OC\HintException;
use OCP\Server;
use Psr\Log\LoggerInterface;
use Throwable;
trait TNCLogger {
use TNCSetup;
public static int $EMERGENCY = 4;
public static int $ALERT = 3;
public static int $CRITICAL = 3;
public static int $ERROR = 3;
public static int $WARNING = 2;
public static int $NOTICE = 1;
public static int $INFO = 1;
public static int $DEBUG = 0;
/**
* @param Throwable $t
* @param array $serializable
*/
public function t(Throwable $t, array $serializable = []): void {
$this->throwable($t, self::$ERROR, $serializable);
}
/**
* @param Throwable $t
* @param int $level
* @param array $serializable
*/
public function throwable(Throwable $t, int $level = 3, array $serializable = []): void {
$message = '';
if (!empty($serializable)) {
$message = json_encode($serializable);
}
$this->logger()
->log(
$level,
$message,
[
'app' => $this->setup('app'),
'exception' => $t
]
);
}
/**
* @param Exception $e
* @param array $serializable
*/
public function e(Exception $e, array $serializable = []): void {
$this->exception($e, self::$ERROR, $serializable);
}
/**
* @param Exception $e
* @param int|array $level
* @param array $serializable
*/
public function exception(Exception $e, $level = 3, array $serializable = []): void {
if (is_array($level) && empty($serializable)) {
$serializable = $level;
$level = 3;
}
$message = '';
if (!empty($serializable)) {
$message = json_encode($serializable);
}
if ($level === self::$DEBUG) {
$level = (int)$this->appConfig('debug_level');
}
$this->logger()
->log(
$level,
$message,
[
'app' => $this->setup('app'),
'exception' => $e
]
);
}
/**
* @param string $message
* @param bool $trace
* @param array $serializable
*/
public function emergency(string $message, bool $trace = false, array $serializable = []): void {
$this->log(self::$EMERGENCY, '[emergency] ' . $message, $trace, $serializable);
}
/**
* @param string $message
* @param bool $trace
* @param array $serializable
*/
public function alert(string $message, bool $trace = false, array $serializable = []): void {
$this->log(self::$ALERT, '[alert] ' . $message, $trace, $serializable);
}
/**
* @param string $message
* @param bool $trace
* @param array $serializable
*/
public function warning(string $message, bool $trace = false, array $serializable = []): void {
$this->log(self::$WARNING, '[warning] ' . $message, $trace, $serializable);
}
/**
* @param string $message
* @param bool $trace
* @param array $serializable
*/
public function notice(string $message, bool $trace = false, array $serializable = []): void {
$this->log(self::$NOTICE, '[notice] ' . $message, $trace, $serializable);
}
/**
* @param string $message
* @param array $serializable
*/
public function debug(string $message, array $serializable = []): void {
$message = '[debug] ' . $message;
$debugLevel = (int)$this->appConfig('debug_level');
$this->log($debugLevel, $message, ($this->appConfig('debug_trace') === '1'), $serializable);
}
/**
* @param int $level
* @param string $message
* @param bool $trace
* @param array $serializable
*/
public function log(int $level, string $message, bool $trace = false, array $serializable = []): void {
$opts = ['app' => $this->setup('app')];
if ($trace) {
$opts['exception'] = new HintException($message, json_encode($serializable));
} elseif (!empty($serializable)) {
$message .= ' -- ' . json_encode($serializable);
}
$this->logger()
->log($level, $message, $opts);
}
/**
* @return LoggerInterface
*/
public function logger(): LoggerInterface {
if (isset($this->logger) && $this->logger instanceof LoggerInterface) {
return $this->logger;
} else {
return Server::get(LoggerInterface::class);
}
}
}

Wyświetl plik

@ -1,10 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<files psalm-version="4.30.0@d0bc6e25d89f649e4f36a534f330f8bb4643dd69">
<file src="lib/AP.php">
<InvalidScalarArgument occurrences="1">
<code>$level</code>
</InvalidScalarArgument>
</file>
<files psalm-version="5.4.0@62db5d4f6a7ae0a20f7cc5a4952d730272fc0863">
<file src="lib/Model/ActivityPub/ACore.php">
<InvalidArgument occurrences="1">
<code>['a', 'p', 'span', 'br']</code>
@ -12,20 +7,15 @@
<InvalidClass occurrences="1">
<code>Acore</code>
</InvalidClass>
<InvalidNullableReturnType occurrences="4">
<InvalidNullableReturnType occurrences="1">
<code>ACore</code>
<code>ACore</code>
<code>Document</code>
<code>LinkedDataSignature</code>
</InvalidNullableReturnType>
<InvalidPropertyAssignmentValue occurrences="1">
<code>$parent</code>
</InvalidPropertyAssignmentValue>
<NullableReturnStatement occurrences="4">
<code>$this-&gt;icon</code>
<code>$this-&gt;object</code>
<NullableReturnStatement occurrences="1">
<code>$this-&gt;parent</code>
<code>$this-&gt;signature</code>
</NullableReturnStatement>
<TypeDoesNotContainNull occurrences="1">
<code>$v === null</code>
@ -40,28 +30,13 @@
<code>$object = $cache-&gt;getItem($this-&gt;getObjectId())</code>
</RedundantCondition>
</file>
<file src="lib/Model/Instance.php">
<InvalidNullableReturnType occurrences="1">
<code>Person</code>
</InvalidNullableReturnType>
<NullableReturnStatement occurrences="1">
<code>$this-&gt;contactAccount</code>
</NullableReturnStatement>
</file>
<file src="lib/Model/RequestQueue.php">
<InvalidNullableReturnType occurrences="1">
<code>InstancePath</code>
</InvalidNullableReturnType>
<NullableReturnStatement occurrences="1">
<code>$this-&gt;instance</code>
</NullableReturnStatement>
</file>
<file src="lib/Db/CoreRequestBuilder.php">
<UndefinedMethod occurrences="3">
<code>dropTable</code>
<code>hasTable</code>
<code>hasTable</code>
</UndefinedMethod>
<InvalidArgument occurrences="2"/>
</file>
<file src="lib/Service/CheckService.php">
<RedundantCast occurrences="1">
@ -81,36 +56,16 @@
<TypeDoesNotContainType occurrences="1">
<code>$this-&gt;maxDownloadSizeReached === true</code>
</TypeDoesNotContainType>
</file>
<file src="lib/Service/FollowService.php">
<InvalidReturnStatement occurrences="2">
<code>$this-&gt;followsRequest-&gt;getFollowersByActorId($actor-&gt;getId())</code>
<code>$this-&gt;followsRequest-&gt;getFollowingByActorId($actor-&gt;getId())</code>
</InvalidReturnStatement>
<InvalidReturnType occurrences="2">
<code>Person[]</code>
<code>Person[]</code>
</InvalidReturnType>
</file>
<file src="lib/Service/HashtagService.php">
<InvalidReturnStatement occurrences="1">
<code>$result</code>
</InvalidReturnStatement>
<InvalidReturnType occurrences="1">
<code>Stream[]</code>
</InvalidReturnType>
<InvalidArgument occurrences="8"/>
</file>
<file src="lib/Service/PostService.php">
<InvalidNullableReturnType occurrences="1">
<code>ACore</code>
</InvalidNullableReturnType>
<NullableReturnStatement occurrences="1">
<code>$activity</code>
</NullableReturnStatement>
<UndefinedMethod occurrences="2">
<code>setAttributedTo</code>
<code>setContent</code>
</UndefinedMethod>
<TypeDoesNotContainType occurrences="1">
<code>is_array($_FILES['attachments']['error'])</code>
</TypeDoesNotContainType>
</file>
<file src="lib/Service/SearchService.php">
<InvalidOperand occurrences="3">
@ -131,9 +86,4 @@
<code>$username === null</code>
</TypeDoesNotContainNull>
</file>
<file src="lib/Tools/Traits/TNCLogger.php">
<UndefinedClass occurrences="1">
<code>HintException</code>
</UndefinedClass>
</file>
</files>