build: add phpstan-codeigniter extension to manage config(), model() and service() functions

This commit is contained in:
Yassine Doghri 2023-08-29 12:58:20 +00:00
parent ae57601c83
commit 77c2d08b6e
15 changed files with 181 additions and 41 deletions

View File

@ -101,9 +101,9 @@ class EpisodeAudioController extends Controller
$subscription = null;
// check if podcast is already unlocked before any token validation
if ($this->episode->is_premium && ($subscription = service('premium_podcasts')->subscription(
if ($this->episode->is_premium && ! ($subscription = service('premium_podcasts')->subscription(
$this->episode->podcast->handle
)) === null) {
)) instanceof Subscription) {
// look for token as GET parameter
if (($token = $this->request->getGet('token')) === null) {
return $this->response->setStatusCode(401)
@ -164,7 +164,7 @@ class EpisodeAudioController extends Controller
$audioDuration,
$this->episode->published_at->getTimestamp(),
$serviceName,
$subscription !== null ? $subscription->id : null
$subscription instanceof Subscription ? $subscription->id : null
);
return redirect()->to($this->analyticsConfig->getAudioUrl($this->episode, $this->request->getGet()));

View File

@ -177,8 +177,8 @@ class EpisodeController extends BaseController
$session = Services::session();
$session->start();
if (isset($_SERVER['HTTP_REFERER'])) {
$session->set('embed_domain', parse_url((string) $_SERVER['HTTP_REFERER'], PHP_URL_HOST));
if (service('superglobals')->server('HTTP_REFERER') !== null) {
$session->set('embed_domain', parse_url(service('superglobals')->server('HTTP_REFERER'), PHP_URL_HOST));
}
$cacheName = implode(

View File

@ -43,7 +43,7 @@ class FeedController extends Controller
$service = null;
try {
$service = UserAgentsRSS::find($_SERVER['HTTP_USER_AGENT']);
$service = UserAgentsRSS::find(service('superglobals')->server('HTTP_USER_AGENT'));
} catch (Exception $exception) {
// If things go wrong the show must go on and the user must be able to download the file
log_message('critical', $exception->getMessage());

View File

@ -16,13 +16,14 @@ if (! function_exists('host_url')) {
*/
function host_url(): ?string
{
if (isset($_SERVER['HTTP_HOST'])) {
$superglobals = service('superglobals');
if ($superglobals->server('HTTP_HOST') !== null) {
$protocol =
(isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
$_SERVER['SERVER_PORT'] === 443
($superglobals->server('HTTPS') !== null && $superglobals->server('HTTPS') !== 'off') ||
(int) $superglobals->server('SERVER_PORT') === 443
? 'https://'
: 'http://';
return $protocol . $_SERVER['HTTP_HOST'] . '/';
return $protocol . $superglobals->server('HTTP_HOST') . '/';
}
return null;

View File

@ -29,13 +29,15 @@
"yassinedoghri/podcast-feed": "dev-main"
},
"require-dev": {
"mikey179/vfsstream": "^v1.6.11",
"phpunit/phpunit": "^10.3.2",
"captainhook/captainhook": "^5.16.4",
"symplify/easy-coding-standard": "^12.0.7",
"codeigniter/phpstan-codeigniter": "^1.0",
"mikey179/vfsstream": "^v1.6.11",
"phpstan/extension-installer": "^1.3",
"phpstan/phpstan": "^1.10.32",
"phpunit/phpunit": "^10.3.2",
"rector/rector": "^0.18.0",
"symplify/coding-standard": "^12.0.3"
"symplify/coding-standard": "^12.0.3",
"symplify/easy-coding-standard": "^12.0.7"
},
"autoload": {
"exclude-from-classmap": [

111
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "4526c68d78e5abe8e5c86016356e15f9",
"content-hash": "02db4cf9b79f67dad431f7d10f5c19f4",
"packages": [
{
"name": "adaures/ipcat-php",
@ -3224,6 +3224,73 @@
],
"time": "2023-04-17T19:48:47+00:00"
},
{
"name": "codeigniter/phpstan-codeigniter",
"version": "v1.0.0",
"source": {
"type": "git",
"url": "https://github.com/CodeIgniter/phpstan-codeigniter.git",
"reference": "2c6eebd9798e463ea8596493bd068310b7a701d9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/CodeIgniter/phpstan-codeigniter/zipball/2c6eebd9798e463ea8596493bd068310b7a701d9",
"reference": "2c6eebd9798e463ea8596493bd068310b7a701d9",
"shasum": ""
},
"require": {
"php": "^8.1",
"phpstan/phpstan": "^1.10"
},
"conflict": {
"codeigniter/framework": "*"
},
"require-dev": {
"codeigniter/coding-standard": "^1.7",
"codeigniter4/framework": "^4.3",
"friendsofphp/php-cs-fixer": "^3.20",
"nexusphp/cs-config": "^3.12",
"phpstan/extension-installer": "^1.3",
"phpstan/phpstan-deprecation-rules": "^1.1",
"phpstan/phpstan-phpunit": "^1.3",
"phpstan/phpstan-strict-rules": "^1.5",
"phpunit/phpunit": "^10.2"
},
"type": "phpstan-extension",
"extra": {
"phpstan": {
"includes": ["extension.neon"]
}
},
"autoload": {
"psr-4": {
"CodeIgniter\\PHPStan\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": ["MIT"],
"authors": [
{
"name": "John Paul E. Balandan, CPA",
"email": "paulbalandan@gmail.com"
}
],
"description": "CodeIgniter extensions and rules for PHPStan",
"keywords": [
"PHPStan",
"codeigniter",
"codeigniter4",
"dev",
"static analysis"
],
"support": {
"forum": "http://forum.codeigniter.com/",
"issues": "https://github.com/CodeIgniter/phpstan-codeigniter/issues",
"slack": "https://codeigniterchat.slack.com",
"source": "https://github.com/CodeIgniter/phpstan-codeigniter"
},
"time": "2023-08-27T09:19:23+00:00"
},
{
"name": "composer/pcre",
"version": "3.1.0",
@ -3905,6 +3972,48 @@
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "phpstan/extension-installer",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/extension-installer.git",
"reference": "f45734bfb9984c6c56c4486b71230355f066a58a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/extension-installer/zipball/f45734bfb9984c6c56c4486b71230355f066a58a",
"reference": "f45734bfb9984c6c56c4486b71230355f066a58a",
"shasum": ""
},
"require": {
"composer-plugin-api": "^2.0",
"php": "^7.2 || ^8.0",
"phpstan/phpstan": "^1.9.0"
},
"require-dev": {
"composer/composer": "^2.0",
"php-parallel-lint/php-parallel-lint": "^1.2.0",
"phpstan/phpstan-strict-rules": "^0.11 || ^0.12 || ^1.0"
},
"type": "composer-plugin",
"extra": {
"class": "PHPStan\\ExtensionInstaller\\Plugin"
},
"autoload": {
"psr-4": {
"PHPStan\\ExtensionInstaller\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": ["MIT"],
"description": "Composer plugin for automatic installation of PHPStan extensions",
"support": {
"issues": "https://github.com/phpstan/extension-installer/issues",
"source": "https://github.com/phpstan/extension-installer/tree/1.3.1"
},
"time": "2023-05-24T08:59:17+00:00"
},
{
"name": "phpstan/phpstan",
"version": "1.10.32",

View File

@ -17,6 +17,7 @@ use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\I18n\Time;
use Exception;
use Modules\Fediverse\Config\Fediverse;
use Modules\Fediverse\Entities\Activity;
use Modules\Fediverse\Entities\Actor;
use Modules\Fediverse\Entities\Post;
use Modules\Fediverse\Objects\OrderedCollectionObject;
@ -45,7 +46,7 @@ class ActorController extends Controller
}
if (
($actor = model('ActorModel', false)->getActorByUsername($params[0])) === null
! ($actor = model('ActorModel', false)->getActorByUsername($params[0])) instanceof Actor
) {
throw PageNotFoundException::forPageNotFound();
}
@ -101,7 +102,7 @@ class ActorController extends Controller
->getPostByUri($payload->object->inReplyTo);
$reply = null;
if ($replyToPost !== null) {
if ($replyToPost instanceof Post) {
// TODO: strip content from html to retrieve message
// remove all html tags and reconstruct message with mentions?
$message = get_message_from_object($payload->object);
@ -136,7 +137,7 @@ class ActorController extends Controller
$postToDelete = model('PostModel', false)
->getPostByUri($payload->object->id);
if ($postToDelete !== null) {
if ($postToDelete instanceof Post) {
model('PostModel', false)
->removePost($postToDelete, false);
}
@ -160,7 +161,7 @@ class ActorController extends Controller
$post = model('PostModel', false)
->getPostByUri($payload->object);
if ($post !== null) {
if ($post instanceof Post) {
// Like side-effect
model('FavouriteModel', false)
->addFavourite($payloadActor, $post, false);
@ -177,7 +178,7 @@ class ActorController extends Controller
$post = model('PostModel', false)
->getPostByUri($payload->object);
if ($post !== null) {
if ($post instanceof Post) {
model('ActivityModel', false)
->update($activityId, [
'post_id' => $post->id,
@ -205,7 +206,7 @@ class ActorController extends Controller
$post = model('PostModel', false)
->getPostByUri($payload->object->object);
if ($post !== null) {
if ($post instanceof Post) {
// revert side-effect by removing favourite from database
model('FavouriteModel', false)
->removeFavourite($payloadActor, $post, false);
@ -223,7 +224,7 @@ class ActorController extends Controller
->getPostByUri($payload->object->object);
$reblogPost = null;
if ($post !== null) {
if ($post instanceof Post) {
$reblogPost = model('PostModel', false)
->where([
'actor_id' => $payloadActor->id,
@ -374,7 +375,7 @@ class ActorController extends Controller
public function activity(string $activityId): ResponseInterface
{
if (
! ($activity = model('ActivityModel', false)->getActivityById($activityId))
! ($activity = model('ActivityModel', false)->getActivityById($activityId)) instanceof Activity
) {
throw PageNotFoundException::forPageNotFound();
}

View File

@ -50,7 +50,7 @@ class PostController extends Controller
public function _remap(string $method, string ...$params): mixed
{
if (($post = model('PostModel', false)->getPostById($params[0])) === null) {
if (! ($post = model('PostModel', false)->getPostById($params[0])) instanceof Post) {
throw PageNotFoundException::forPageNotFound();
}

View File

@ -102,7 +102,7 @@ class Actor extends Entity
}
if ($this->followers === null) {
$this->followers = (array) model('ActorModel', false)
$this->followers = model('ActorModel', false)
->getFollowers($this->id);
}

View File

@ -126,7 +126,7 @@ class Post extends UuidEntity
}
if ($this->replies === null) {
$this->replies = (array) model('PostModel', false)
$this->replies = model('PostModel', false)
->getPostReplies($this->id);
}
@ -162,7 +162,7 @@ class Post extends UuidEntity
}
if ($this->reblogs === null) {
$this->reblogs = (array) model('PostModel', false)
$this->reblogs = model('PostModel', false)
->getPostReblogs($this->id);
}

View File

@ -212,8 +212,8 @@ if (! function_exists('get_or_create_preview_card_from_url')) {
{
// check if preview card has already been generated
if (
$previewCard = model('PreviewCardModel', false)
->getPreviewCardFromUrl((string) $url)
($previewCard = model('PreviewCardModel', false)
->getPreviewCardFromUrl((string) $url)) instanceof PreviewCard
) {
return $previewCard;
}
@ -231,7 +231,7 @@ if (! function_exists('get_or_create_actor_from_uri')) {
function get_or_create_actor_from_uri(string $actorUri): ?Actor
{
// check if actor exists in database already and return it
if ($actor = model('ActorModel', false)->getActorByUri($actorUri)) {
if (($actor = model('ActorModel', false)->getActorByUri($actorUri)) instanceof Actor) {
return $actor;
}
@ -249,8 +249,8 @@ if (! function_exists('get_or_create_actor')) {
{
// check if actor exists in database already and return it
if (
$actor = model('ActorModel', false)
->getActorByUsername($username, $domain)
($actor = model('ActorModel', false)
->getActorByUsername($username, $domain)) instanceof Actor
) {
return $actor;
}
@ -412,9 +412,9 @@ if (! function_exists('linkify')) {
// check if host is set and look for actor in database
if (isset($match['host'])) {
if (
$actor = model(
($actor = model(
'ActorModel',
)->getActorByUsername($match['username'], $match['domain'])
)->getActorByUsername($match['username'], $match['domain'])) instanceof Actor
) {
// TODO: check that host is local to remove target blank?
return '<' .
@ -447,8 +447,8 @@ if (! function_exists('linkify')) {
}
} else {
if (
$actor = model('ActorModel', false)
->getActorByUsername($match['username'])
($actor = model('ActorModel', false)
->getActorByUsername($match['username'])) instanceof Actor
) {
return '<' .
array_push($links, anchor($actor->uri, $match[0])) .

View File

@ -11,6 +11,7 @@ declare(strict_types=1);
namespace Modules\Fediverse;
use Exception;
use Modules\Fediverse\Entities\Actor;
class WebFinger
{
@ -62,7 +63,7 @@ class WebFinger
}
if (
! ($actor = model('ActorModel', false)->getActorByUsername($username, $domain))
! ($actor = model('ActorModel', false)->getActorByUsername($username, $domain)) instanceof Actor
) {
throw new Exception('Could not find actor');
}

View File

@ -4,14 +4,16 @@ declare(strict_types=1);
namespace Modules\PremiumPodcasts\Config;
use Config\Services as BaseService;
use CodeIgniter\Config\BaseService;
use Modules\PremiumPodcasts\Models\SubscriptionModel;
use Modules\PremiumPodcasts\PremiumPodcasts;
class Services extends BaseService
{
public static function premium_podcasts(?SubscriptionModel $subscriptionModel = null, bool $getShared = true)
{
public static function premium_podcasts(
?SubscriptionModel $subscriptionModel = null,
bool $getShared = true
): PremiumPodcasts {
if ($getShared) {
return self::getSharedInstance('premium_podcasts', $subscriptionModel);
}

View File

@ -16,11 +16,34 @@ parameters:
- app/Views/*
- modules/*/Views/*
- themes/*
codeigniter:
additionalConfigNamespaces:
- Modules\Admin\Config\
- Modules\Analytics\Config\
- Modules\Api\Rest\V1\Config\
- Modules\Auth\Config\
- Modules\Fediverse\Config\
- Modules\Install\Config\
- Modules\Media\Config\
- Modules\MediaClipper\Config\
- Modules\PodcastImport\Config\
- Modules\PremiumPodcasts\Config\
- Modules\WebSub\Config\
additionalModelNamespaces:
- Modules\Analytics\Models\
- Modules\Auth\Models\
- Modules\Fediverse\Models\
- Modules\Media\Models\
- Modules\PremiumPodcasts\Models\
additionalServices:
- CodeIgniter\Settings\Config\Services
- Michalsn\Uuid\Config\Services
- Modules\PremiumPodcasts\Config\Services
- Modules\Media\Config\Services
dynamicConstantNames:
- APP_NAMESPACE
- CI_DEBUG
- ENVIRONMENT
- SODIUM_LIBRARY_VERSION
ignoreErrors:
- '#^Access to an undefined property Modules\\Media\\Entities\\Image#'
- '#^Call to an undefined method CodeIgniter\\Cache\\CacheInterface\:\:deleteMatching\(\)#'

View File

@ -71,4 +71,5 @@ return static function (RectorConfig $rectorConfig): void {
// Path to phpstan with extensions, that PHPStan in Rector uses to determine types
$rectorConfig->phpstanConfig(__DIR__ . '/phpstan.neon');
$rectorConfig->phpstanConfigs(['vendor/codeigniter/phpstan-codeigniter/extension.neon']);
};