mirror of
https://github.com/flarum/framework.git
synced 2024-11-22 08:48:39 +08:00
chore: Setup PHPStan Level 5 (#3553)
This commit is contained in:
parent
b2fa28e4b5
commit
fc4d5e3d43
|
@ -20,3 +20,6 @@ indent_size = 4
|
||||||
|
|
||||||
[tsconfig.json]
|
[tsconfig.json]
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.neon]
|
||||||
|
indent_style = tab
|
||||||
|
|
38
.github/workflows/REUSABLE_backend.yml
vendored
38
.github/workflows/REUSABLE_backend.yml
vendored
|
@ -9,6 +9,12 @@ on:
|
||||||
default: true
|
default: true
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
|
enable_phpstan:
|
||||||
|
description: "Enable PHPStan Static Analysis?"
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
required: false
|
||||||
|
|
||||||
backend_directory:
|
backend_directory:
|
||||||
description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo.
|
description: The directory of the project where backend code is located. This should contain a `composer.json` file, and is generally the root directory of the repo.
|
||||||
type: string
|
type: string
|
||||||
|
@ -130,3 +136,35 @@ jobs:
|
||||||
working-directory: ${{ inputs.backend_directory }}
|
working-directory: ${{ inputs.backend_directory }}
|
||||||
env:
|
env:
|
||||||
COMPOSER_PROCESS_TIMEOUT: 600
|
COMPOSER_PROCESS_TIMEOUT: 600
|
||||||
|
|
||||||
|
phpstan:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
php: ${{ fromJSON(inputs.php_versions) }}
|
||||||
|
|
||||||
|
name: 'PHPStan PHP ${{ matrix.php }}'
|
||||||
|
|
||||||
|
if: >-
|
||||||
|
inputs.enable_phpstan &&
|
||||||
|
((github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name != github.repository) || github.event_name != 'pull_request')
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@master
|
||||||
|
|
||||||
|
- name: Setup PHP
|
||||||
|
uses: shivammathur/setup-php@v2
|
||||||
|
with:
|
||||||
|
php-version: ${{ matrix.php }}
|
||||||
|
coverage: xdebug
|
||||||
|
extensions: curl, dom, gd, json, mbstring, openssl, pdo_mysql, tokenizer, zip
|
||||||
|
tools: phpunit, composer:v2
|
||||||
|
ini-values: ${{ inputs.php_ini_values }}
|
||||||
|
|
||||||
|
- name: Install Composer dependencies
|
||||||
|
run: composer install
|
||||||
|
working-directory: ${{ inputs.backend_directory }}
|
||||||
|
|
||||||
|
- name: Run PHPStan
|
||||||
|
run: composer analyse:phpstan
|
||||||
|
|
12
.github/workflows/phpstan.yml
vendored
Normal file
12
.github/workflows/phpstan.yml
vendored
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
name: Framework PHP
|
||||||
|
|
||||||
|
on: [workflow_dispatch, push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
run:
|
||||||
|
uses: ./.github/workflows/REUSABLE_backend.yml
|
||||||
|
with:
|
||||||
|
enable_backend_testing: false
|
||||||
|
enable_phpstan: true
|
||||||
|
|
||||||
|
backend_directory: .
|
|
@ -140,8 +140,8 @@
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"mockery/mockery": "^1.4",
|
"mockery/mockery": "^1.4",
|
||||||
"phpunit/phpunit": "^9.0",
|
"phpunit/phpunit": "^9.0",
|
||||||
"phpstan/phpstan-php-parser": "^1.0",
|
"phpstan/phpstan": "^1.2",
|
||||||
"phpstan/phpstan": "^1.2"
|
"nunomaduro/larastan": "^1.0"
|
||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"sort-packages": true
|
"sort-packages": true
|
||||||
|
@ -178,5 +178,11 @@
|
||||||
"extension.neon"
|
"extension.neon"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"analyse:phpstan": "phpstan analyse"
|
||||||
|
},
|
||||||
|
"scripts-descriptions": {
|
||||||
|
"analyse:phpstan": "Run static analysis"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ namespace Flarum\Api;
|
||||||
|
|
||||||
use Flarum\Http\RequestUtil;
|
use Flarum\Http\RequestUtil;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
use Illuminate\Contracts\Container\Container;
|
|
||||||
use Laminas\Diactoros\ServerRequestFactory;
|
use Laminas\Diactoros\ServerRequestFactory;
|
||||||
use Laminas\Diactoros\Uri;
|
use Laminas\Diactoros\Uri;
|
||||||
use Laminas\Stratigility\MiddlewarePipeInterface;
|
use Laminas\Stratigility\MiddlewarePipeInterface;
|
||||||
|
@ -26,12 +25,12 @@ class Client
|
||||||
protected $pipe;
|
protected $pipe;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var User
|
* @var User|null
|
||||||
*/
|
*/
|
||||||
protected $actor;
|
protected $actor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ServerRequestInterface
|
* @var ServerRequestInterface|null
|
||||||
*/
|
*/
|
||||||
protected $parent;
|
protected $parent;
|
||||||
|
|
||||||
|
@ -45,9 +44,6 @@ class Client
|
||||||
*/
|
*/
|
||||||
protected $body = [];
|
protected $body = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Container $container
|
|
||||||
*/
|
|
||||||
public function __construct(MiddlewarePipeInterface $pipe)
|
public function __construct(MiddlewarePipeInterface $pipe)
|
||||||
{
|
{
|
||||||
$this->pipe = $pipe;
|
$this->pipe = $pipe;
|
||||||
|
|
|
@ -88,7 +88,7 @@ abstract class AbstractSerializeController implements RequestHandlerInterface
|
||||||
protected static $beforeSerializationCallbacks = [];
|
protected static $beforeSerializationCallbacks = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string[]
|
* @var string[][]
|
||||||
*/
|
*/
|
||||||
protected static $loadRelations = [];
|
protected static $loadRelations = [];
|
||||||
|
|
||||||
|
|
|
@ -113,15 +113,15 @@ class ListNotificationsController extends AbstractListController
|
||||||
$ids = [];
|
$ids = [];
|
||||||
|
|
||||||
foreach ($notifications as $notification) {
|
foreach ($notifications as $notification) {
|
||||||
if ($notification->subject && $notification->subject->discussion_id) {
|
if ($notification->subject && isset($notification->subject->discussion_id)) {
|
||||||
$ids[] = $notification->subject->discussion_id;
|
$ids[] = $notification->subject->discussion_id;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$discussions = Discussion::find(array_unique($ids));
|
$discussions = Discussion::query()->find(array_unique($ids));
|
||||||
|
|
||||||
foreach ($notifications as $notification) {
|
foreach ($notifications as $notification) {
|
||||||
if ($notification->subject && $notification->subject->discussion_id) {
|
if ($notification->subject && isset($notification->subject->discussion_id)) {
|
||||||
$notification->subject->setRelation('discussion', $discussions->find($notification->subject->discussion_id));
|
$notification->subject->setRelation('discussion', $discussions->find($notification->subject->discussion_id));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,12 +42,12 @@ abstract class AbstractSerializer extends BaseAbstractSerializer
|
||||||
protected static $container;
|
protected static $container;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var callable[]
|
* @var array<string, callable[]>
|
||||||
*/
|
*/
|
||||||
protected static $attributeMutators = [];
|
protected static $attributeMutators = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array
|
* @var array<string, array<string, callable>>
|
||||||
*/
|
*/
|
||||||
protected static $customRelations = [];
|
protected static $customRelations = [];
|
||||||
|
|
||||||
|
@ -189,12 +189,12 @@ abstract class AbstractSerializer extends BaseAbstractSerializer
|
||||||
* @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer
|
* @param string|Closure|\Tobscure\JsonApi\SerializerInterface $serializer
|
||||||
* @param string|null $relation
|
* @param string|null $relation
|
||||||
* @param bool $many
|
* @param bool $many
|
||||||
* @return Relationship
|
* @return Relationship|null
|
||||||
*/
|
*/
|
||||||
protected function buildRelationship($model, $serializer, $relation = null, $many = false)
|
protected function buildRelationship($model, $serializer, $relation = null, $many = false)
|
||||||
{
|
{
|
||||||
if (is_null($relation)) {
|
if (is_null($relation)) {
|
||||||
list(, , $caller) = debug_backtrace(false, 3);
|
list(, , $caller) = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 3);
|
||||||
|
|
||||||
$relation = $caller['function'];
|
$relation = $caller['function'];
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,8 @@ abstract class AbstractSerializer extends BaseAbstractSerializer
|
||||||
|
|
||||||
return new Relationship($element);
|
return new Relationship($element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,7 +12,8 @@ namespace Flarum\Api\Serializer;
|
||||||
class ExtensionReadmeSerializer extends AbstractSerializer
|
class ExtensionReadmeSerializer extends AbstractSerializer
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* @param \Flarum\Extension\Extension $extension
|
||||||
|
* @return array
|
||||||
*/
|
*/
|
||||||
protected function getDefaultAttributes($extension)
|
protected function getDefaultAttributes($extension)
|
||||||
{
|
{
|
||||||
|
|
|
@ -62,7 +62,7 @@ class ForumSerializer extends AbstractSerializer
|
||||||
*/
|
*/
|
||||||
public function getId($model)
|
public function getId($model)
|
||||||
{
|
{
|
||||||
return 1;
|
return '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -18,17 +18,20 @@ class Schedule extends LaravelSchedule
|
||||||
public function dueEvents($container)
|
public function dueEvents($container)
|
||||||
{
|
{
|
||||||
return (new Collection($this->events))->filter->isDue(new class($container) {
|
return (new Collection($this->events))->filter->isDue(new class($container) {
|
||||||
|
/** @var Config */
|
||||||
|
protected $config;
|
||||||
|
|
||||||
public function __construct($container)
|
public function __construct($container)
|
||||||
{
|
{
|
||||||
$this->config = $container->make(Config::class);
|
$this->config = $container->make(Config::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isDownForMaintenance()
|
public function isDownForMaintenance(): bool
|
||||||
{
|
{
|
||||||
return $this->config->inMaintenanceMode();
|
return $this->config->inMaintenanceMode();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function environment()
|
public function environment(): string
|
||||||
{
|
{
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,8 @@ use LogicException;
|
||||||
* Adds the ability for custom relations to be added to a model during runtime.
|
* Adds the ability for custom relations to be added to a model during runtime.
|
||||||
* These relations behave in the same way that you would expect; they can be
|
* These relations behave in the same way that you would expect; they can be
|
||||||
* queried, eager loaded, and accessed as an attribute.
|
* queried, eager loaded, and accessed as an attribute.
|
||||||
|
*
|
||||||
|
* @property-read int|null $id
|
||||||
*/
|
*/
|
||||||
abstract class AbstractModel extends Eloquent
|
abstract class AbstractModel extends Eloquent
|
||||||
{
|
{
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Flarum\Database\Console;
|
||||||
use Flarum\Console\AbstractCommand;
|
use Flarum\Console\AbstractCommand;
|
||||||
use Flarum\Foundation\Paths;
|
use Flarum\Foundation\Paths;
|
||||||
use Illuminate\Database\Connection;
|
use Illuminate\Database\Connection;
|
||||||
|
use Illuminate\Database\MySqlConnection;
|
||||||
|
|
||||||
class GenerateDumpCommand extends AbstractCommand
|
class GenerateDumpCommand extends AbstractCommand
|
||||||
{
|
{
|
||||||
|
@ -53,7 +54,7 @@ class GenerateDumpCommand extends AbstractCommand
|
||||||
protected function fire()
|
protected function fire()
|
||||||
{
|
{
|
||||||
$dumpPath = __DIR__.'/../../../migrations/install.dump';
|
$dumpPath = __DIR__.'/../../../migrations/install.dump';
|
||||||
/** @var Connection */
|
/** @var Connection&MySqlConnection */
|
||||||
$connection = resolve('db.connection');
|
$connection = resolve('db.connection');
|
||||||
|
|
||||||
$connection
|
$connection
|
||||||
|
|
|
@ -30,8 +30,8 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface
|
||||||
/**
|
/**
|
||||||
* Create a new database migration repository instance.
|
* Create a new database migration repository instance.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\ConnectionInterface $connection
|
* @param ConnectionInterface $connection
|
||||||
* @param string $table
|
* @param string $table
|
||||||
*/
|
*/
|
||||||
public function __construct(ConnectionInterface $connection, $table)
|
public function __construct(ConnectionInterface $connection, $table)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
namespace Flarum\Database;
|
namespace Flarum\Database;
|
||||||
|
|
||||||
use Flarum\Foundation\AbstractServiceProvider;
|
use Flarum\Foundation\AbstractServiceProvider;
|
||||||
|
use Illuminate\Container\Container as ContainerImplementation;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Illuminate\Database\Capsule\Manager;
|
use Illuminate\Database\Capsule\Manager;
|
||||||
use Illuminate\Database\ConnectionInterface;
|
use Illuminate\Database\ConnectionInterface;
|
||||||
|
@ -22,7 +23,7 @@ class DatabaseServiceProvider extends AbstractServiceProvider
|
||||||
*/
|
*/
|
||||||
public function register()
|
public function register()
|
||||||
{
|
{
|
||||||
$this->container->singleton(Manager::class, function (Container $container) {
|
$this->container->singleton(Manager::class, function (ContainerImplementation $container) {
|
||||||
$manager = new Manager($container);
|
$manager = new Manager($container);
|
||||||
|
|
||||||
$config = $container['flarum']->config('database');
|
$config = $container['flarum']->config('database');
|
||||||
|
|
|
@ -39,20 +39,17 @@ class Migrator
|
||||||
/**
|
/**
|
||||||
* The output interface implementation.
|
* The output interface implementation.
|
||||||
*
|
*
|
||||||
* @var OutputInterface
|
* @var OutputInterface|null
|
||||||
*/
|
*/
|
||||||
protected $output;
|
protected $output;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var ConnectionInterface|MySqlConnection
|
* @var ConnectionInterface
|
||||||
*/
|
*/
|
||||||
protected $connection;
|
protected $connection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new migrator instance.
|
* Create a new migrator instance.
|
||||||
*
|
|
||||||
* @param MigrationRepositoryInterface $repository
|
|
||||||
* @param ConnectionInterface $connection
|
|
||||||
* @param Filesystem $files
|
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
MigrationRepositoryInterface $repository,
|
MigrationRepositoryInterface $repository,
|
||||||
|
@ -76,7 +73,7 @@ class Migrator
|
||||||
* Run the outstanding migrations at a given path.
|
* Run the outstanding migrations at a given path.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param Extension $extension
|
* @param Extension|null $extension
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function run($path, Extension $extension = null)
|
public function run($path, Extension $extension = null)
|
||||||
|
@ -95,7 +92,7 @@ class Migrator
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param array $migrations
|
* @param array $migrations
|
||||||
* @param Extension $extension
|
* @param Extension|null $extension
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function runMigrationList($path, $migrations, Extension $extension = null)
|
public function runMigrationList($path, $migrations, Extension $extension = null)
|
||||||
|
@ -122,8 +119,7 @@ class Migrator
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param string $file
|
* @param string $file
|
||||||
* @param string $path
|
* @param Extension|null $extension
|
||||||
* @param Extension $extension
|
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
protected function runUp($path, $file, Extension $extension = null)
|
protected function runUp($path, $file, Extension $extension = null)
|
||||||
|
@ -144,7 +140,7 @@ class Migrator
|
||||||
* Rolls all of the currently applied migrations back.
|
* Rolls all of the currently applied migrations back.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string $path
|
||||||
* @param Extension $extension
|
* @param Extension|null $extension
|
||||||
* @return int
|
* @return int
|
||||||
*/
|
*/
|
||||||
public function reset($path, Extension $extension = null)
|
public function reset($path, Extension $extension = null)
|
||||||
|
@ -245,6 +241,8 @@ class Migrator
|
||||||
if ($this->files->exists($migration)) {
|
if ($this->files->exists($migration)) {
|
||||||
return $this->files->getRequire($migration);
|
return $this->files->getRequire($migration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,7 +13,6 @@ use Flarum\Discussion\Discussion;
|
||||||
use Flarum\Settings\SettingsRepositoryInterface;
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
use Flarum\User\Access\AbstractPolicy;
|
use Flarum\User\Access\AbstractPolicy;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
use Illuminate\Contracts\Events\Dispatcher;
|
|
||||||
|
|
||||||
class DiscussionPolicy extends AbstractPolicy
|
class DiscussionPolicy extends AbstractPolicy
|
||||||
{
|
{
|
||||||
|
@ -22,10 +21,6 @@ class DiscussionPolicy extends AbstractPolicy
|
||||||
*/
|
*/
|
||||||
protected $settings;
|
protected $settings;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param SettingsRepositoryInterface $settings
|
|
||||||
* @param Dispatcher $events
|
|
||||||
*/
|
|
||||||
public function __construct(SettingsRepositoryInterface $settings)
|
public function __construct(SettingsRepositoryInterface $settings)
|
||||||
{
|
{
|
||||||
$this->settings = $settings;
|
$this->settings = $settings;
|
||||||
|
@ -34,7 +29,7 @@ class DiscussionPolicy extends AbstractPolicy
|
||||||
/**
|
/**
|
||||||
* @param User $actor
|
* @param User $actor
|
||||||
* @param string $ability
|
* @param string $ability
|
||||||
* @return bool|null
|
* @return string|void
|
||||||
*/
|
*/
|
||||||
public function can(User $actor, $ability)
|
public function can(User $actor, $ability)
|
||||||
{
|
{
|
||||||
|
|
|
@ -23,6 +23,7 @@ use Flarum\Post\MergeableInterface;
|
||||||
use Flarum\Post\Post;
|
use Flarum\Post\Post;
|
||||||
use Flarum\Settings\SettingsRepositoryInterface;
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -83,7 +84,7 @@ class Discussion extends AbstractModel
|
||||||
/**
|
/**
|
||||||
* The user for which the state relationship should be loaded.
|
* The user for which the state relationship should be loaded.
|
||||||
*
|
*
|
||||||
* @var User
|
* @var User|null
|
||||||
*/
|
*/
|
||||||
protected static $stateUser;
|
protected static $stateUser;
|
||||||
|
|
||||||
|
@ -224,8 +225,8 @@ class Discussion extends AbstractModel
|
||||||
*/
|
*/
|
||||||
public function refreshLastPost()
|
public function refreshLastPost()
|
||||||
{
|
{
|
||||||
/** @var Post $lastPost */
|
|
||||||
if ($lastPost = $this->comments()->latest()->first()) {
|
if ($lastPost = $this->comments()->latest()->first()) {
|
||||||
|
/** @var Post $lastPost */
|
||||||
$this->setLastPost($lastPost);
|
$this->setLastPost($lastPost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,8 +265,9 @@ class Discussion extends AbstractModel
|
||||||
* DiscussionRenamedPost, and delete if the title has been reverted
|
* DiscussionRenamedPost, and delete if the title has been reverted
|
||||||
* completely.)
|
* completely.)
|
||||||
*
|
*
|
||||||
* @param \Flarum\Post\MergeableInterface $post The post to save.
|
* @template T of \Flarum\Post\MergeableInterface
|
||||||
* @return Post The resulting post. It may or may not be the same post as
|
* @param T $post The post to save.
|
||||||
|
* @return T The resulting post. It may or may not be the same post as
|
||||||
* was originally intended to be saved. It also may not exist, if the
|
* was originally intended to be saved. It also may not exist, if the
|
||||||
* merge logic resulted in deletion.
|
* merge logic resulted in deletion.
|
||||||
*/
|
*/
|
||||||
|
@ -301,7 +303,7 @@ class Discussion extends AbstractModel
|
||||||
/**
|
/**
|
||||||
* Define the relationship with the discussion's publicly-visible comments.
|
* Define the relationship with the discussion's publicly-visible comments.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany<Post>
|
||||||
*/
|
*/
|
||||||
public function comments()
|
public function comments()
|
||||||
{
|
{
|
||||||
|
@ -394,12 +396,12 @@ class Discussion extends AbstractModel
|
||||||
* If no user is passed (i.e. in the case of eager loading the 'state'
|
* If no user is passed (i.e. in the case of eager loading the 'state'
|
||||||
* relation), then the static `$stateUser` property is used.
|
* relation), then the static `$stateUser` property is used.
|
||||||
*
|
*
|
||||||
* @see Discussion::setStateUser()
|
|
||||||
*
|
|
||||||
* @param User|null $user
|
* @param User|null $user
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne
|
* @return HasOne
|
||||||
|
*
|
||||||
|
* @see Discussion::setStateUser()
|
||||||
*/
|
*/
|
||||||
public function state(User $user = null)
|
public function state(User $user = null): HasOne
|
||||||
{
|
{
|
||||||
$user = $user ?: static::$stateUser;
|
$user = $user ?: static::$stateUser;
|
||||||
|
|
||||||
|
@ -409,12 +411,10 @@ class Discussion extends AbstractModel
|
||||||
/**
|
/**
|
||||||
* Get the state model for a user, or instantiate a new one if it does not
|
* Get the state model for a user, or instantiate a new one if it does not
|
||||||
* exist.
|
* exist.
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
* @return \Flarum\Discussion\UserState
|
|
||||||
*/
|
*/
|
||||||
public function stateFor(User $user)
|
public function stateFor(User $user): UserState
|
||||||
{
|
{
|
||||||
|
/** @var UserState|null $state */
|
||||||
$state = $this->state($user)->first();
|
$state = $this->state($user)->first();
|
||||||
|
|
||||||
if (! $state) {
|
if (! $state) {
|
||||||
|
@ -428,8 +428,6 @@ class Discussion extends AbstractModel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the user for which the state relationship should be loaded.
|
* Set the user for which the state relationship should be loaded.
|
||||||
*
|
|
||||||
* @param User $user
|
|
||||||
*/
|
*/
|
||||||
public static function setStateUser(User $user)
|
public static function setStateUser(User $user)
|
||||||
{
|
{
|
||||||
|
@ -440,11 +438,8 @@ class Discussion extends AbstractModel
|
||||||
* Set the discussion title.
|
* Set the discussion title.
|
||||||
*
|
*
|
||||||
* This automatically creates a matching slug for the discussion.
|
* This automatically creates a matching slug for the discussion.
|
||||||
*
|
|
||||||
* @todo slug should be set by the slugger, drop slug column entirely?
|
|
||||||
* @param string $title
|
|
||||||
*/
|
*/
|
||||||
protected function setTitleAttribute($title)
|
protected function setTitleAttribute(string $title)
|
||||||
{
|
{
|
||||||
$this->attributes['title'] = $title;
|
$this->attributes['title'] = $title;
|
||||||
$this->slug = Str::slug(
|
$this->slug = Str::slug(
|
||||||
|
|
|
@ -17,7 +17,7 @@ class DiscussionRepository
|
||||||
/**
|
/**
|
||||||
* Get a new query builder for the discussions table.
|
* Get a new query builder for the discussions table.
|
||||||
*
|
*
|
||||||
* @return Builder
|
* @return Builder<Discussion>
|
||||||
*/
|
*/
|
||||||
public function query()
|
public function query()
|
||||||
{
|
{
|
||||||
|
@ -28,13 +28,13 @@ class DiscussionRepository
|
||||||
* Find a discussion by ID, optionally making sure it is visible to a
|
* Find a discussion by ID, optionally making sure it is visible to a
|
||||||
* certain user, or throw an exception.
|
* certain user, or throw an exception.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int|string $id
|
||||||
* @param User $user
|
* @param User|null $user
|
||||||
* @return \Flarum\Discussion\Discussion
|
* @return \Flarum\Discussion\Discussion
|
||||||
*/
|
*/
|
||||||
public function findOrFail($id, User $user = null)
|
public function findOrFail($id, User $user = null)
|
||||||
{
|
{
|
||||||
$query = Discussion::where('id', $id);
|
$query = $this->query()->where('id', $id);
|
||||||
|
|
||||||
return $this->scopeVisibleTo($query, $user)->firstOrFail();
|
return $this->scopeVisibleTo($query, $user)->firstOrFail();
|
||||||
}
|
}
|
||||||
|
@ -42,26 +42,25 @@ class DiscussionRepository
|
||||||
/**
|
/**
|
||||||
* Get the IDs of discussions which a user has read completely.
|
* Get the IDs of discussions which a user has read completely.
|
||||||
*
|
*
|
||||||
* @deprecated 1.3 Use `getReadIdsQuery` instead
|
|
||||||
*
|
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @return array
|
* @return \Illuminate\Database\Eloquent\Collection<Discussion>
|
||||||
|
* @deprecated 1.3 Use `getReadIdsQuery` instead
|
||||||
*/
|
*/
|
||||||
public function getReadIds(User $user)
|
public function getReadIds(User $user)
|
||||||
{
|
{
|
||||||
return $this->getReadIdsQuery($user)
|
return $this->getReadIdsQuery($user)->get();
|
||||||
->all();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a query containing the IDs of discussions which a user has read completely.
|
* Get a query containing the IDs of discussions which a user has read completely.
|
||||||
*
|
*
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @return Builder
|
* @return Builder<Discussion>
|
||||||
*/
|
*/
|
||||||
public function getReadIdsQuery(User $user): Builder
|
public function getReadIdsQuery(User $user): Builder
|
||||||
{
|
{
|
||||||
return Discussion::leftJoin('discussion_user', 'discussion_user.discussion_id', '=', 'discussions.id')
|
return $this->query()
|
||||||
|
->leftJoin('discussion_user', 'discussion_user.discussion_id', '=', 'discussions.id')
|
||||||
->where('discussion_user.user_id', $user->id)
|
->where('discussion_user.user_id', $user->id)
|
||||||
->whereColumn('last_read_post_number', '>=', 'last_post_number')
|
->whereColumn('last_read_post_number', '>=', 'last_post_number')
|
||||||
->select('id');
|
->select('id');
|
||||||
|
@ -70,9 +69,9 @@ class DiscussionRepository
|
||||||
/**
|
/**
|
||||||
* Scope a query to only include records that are visible to a user.
|
* Scope a query to only include records that are visible to a user.
|
||||||
*
|
*
|
||||||
* @param Builder $query
|
* @param Builder<Discussion> $query
|
||||||
* @param User $user
|
* @param User|null $user
|
||||||
* @return Builder
|
* @return Builder<Discussion>
|
||||||
*/
|
*/
|
||||||
protected function scopeVisibleTo(Builder $query, User $user = null)
|
protected function scopeVisibleTo(Builder $query, User $user = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,9 @@ use Flarum\Database\AbstractModel;
|
||||||
use Flarum\Http\SlugDriverInterface;
|
use Flarum\Http\SlugDriverInterface;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements SlugDriverInterface<Discussion>
|
||||||
|
*/
|
||||||
class IdWithTransliteratedSlugDriver implements SlugDriverInterface
|
class IdWithTransliteratedSlugDriver implements SlugDriverInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +28,9 @@ class IdWithTransliteratedSlugDriver implements SlugDriverInterface
|
||||||
$this->discussions = $discussions;
|
$this->discussions = $discussions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Discussion $instance
|
||||||
|
*/
|
||||||
public function toSlug(AbstractModel $instance): string
|
public function toSlug(AbstractModel $instance): string
|
||||||
{
|
{
|
||||||
return $instance->id.(trim($instance->slug) ? '-'.$instance->slug : '');
|
return $instance->id.(trim($instance->slug) ? '-'.$instance->slug : '');
|
||||||
|
|
|
@ -65,5 +65,7 @@ class FulltextGambit implements GambitInterface
|
||||||
$query->orderByRaw('MATCH('.$grammar->wrap('discussions.title').') AGAINST (?) desc', [$bit]);
|
$query->orderByRaw('MATCH('.$grammar->wrap('discussions.title').') AGAINST (?) desc', [$bit]);
|
||||||
$query->orderBy('posts_ft.score', 'desc');
|
$query->orderBy('posts_ft.score', 'desc');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,9 @@ use Flarum\Database\AbstractModel;
|
||||||
use Flarum\Http\SlugDriverInterface;
|
use Flarum\Http\SlugDriverInterface;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements SlugDriverInterface<Discussion>
|
||||||
|
*/
|
||||||
class Utf8SlugDriver implements SlugDriverInterface
|
class Utf8SlugDriver implements SlugDriverInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +28,10 @@ class Utf8SlugDriver implements SlugDriverInterface
|
||||||
$this->discussions = $discussions;
|
$this->discussions = $discussions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Discussion $instance
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
public function toSlug(AbstractModel $instance): string
|
public function toSlug(AbstractModel $instance): string
|
||||||
{
|
{
|
||||||
$slug = preg_replace('/[-\s]+/u', '-', $instance->title);
|
$slug = preg_replace('/[-\s]+/u', '-', $instance->title);
|
||||||
|
@ -34,6 +41,11 @@ class Utf8SlugDriver implements SlugDriverInterface
|
||||||
return $instance->id.(trim($slug) ? '-'.$slug : '');
|
return $instance->id.(trim($slug) ? '-'.$slug : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $slug
|
||||||
|
* @param User $actor
|
||||||
|
* @return Discussion
|
||||||
|
*/
|
||||||
public function fromSlug(string $slug, User $actor): AbstractModel
|
public function fromSlug(string $slug, User $actor): AbstractModel
|
||||||
{
|
{
|
||||||
if (strpos($slug, '-')) {
|
if (strpos($slug, '-')) {
|
||||||
|
|
|
@ -76,7 +76,7 @@ class ErrorHandling implements ExtenderInterface
|
||||||
* contain "details" - arbitrary data with more context for to the error.
|
* contain "details" - arbitrary data with more context for to the error.
|
||||||
*
|
*
|
||||||
* @param string $exceptionClass: The ::class attribute of the exception class.
|
* @param string $exceptionClass: The ::class attribute of the exception class.
|
||||||
* @param string $errorType: The ::class attribute of the handler class.
|
* @param string $handlerClass: The ::class attribute of the handler class.
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
public function handler(string $exceptionClass, string $handlerClass): self
|
public function handler(string $exceptionClass, string $handlerClass): self
|
||||||
|
|
|
@ -110,7 +110,7 @@ class Frontend implements ExtenderInterface
|
||||||
/**
|
/**
|
||||||
* Modify the content of the frontend.
|
* Modify the content of the frontend.
|
||||||
*
|
*
|
||||||
* @param callable|string|null $content
|
* @param callable|string|null $callback
|
||||||
*
|
*
|
||||||
* The content can be a closure or an invokable class, and should accept:
|
* The content can be a closure or an invokable class, and should accept:
|
||||||
* - \Flarum\Frontend\Document $document
|
* - \Flarum\Frontend\Document $document
|
||||||
|
|
|
@ -31,7 +31,7 @@ class LanguagePack implements ExtenderInterface, LifecycleInterface
|
||||||
/**
|
/**
|
||||||
* LanguagePack constructor.
|
* LanguagePack constructor.
|
||||||
*
|
*
|
||||||
* @param string|null $path: Path to yaml language files.
|
* @param string $path: Path to yaml language files.
|
||||||
*/
|
*/
|
||||||
public function __construct(string $path = '/locale')
|
public function __construct(string $path = '/locale')
|
||||||
{
|
{
|
||||||
|
@ -115,7 +115,7 @@ class LanguagePack implements ExtenderInterface, LifecycleInterface
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @var ExtensionManager $extensions */
|
/** @var ExtensionManager|null $extensions */
|
||||||
static $extensions;
|
static $extensions;
|
||||||
$extensions = $extensions ?? $container->make(ExtensionManager::class);
|
$extensions = $extensions ?? $container->make(ExtensionManager::class);
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ class Middleware implements ExtenderInterface
|
||||||
*
|
*
|
||||||
* @param string $originalMiddleware: ::class attribute of the original middleware class.
|
* @param string $originalMiddleware: ::class attribute of the original middleware class.
|
||||||
* Or container binding name.
|
* Or container binding name.
|
||||||
* @param string $middleware: ::class attribute of the middleware class.
|
* @param string $newMiddleware: ::class attribute of the middleware class.
|
||||||
* Must implement \Psr\Http\Server\MiddlewareInterface.
|
* Must implement \Psr\Http\Server\MiddlewareInterface.
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
|
@ -77,7 +77,7 @@ class Middleware implements ExtenderInterface
|
||||||
*
|
*
|
||||||
* @param string $originalMiddleware: ::class attribute of the original middleware class.
|
* @param string $originalMiddleware: ::class attribute of the original middleware class.
|
||||||
* Or container binding name.
|
* Or container binding name.
|
||||||
* @param string $middleware: ::class attribute of the middleware class.
|
* @param string $newMiddleware: ::class attribute of the middleware class.
|
||||||
* Must implement \Psr\Http\Server\MiddlewareInterface.
|
* Must implement \Psr\Http\Server\MiddlewareInterface.
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
|
@ -93,7 +93,7 @@ class Middleware implements ExtenderInterface
|
||||||
*
|
*
|
||||||
* @param string $originalMiddleware: ::class attribute of the original middleware class.
|
* @param string $originalMiddleware: ::class attribute of the original middleware class.
|
||||||
* Or container binding name.
|
* Or container binding name.
|
||||||
* @param string $middleware: ::class attribute of the middleware class.
|
* @param string $newMiddleware: ::class attribute of the middleware class.
|
||||||
* Must implement \Psr\Http\Server\MiddlewareInterface.
|
* Must implement \Psr\Http\Server\MiddlewareInterface.
|
||||||
* @return self
|
* @return self
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Flarum\Extension\Extension;
|
||||||
use Flarum\Foundation\Paths;
|
use Flarum\Foundation\Paths;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Illuminate\Contracts\View\Factory;
|
use Illuminate\Contracts\View\Factory;
|
||||||
|
use Illuminate\View\Factory as FactoryImplementation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Views are PHP files that use the Laravel Blade syntax for creation of server-side generated HTML.
|
* Views are PHP files that use the Laravel Blade syntax for creation of server-side generated HTML.
|
||||||
|
@ -65,7 +66,7 @@ class View implements ExtenderInterface, LifecycleInterface
|
||||||
|
|
||||||
public function extend(Container $container, Extension $extension = null)
|
public function extend(Container $container, Extension $extension = null)
|
||||||
{
|
{
|
||||||
$container->resolving(Factory::class, function (Factory $view) {
|
$container->resolving(Factory::class, function (FactoryImplementation $view) {
|
||||||
foreach ($this->namespaces as $namespace => $hints) {
|
foreach ($this->namespaces as $namespace => $hints) {
|
||||||
$view->addNamespace($namespace, $hints);
|
$view->addNamespace($namespace, $hints);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,6 @@ class ExtensionBootError extends Exception
|
||||||
|
|
||||||
$extenderClass = get_class($extender);
|
$extenderClass = get_class($extender);
|
||||||
|
|
||||||
parent::__construct("Experienced an error while booting extension: {$extension->getTitle()}.\n\nError occurred while applying an extender of type: $extenderClass.", null, $previous);
|
parent::__construct("Experienced an error while booting extension: {$extension->getTitle()}.\n\nError occurred while applying an extender of type: $extenderClass.", 0, $previous);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,9 +214,6 @@ class Extension implements Arrayable
|
||||||
* @param array $extensionSet: An associative array where keys are the composer package names
|
* @param array $extensionSet: An associative array where keys are the composer package names
|
||||||
* of installed extensions. Used to figure out which dependencies
|
* of installed extensions. Used to figure out which dependencies
|
||||||
* are flarum extensions.
|
* are flarum extensions.
|
||||||
* @param array $enabledIds: An associative array where keys are the composer package names
|
|
||||||
* of enabled extensions. Used to figure out optional dependencies.
|
|
||||||
*
|
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function calculateDependencies($extensionSet)
|
public function calculateDependencies($extensionSet)
|
||||||
|
@ -489,6 +486,7 @@ class Extension implements Arrayable
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @return int|void
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function migrate(Migrator $migrator, $direction = 'up')
|
public function migrate(Migrator $migrator, $direction = 'up')
|
||||||
|
@ -498,7 +496,7 @@ class Extension implements Arrayable
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($direction == 'up') {
|
if ($direction == 'up') {
|
||||||
return $migrator->run($this->getPath().'/migrations', $this);
|
$migrator->run($this->getPath().'/migrations', $this);
|
||||||
} else {
|
} else {
|
||||||
return $migrator->reset($this->getPath().'/migrations', $this);
|
return $migrator->reset($this->getPath().'/migrations', $this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -316,7 +316,7 @@ class ExtensionManager
|
||||||
*
|
*
|
||||||
* @param Extension $extension
|
* @param Extension $extension
|
||||||
* @param string $direction
|
* @param string $direction
|
||||||
* @return void
|
* @return int
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
@ -326,20 +326,20 @@ class ExtensionManager
|
||||||
return $container->make(ConnectionInterface::class)->getSchemaBuilder();
|
return $container->make(ConnectionInterface::class)->getSchemaBuilder();
|
||||||
});
|
});
|
||||||
|
|
||||||
$extension->migrate($this->migrator, $direction);
|
return $extension->migrate($this->migrator, $direction);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs the database migrations to reset the database to its old state.
|
* Runs the database migrations to reset the database to its old state.
|
||||||
*
|
*
|
||||||
* @param Extension $extension
|
* @param Extension $extension
|
||||||
* @return array Notes from the migrator.
|
* @return void
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
public function migrateDown(Extension $extension)
|
public function migrateDown(Extension $extension)
|
||||||
{
|
{
|
||||||
return $this->migrate($extension, 'down');
|
$this->migrate($extension, 'down');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -39,7 +39,7 @@ abstract class AbstractFilterer
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param QueryCriteria $criteria
|
* @param QueryCriteria $criteria
|
||||||
* @param mixed|null $limit
|
* @param int|null $limit
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
*
|
*
|
||||||
* @return QueryResults
|
* @return QueryResults
|
||||||
|
|
|
@ -18,9 +18,6 @@ interface FilterInterface
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters a query.
|
* Filters a query.
|
||||||
*
|
|
||||||
* @param FilterState $filter
|
|
||||||
* @param string $value The value of the requested filter
|
|
||||||
*/
|
*/
|
||||||
public function filter(FilterState $filterState, string $filterValue, bool $negate);
|
public function filter(FilterState $filterState, string $filterValue, bool $negate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
namespace Flarum\Formatter;
|
namespace Flarum\Formatter;
|
||||||
|
|
||||||
use DOMDocument;
|
|
||||||
use DOMElement;
|
|
||||||
use Illuminate\Contracts\Cache\Repository;
|
use Illuminate\Contracts\Cache\Repository;
|
||||||
use Psr\Http\Message\ServerRequestInterface;
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
use s9e\TextFormatter\Configurator;
|
use s9e\TextFormatter\Configurator;
|
||||||
|
@ -152,8 +150,8 @@ class Formatter
|
||||||
|
|
||||||
$configurator->rootRules->enableAutoLineBreaks();
|
$configurator->rootRules->enableAutoLineBreaks();
|
||||||
|
|
||||||
$configurator->rendering->engine = 'PHP';
|
$configurator->rendering->setEngine('PHP');
|
||||||
$configurator->rendering->engine->cacheDir = $this->cacheDir;
|
$configurator->rendering->getEngine()->cacheDir = $this->cacheDir; // @phpstan-ignore-line
|
||||||
|
|
||||||
$configurator->enableJavaScript();
|
$configurator->enableJavaScript();
|
||||||
$configurator->javascript->exports = ['preview'];
|
$configurator->javascript->exports = ['preview'];
|
||||||
|
@ -161,9 +159,9 @@ class Formatter
|
||||||
$configurator->javascript->setMinifier('MatthiasMullieMinify')
|
$configurator->javascript->setMinifier('MatthiasMullieMinify')
|
||||||
->keepGoing = true;
|
->keepGoing = true;
|
||||||
|
|
||||||
$configurator->Escaper;
|
$configurator->Escaper; /** @phpstan-ignore-line */
|
||||||
$configurator->Autoemail;
|
$configurator->Autoemail; /** @phpstan-ignore-line */
|
||||||
$configurator->Autolink;
|
$configurator->Autolink; /** @phpstan-ignore-line */
|
||||||
$configurator->tags->onDuplicate('replace');
|
$configurator->tags->onDuplicate('replace');
|
||||||
|
|
||||||
foreach ($this->configurationCallbacks as $callback) {
|
foreach ($this->configurationCallbacks as $callback) {
|
||||||
|
@ -180,11 +178,13 @@ class Formatter
|
||||||
*/
|
*/
|
||||||
protected function configureExternalLinks(Configurator $configurator)
|
protected function configureExternalLinks(Configurator $configurator)
|
||||||
{
|
{
|
||||||
/** @var DOMDocument $dom */
|
/**
|
||||||
|
* @var Configurator\Items\TemplateDocument $dom
|
||||||
|
*/
|
||||||
$dom = $configurator->tags['URL']->template->asDOM();
|
$dom = $configurator->tags['URL']->template->asDOM();
|
||||||
|
|
||||||
/** @var DOMElement $a */
|
|
||||||
foreach ($dom->getElementsByTagName('a') as $a) {
|
foreach ($dom->getElementsByTagName('a') as $a) {
|
||||||
|
/** @var \s9e\SweetDOM\Element $a */
|
||||||
$a->prependXslCopyOf('@target');
|
$a->prependXslCopyOf('@target');
|
||||||
$a->prependXslCopyOf('@rel');
|
$a->prependXslCopyOf('@rel');
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,10 +140,10 @@ class Application
|
||||||
* Use container inside flarum instead.
|
* Use container inside flarum instead.
|
||||||
*/
|
*/
|
||||||
$this->container->instance('app', $this->container);
|
$this->container->instance('app', $this->container);
|
||||||
$this->container->alias('app', \Illluminate\Container\Container::class);
|
$this->container->alias('app', \Illuminate\Container\Container::class);
|
||||||
|
|
||||||
$this->container->instance('container', $this->container);
|
$this->container->instance('container', $this->container);
|
||||||
$this->container->alias('container', \Illluminate\Container\Container::class);
|
$this->container->alias('container', \Illuminate\Container\Container::class);
|
||||||
|
|
||||||
$this->container->instance('flarum', $this);
|
$this->container->instance('flarum', $this);
|
||||||
$this->container->alias('flarum', self::class);
|
$this->container->alias('flarum', self::class);
|
||||||
|
@ -170,7 +170,7 @@ class Application
|
||||||
*/
|
*/
|
||||||
public function register($provider, $options = [], $force = false)
|
public function register($provider, $options = [], $force = false)
|
||||||
{
|
{
|
||||||
if ($registered = $this->getProvider($provider) && ! $force) {
|
if (($registered = $this->getProvider($provider)) && ! $force) {
|
||||||
return $registered;
|
return $registered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ class InfoCommand extends AbstractCommand
|
||||||
* @var ConnectionInterface
|
* @var ConnectionInterface
|
||||||
*/
|
*/
|
||||||
protected $db;
|
protected $db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Queue
|
* @var Queue
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -104,7 +104,7 @@ class InstalledSite implements SiteInterface
|
||||||
$container->instance('flarum.config', $this->config);
|
$container->instance('flarum.config', $this->config);
|
||||||
$container->alias('flarum.config', Config::class);
|
$container->alias('flarum.config', Config::class);
|
||||||
$container->instance('flarum.debug', $this->config->inDebugMode());
|
$container->instance('flarum.debug', $this->config->inDebugMode());
|
||||||
$container->instance('config', $config = $this->getIlluminateConfig($laravel));
|
$container->instance('config', $config = $this->getIlluminateConfig());
|
||||||
$container->instance('flarum.maintenance.handler', new MaintenanceModeHandler);
|
$container->instance('flarum.maintenance.handler', new MaintenanceModeHandler);
|
||||||
|
|
||||||
$this->registerLogger($container);
|
$this->registerLogger($container);
|
||||||
|
|
|
@ -12,10 +12,10 @@ namespace Flarum\Foundation;
|
||||||
use InvalidArgumentException;
|
use InvalidArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property-read string base
|
* @property-read string $base
|
||||||
* @property-read string public
|
* @property-read string $public
|
||||||
* @property-read string storage
|
* @property-read string $storage
|
||||||
* @property-read string vendor
|
* @property-read string $vendor
|
||||||
*/
|
*/
|
||||||
class Paths
|
class Paths
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,7 @@ use Flarum\Frontend\Compiler\CompilerInterface;
|
||||||
use Flarum\Frontend\Compiler\JsCompiler;
|
use Flarum\Frontend\Compiler\JsCompiler;
|
||||||
use Flarum\Frontend\Compiler\LessCompiler;
|
use Flarum\Frontend\Compiler\LessCompiler;
|
||||||
use Flarum\Frontend\Compiler\Source\SourceCollector;
|
use Flarum\Frontend\Compiler\Source\SourceCollector;
|
||||||
use Illuminate\Contracts\Filesystem\Filesystem;
|
use Illuminate\Contracts\Filesystem\Cloud;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A factory class for creating frontend asset compilers.
|
* A factory class for creating frontend asset compilers.
|
||||||
|
@ -38,7 +38,7 @@ class Assets
|
||||||
protected $name;
|
protected $name;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Filesystem
|
* @var Cloud
|
||||||
*/
|
*/
|
||||||
protected $assetsDir;
|
protected $assetsDir;
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ class Assets
|
||||||
*/
|
*/
|
||||||
protected $customFunctions = [];
|
protected $customFunctions = [];
|
||||||
|
|
||||||
public function __construct(string $name, Filesystem $assetsDir, string $cacheDir = null, array $lessImportDirs = null, array $customFunctions = [])
|
public function __construct(string $name, Cloud $assetsDir, string $cacheDir = null, array $lessImportDirs = null, array $customFunctions = [])
|
||||||
{
|
{
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
$this->assetsDir = $assetsDir;
|
$this->assetsDir = $assetsDir;
|
||||||
|
@ -200,12 +200,12 @@ class Assets
|
||||||
$this->name = $name;
|
$this->name = $name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAssetsDir(): Filesystem
|
public function getAssetsDir(): Cloud
|
||||||
{
|
{
|
||||||
return $this->assetsDir;
|
return $this->assetsDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setAssetsDir(Filesystem $assetsDir)
|
public function setAssetsDir(Cloud $assetsDir)
|
||||||
{
|
{
|
||||||
$this->assetsDir = $assetsDir;
|
$this->assetsDir = $assetsDir;
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,8 @@ class FileVersioner implements VersionerInterface
|
||||||
|
|
||||||
public function putRevision(string $file, ?string $revision)
|
public function putRevision(string $file, ?string $revision)
|
||||||
{
|
{
|
||||||
if ($this->filesystem->has(static::REV_MANIFEST)) {
|
if ($this->filesystem->exists(static::REV_MANIFEST)) {
|
||||||
$manifest = json_decode($this->filesystem->read(static::REV_MANIFEST), true);
|
$manifest = json_decode($this->filesystem->get(static::REV_MANIFEST), true);
|
||||||
} else {
|
} else {
|
||||||
$manifest = [];
|
$manifest = [];
|
||||||
}
|
}
|
||||||
|
@ -44,8 +44,8 @@ class FileVersioner implements VersionerInterface
|
||||||
|
|
||||||
public function getRevision(string $file): ?string
|
public function getRevision(string $file): ?string
|
||||||
{
|
{
|
||||||
if ($this->filesystem->has(static::REV_MANIFEST)) {
|
if ($this->filesystem->exists(static::REV_MANIFEST)) {
|
||||||
$manifest = json_decode($this->filesystem->read(static::REV_MANIFEST), true);
|
$manifest = json_decode($this->filesystem->get(static::REV_MANIFEST), true);
|
||||||
|
|
||||||
return Arr::get($manifest, $file);
|
return Arr::get($manifest, $file);
|
||||||
}
|
}
|
||||||
|
|
|
@ -72,7 +72,7 @@ class JsCompiler extends RevisionCompiler
|
||||||
{
|
{
|
||||||
parent::delete($file);
|
parent::delete($file);
|
||||||
|
|
||||||
if ($this->assetsDir->has($mapFile = $file.'.map')) {
|
if ($this->assetsDir->exists($mapFile = $file.'.map')) {
|
||||||
$this->assetsDir->delete($mapFile);
|
$this->assetsDir->delete($mapFile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,12 +35,12 @@ class LessCompiler extends RevisionCompiler
|
||||||
protected $customFunctions = [];
|
protected $customFunctions = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Collection
|
* @var Collection|null
|
||||||
*/
|
*/
|
||||||
protected $lessImportOverrides;
|
protected $lessImportOverrides;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Collection
|
* @var Collection|null
|
||||||
*/
|
*/
|
||||||
protected $fileSourceOverrides;
|
protected $fileSourceOverrides;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ class LessCompiler extends RevisionCompiler
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
ini_set('xdebug.max_nesting_level', 200);
|
ini_set('xdebug.max_nesting_level', '200');
|
||||||
|
|
||||||
$parser = new Less_Parser([
|
$parser = new Less_Parser([
|
||||||
'compress' => true,
|
'compress' => true,
|
||||||
|
|
|
@ -11,7 +11,7 @@ namespace Flarum\Frontend\Compiler;
|
||||||
|
|
||||||
use Flarum\Frontend\Compiler\Source\SourceCollector;
|
use Flarum\Frontend\Compiler\Source\SourceCollector;
|
||||||
use Flarum\Frontend\Compiler\Source\SourceInterface;
|
use Flarum\Frontend\Compiler\Source\SourceInterface;
|
||||||
use Illuminate\Contracts\Filesystem\Filesystem;
|
use Illuminate\Contracts\Filesystem\Cloud;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* @internal
|
||||||
|
@ -21,9 +21,10 @@ class RevisionCompiler implements CompilerInterface
|
||||||
const EMPTY_REVISION = 'empty';
|
const EMPTY_REVISION = 'empty';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Filesystem
|
* @var Cloud
|
||||||
*/
|
*/
|
||||||
protected $assetsDir;
|
protected $assetsDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var VersionerInterface
|
* @var VersionerInterface
|
||||||
*/
|
*/
|
||||||
|
@ -40,11 +41,11 @@ class RevisionCompiler implements CompilerInterface
|
||||||
protected $sourcesCallbacks = [];
|
protected $sourcesCallbacks = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Filesystem $assetsDir
|
* @param Cloud $assetsDir
|
||||||
* @param string $filename
|
* @param string $filename
|
||||||
* @param VersionerInterface|null $versioner @deprecated nullable will be removed at v2.0
|
* @param VersionerInterface|null $versioner @deprecated nullable will be removed at v2.0
|
||||||
*/
|
*/
|
||||||
public function __construct(Filesystem $assetsDir, string $filename, VersionerInterface $versioner = null)
|
public function __construct(Cloud $assetsDir, string $filename, VersionerInterface $versioner = null)
|
||||||
{
|
{
|
||||||
$this->assetsDir = $assetsDir;
|
$this->assetsDir = $assetsDir;
|
||||||
$this->filename = $filename;
|
$this->filename = $filename;
|
||||||
|
@ -71,7 +72,7 @@ class RevisionCompiler implements CompilerInterface
|
||||||
|
|
||||||
// In case the previous and current revisions do not match
|
// In case the previous and current revisions do not match
|
||||||
// Or no file was written yet, let's save the file to disk.
|
// Or no file was written yet, let's save the file to disk.
|
||||||
if ($force || $oldRevision !== $newRevision || ! $this->assetsDir->has($this->filename)) {
|
if ($force || $oldRevision !== $newRevision || ! $this->assetsDir->exists($this->filename)) {
|
||||||
if (! $this->save($this->filename, $sources)) {
|
if (! $this->save($this->filename, $sources)) {
|
||||||
// If no file was written (because the sources were empty), we
|
// If no file was written (because the sources were empty), we
|
||||||
// will set the revision to a special value so that we can tell
|
// will set the revision to a special value so that we can tell
|
||||||
|
@ -145,7 +146,6 @@ class RevisionCompiler implements CompilerInterface
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param SourceInterface[] $sources
|
* @param SourceInterface[] $sources
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
protected function compile(array $sources): string
|
protected function compile(array $sources): string
|
||||||
{
|
{
|
||||||
|
@ -158,10 +158,6 @@ class RevisionCompiler implements CompilerInterface
|
||||||
return $output;
|
return $output;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $string
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
protected function format(string $string): string
|
protected function format(string $string): string
|
||||||
{
|
{
|
||||||
return $string;
|
return $string;
|
||||||
|
@ -169,7 +165,6 @@ class RevisionCompiler implements CompilerInterface
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param SourceInterface[] $sources
|
* @param SourceInterface[] $sources
|
||||||
* @return string
|
|
||||||
*/
|
*/
|
||||||
protected function calculateRevision(array $sources): string
|
protected function calculateRevision(array $sources): string
|
||||||
{
|
{
|
||||||
|
@ -196,12 +191,9 @@ class RevisionCompiler implements CompilerInterface
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $file
|
|
||||||
*/
|
|
||||||
protected function delete(string $file)
|
protected function delete(string $file)
|
||||||
{
|
{
|
||||||
if ($this->assetsDir->has($file)) {
|
if ($this->assetsDir->exists($file)) {
|
||||||
$this->assetsDir->delete($file);
|
$this->assetsDir->delete($file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -221,14 +221,13 @@ class Document implements Renderable
|
||||||
return resolve(TitleDriverInterface::class)->makeTitle($this, $this->request, $this->forumApiDocument);
|
return resolve(TitleDriverInterface::class)->makeTitle($this, $this->request, $this->forumApiDocument);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
protected function makeLayout(): ?View
|
||||||
* @return View
|
|
||||||
*/
|
|
||||||
protected function makeLayout(): View
|
|
||||||
{
|
{
|
||||||
if ($this->layoutView) {
|
if ($this->layoutView) {
|
||||||
return $this->view->make($this->layoutView)->with('content', $this->makeContent());
|
return $this->view->make($this->layoutView)->with('content', $this->makeContent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,7 +17,7 @@ class GroupRepository
|
||||||
/**
|
/**
|
||||||
* Get a new query builder for the groups table.
|
* Get a new query builder for the groups table.
|
||||||
*
|
*
|
||||||
* @return Builder
|
* @return Builder<Group>
|
||||||
*/
|
*/
|
||||||
public function query()
|
public function query()
|
||||||
{
|
{
|
||||||
|
@ -29,14 +29,14 @@ class GroupRepository
|
||||||
* user, or throw an exception.
|
* user, or throw an exception.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @param User $actor
|
* @param User|null $actor
|
||||||
* @return \Flarum\Group\Group
|
* @return Group
|
||||||
*
|
*
|
||||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||||
*/
|
*/
|
||||||
public function findOrFail($id, User $actor = null)
|
public function findOrFail($id, User $actor = null)
|
||||||
{
|
{
|
||||||
$query = Group::where('id', $id);
|
$query = $this->query()->where('id', $id);
|
||||||
|
|
||||||
return $this->scopeVisibleTo($query, $actor)->firstOrFail();
|
return $this->scopeVisibleTo($query, $actor)->firstOrFail();
|
||||||
}
|
}
|
||||||
|
@ -44,9 +44,9 @@ class GroupRepository
|
||||||
/**
|
/**
|
||||||
* Scope a query to only include records that are visible to a user.
|
* Scope a query to only include records that are visible to a user.
|
||||||
*
|
*
|
||||||
* @param Builder $query
|
* @param Builder<Group> $query
|
||||||
* @param User $actor
|
* @param User|null $actor
|
||||||
* @return Builder
|
* @return Builder<Group>
|
||||||
*/
|
*/
|
||||||
protected function scopeVisibleTo(Builder $query, User $actor = null)
|
protected function scopeVisibleTo(Builder $query, User $actor = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -25,8 +25,8 @@ use Psr\Http\Message\ServerRequestInterface;
|
||||||
* @property Carbon|null $last_activity_at
|
* @property Carbon|null $last_activity_at
|
||||||
* @property string $type
|
* @property string $type
|
||||||
* @property string $title
|
* @property string $title
|
||||||
* @property string $last_ip_address
|
* @property string|null $last_ip_address
|
||||||
* @property string $last_user_agent
|
* @property string|null $last_user_agent
|
||||||
* @property \Flarum\User\User|null $user
|
* @property \Flarum\User\User|null $user
|
||||||
*/
|
*/
|
||||||
class AccessToken extends AbstractModel
|
class AccessToken extends AbstractModel
|
||||||
|
|
|
@ -46,7 +46,7 @@ class CookieFactory
|
||||||
/**
|
/**
|
||||||
* Same Site cookie value.
|
* Same Site cookie value.
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string|null
|
||||||
*/
|
*/
|
||||||
protected $samesite;
|
protected $samesite;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ class ResolveRoute implements Middleware
|
||||||
protected $routes;
|
protected $routes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var Dispatcher
|
* @var Dispatcher|null
|
||||||
*/
|
*/
|
||||||
protected $dispatcher;
|
protected $dispatcher;
|
||||||
|
|
||||||
|
@ -43,6 +43,8 @@ class ResolveRoute implements Middleware
|
||||||
/**
|
/**
|
||||||
* Resolve the given request from our route collection.
|
* Resolve the given request from our route collection.
|
||||||
*
|
*
|
||||||
|
* @return Response
|
||||||
|
*
|
||||||
* @throws MethodNotAllowedException
|
* @throws MethodNotAllowedException
|
||||||
* @throws RouteNotFoundException
|
* @throws RouteNotFoundException
|
||||||
*/
|
*/
|
||||||
|
@ -58,7 +60,7 @@ class ResolveRoute implements Middleware
|
||||||
throw new RouteNotFoundException($uri);
|
throw new RouteNotFoundException($uri);
|
||||||
case Dispatcher::METHOD_NOT_ALLOWED:
|
case Dispatcher::METHOD_NOT_ALLOWED:
|
||||||
throw new MethodNotAllowedException($method);
|
throw new MethodNotAllowedException($method);
|
||||||
case Dispatcher::FOUND:
|
default:
|
||||||
$request = $request
|
$request = $request
|
||||||
->withAttribute('routeName', $routeInfo[1]['name'])
|
->withAttribute('routeName', $routeInfo[1]['name'])
|
||||||
->withAttribute('routeHandler', $routeInfo[1]['handler'])
|
->withAttribute('routeHandler', $routeInfo[1]['handler'])
|
||||||
|
|
|
@ -11,6 +11,7 @@ namespace Flarum\Http;
|
||||||
|
|
||||||
use Flarum\Foundation\ErrorHandling\LogReporter;
|
use Flarum\Foundation\ErrorHandling\LogReporter;
|
||||||
use Flarum\Foundation\SiteInterface;
|
use Flarum\Foundation\SiteInterface;
|
||||||
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Laminas\Diactoros\Response;
|
use Laminas\Diactoros\Response;
|
||||||
use Laminas\Diactoros\ServerRequest;
|
use Laminas\Diactoros\ServerRequest;
|
||||||
use Laminas\Diactoros\ServerRequestFactory;
|
use Laminas\Diactoros\ServerRequestFactory;
|
||||||
|
@ -50,7 +51,7 @@ class Server
|
||||||
* We catch all exceptions happening during this process and format them to
|
* We catch all exceptions happening during this process and format them to
|
||||||
* prevent exposure of sensitive information.
|
* prevent exposure of sensitive information.
|
||||||
*
|
*
|
||||||
* @return \Psr\Http\Server\RequestHandlerInterface
|
* @return \Psr\Http\Server\RequestHandlerInterface|void
|
||||||
*/
|
*/
|
||||||
private function safelyBootAndGetHandler()
|
private function safelyBootAndGetHandler()
|
||||||
{
|
{
|
||||||
|
@ -80,7 +81,9 @@ class Server
|
||||||
*/
|
*/
|
||||||
private function cleanBootExceptionLog(Throwable $error)
|
private function cleanBootExceptionLog(Throwable $error)
|
||||||
{
|
{
|
||||||
if (app()->has('flarum.config') && app('flarum.config')->inDebugMode()) {
|
$container = resolve(Container::class);
|
||||||
|
|
||||||
|
if ($container->has('flarum.config') && resolve('flarum.config')->inDebugMode()) {
|
||||||
// If the application booted far enough for the config to be available, we will check for debug mode
|
// If the application booted far enough for the config to be available, we will check for debug mode
|
||||||
// Since the config is loaded very early, it is very likely to be available from the container
|
// Since the config is loaded very early, it is very likely to be available from the container
|
||||||
$message = $error->getMessage();
|
$message = $error->getMessage();
|
||||||
|
@ -96,12 +99,12 @@ class Server
|
||||||
<pre>$error</pre>
|
<pre>$error</pre>
|
||||||
ERROR;
|
ERROR;
|
||||||
exit(1);
|
exit(1);
|
||||||
} elseif (app()->has(LoggerInterface::class)) {
|
} elseif ($container->has(LoggerInterface::class)) {
|
||||||
// If the application booted far enough for the logger to be available, we will log the error there
|
// If the application booted far enough for the logger to be available, we will log the error there
|
||||||
// Considering most boot errors are related to database or extensions, the logger should already be loaded
|
// Considering most boot errors are related to database or extensions, the logger should already be loaded
|
||||||
// We check for LoggerInterface binding because it's a constructor dependency of LogReporter,
|
// We check for LoggerInterface binding because it's a constructor dependency of LogReporter,
|
||||||
// then instantiate LogReporter through the container for automatic dependency injection
|
// then instantiate LogReporter through the container for automatic dependency injection
|
||||||
app(LogReporter::class)->report($error);
|
resolve(LogReporter::class)->report($error);
|
||||||
|
|
||||||
echo 'Flarum encountered a boot error. Details have been logged to the Flarum log file.';
|
echo 'Flarum encountered a boot error. Details have been logged to the Flarum log file.';
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -12,9 +12,18 @@ namespace Flarum\Http;
|
||||||
use Flarum\Database\AbstractModel;
|
use Flarum\Database\AbstractModel;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T of AbstractModel
|
||||||
|
*/
|
||||||
interface SlugDriverInterface
|
interface SlugDriverInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* @param T $instance
|
||||||
|
*/
|
||||||
public function toSlug(AbstractModel $instance): string;
|
public function toSlug(AbstractModel $instance): string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return T
|
||||||
|
*/
|
||||||
public function fromSlug(string $slug, User $actor): AbstractModel;
|
public function fromSlug(string $slug, User $actor): AbstractModel;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,11 @@ class SlugManager
|
||||||
$this->drivers = $drivers;
|
$this->drivers = $drivers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @template T of \Flarum\Database\AbstractModel
|
||||||
|
* @param class-string<T> $resourceName
|
||||||
|
* @return SlugDriverInterface<T>
|
||||||
|
*/
|
||||||
public function forResource(string $resourceName): SlugDriverInterface
|
public function forResource(string $resourceName): SlugDriverInterface
|
||||||
{
|
{
|
||||||
return Arr::get($this->drivers, $resourceName, null);
|
return Arr::get($this->drivers, $resourceName, null);
|
||||||
|
|
|
@ -13,6 +13,7 @@ use Flarum\Console\AbstractCommand;
|
||||||
use Flarum\Install\Installation;
|
use Flarum\Install\Installation;
|
||||||
use Flarum\Install\Pipeline;
|
use Flarum\Install\Pipeline;
|
||||||
use Flarum\Install\Step;
|
use Flarum\Install\Step;
|
||||||
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
||||||
use Symfony\Component\Console\Input\InputOption;
|
use Symfony\Component\Console\Input\InputOption;
|
||||||
|
|
||||||
class InstallCommand extends AbstractCommand
|
class InstallCommand extends AbstractCommand
|
||||||
|
@ -83,7 +84,9 @@ class InstallCommand extends AbstractCommand
|
||||||
if ($this->input->getOption('file')) {
|
if ($this->input->getOption('file')) {
|
||||||
$this->dataSource = new FileDataProvider($this->input);
|
$this->dataSource = new FileDataProvider($this->input);
|
||||||
} else {
|
} else {
|
||||||
$this->dataSource = new UserDataProvider($this->input, $this->output, $this->getHelperSet()->get('question'));
|
/** @var QuestionHelper $questionHelper */
|
||||||
|
$questionHelper = $this->getHelperSet()->get('question');
|
||||||
|
$this->dataSource = new UserDataProvider($this->input, $this->output, $questionHelper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,6 @@ class IndexController extends AbstractHtmlController
|
||||||
*/
|
*/
|
||||||
protected $installation;
|
protected $installation;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Factory $view
|
|
||||||
* @param Installation $installation
|
|
||||||
*/
|
|
||||||
public function __construct(Factory $view, Installation $installation)
|
public function __construct(Factory $view, Installation $installation)
|
||||||
{
|
{
|
||||||
$this->view = $view;
|
$this->view = $view;
|
||||||
|
@ -37,7 +33,6 @@ class IndexController extends AbstractHtmlController
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
|
||||||
* @return \Illuminate\Contracts\Support\Renderable
|
* @return \Illuminate\Contracts\Support\Renderable
|
||||||
*/
|
*/
|
||||||
public function render(Request $request)
|
public function render(Request $request)
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
namespace Flarum\Install;
|
namespace Flarum\Install;
|
||||||
|
|
||||||
interface ReversibleStep
|
interface ReversibleStep extends Step
|
||||||
{
|
{
|
||||||
public function revert();
|
public function revert();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,11 @@ class EnableBundledExtensions implements Step
|
||||||
*/
|
*/
|
||||||
private $enabledExtensions;
|
private $enabledExtensions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Migrator|null
|
||||||
|
*/
|
||||||
|
private $migrator;
|
||||||
|
|
||||||
public function __construct(ConnectionInterface $database, $vendorPath, $assetPath, $enabledExtensions = null)
|
public function __construct(ConnectionInterface $database, $vendorPath, $assetPath, $enabledExtensions = null)
|
||||||
{
|
{
|
||||||
$this->database = $database;
|
$this->database = $database;
|
||||||
|
@ -124,7 +129,7 @@ class EnableBundledExtensions implements Step
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getMigrator()
|
private function getMigrator(): Migrator
|
||||||
{
|
{
|
||||||
return $this->migrator = $this->migrator ?? new Migrator(
|
return $this->migrator = $this->migrator ?? new Migrator(
|
||||||
new DatabaseMigrationRepository($this->database, 'migrations'),
|
new DatabaseMigrationRepository($this->database, 'migrations'),
|
||||||
|
|
|
@ -10,10 +10,9 @@
|
||||||
namespace Flarum\Install\Steps;
|
namespace Flarum\Install\Steps;
|
||||||
|
|
||||||
use Flarum\Install\ReversibleStep;
|
use Flarum\Install\ReversibleStep;
|
||||||
use Flarum\Install\Step;
|
|
||||||
use Illuminate\Filesystem\Filesystem;
|
use Illuminate\Filesystem\Filesystem;
|
||||||
|
|
||||||
class PublishAssets implements Step, ReversibleStep
|
class PublishAssets implements ReversibleStep
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
|
|
@ -12,9 +12,8 @@ namespace Flarum\Install\Steps;
|
||||||
use Flarum\Install\BaseUrl;
|
use Flarum\Install\BaseUrl;
|
||||||
use Flarum\Install\DatabaseConfig;
|
use Flarum\Install\DatabaseConfig;
|
||||||
use Flarum\Install\ReversibleStep;
|
use Flarum\Install\ReversibleStep;
|
||||||
use Flarum\Install\Step;
|
|
||||||
|
|
||||||
class StoreConfig implements Step, ReversibleStep
|
class StoreConfig implements ReversibleStep
|
||||||
{
|
{
|
||||||
private $debugMode;
|
private $debugMode;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ class EmailNotificationDriver implements NotificationDriverInterface
|
||||||
/**
|
/**
|
||||||
* Mail a notification to a list of users.
|
* Mail a notification to a list of users.
|
||||||
*
|
*
|
||||||
* @param MailableInterface $blueprint
|
* @param MailableInterface&BlueprintInterface $blueprint
|
||||||
* @param User[] $recipients
|
* @param User[] $recipients
|
||||||
*/
|
*/
|
||||||
protected function mailNotifications(MailableInterface $blueprint, array $recipients)
|
protected function mailNotifications(MailableInterface $blueprint, array $recipients)
|
||||||
|
|
|
@ -26,7 +26,7 @@ class DeletedAll
|
||||||
|
|
||||||
public function __construct(User $user, DateTime $timestamp)
|
public function __construct(User $user, DateTime $timestamp)
|
||||||
{
|
{
|
||||||
$this->user = $user;
|
$this->actor = $user;
|
||||||
$this->timestamp = $timestamp;
|
$this->timestamp = $timestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ class Read
|
||||||
|
|
||||||
public function __construct(User $user, Notification $notification, DateTime $timestamp)
|
public function __construct(User $user, Notification $notification, DateTime $timestamp)
|
||||||
{
|
{
|
||||||
$this->user = $user;
|
$this->actor = $user;
|
||||||
$this->notification = $notification;
|
$this->notification = $notification;
|
||||||
$this->timestamp = $timestamp;
|
$this->timestamp = $timestamp;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ class ReadAll
|
||||||
|
|
||||||
public function __construct(User $user, DateTime $timestamp)
|
public function __construct(User $user, DateTime $timestamp)
|
||||||
{
|
{
|
||||||
$this->user = $user;
|
$this->actor = $user;
|
||||||
$this->timestamp = $timestamp;
|
$this->timestamp = $timestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ use Illuminate\Support\Arr;
|
||||||
* @property \Carbon\Carbon $deleted_at
|
* @property \Carbon\Carbon $deleted_at
|
||||||
* @property \Flarum\User\User|null $user
|
* @property \Flarum\User\User|null $user
|
||||||
* @property \Flarum\User\User|null $fromUser
|
* @property \Flarum\User\User|null $fromUser
|
||||||
* @property \Flarum\Database\AbstractModel|null $subject
|
* @property \Flarum\Database\AbstractModel|\Flarum\Post\Post|\Flarum\Discussion\Discussion|null $subject
|
||||||
*/
|
*/
|
||||||
class Notification extends AbstractModel
|
class Notification extends AbstractModel
|
||||||
{
|
{
|
||||||
|
@ -76,7 +76,7 @@ class Notification extends AbstractModel
|
||||||
* When getting the data attribute, unserialize the JSON stored in the
|
* When getting the data attribute, unserialize the JSON stored in the
|
||||||
* database into a plain array.
|
* database into a plain array.
|
||||||
*
|
*
|
||||||
* @param string $value
|
* @param string|null $value
|
||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function getDataAttribute($value)
|
public function getDataAttribute($value)
|
||||||
|
@ -258,7 +258,7 @@ class Notification extends AbstractModel
|
||||||
static::$subjectModels[$type] = $subjectModel;
|
static::$subjectModels[$type] = $subjectModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getBlueprintAttributes(BlueprintInterface $blueprint): array
|
protected static function getBlueprintAttributes(BlueprintInterface $blueprint): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'type' => $blueprint::getType(),
|
'type' => $blueprint::getType(),
|
||||||
|
|
|
@ -12,6 +12,7 @@ namespace Flarum\Notification;
|
||||||
use Flarum\Settings\SettingsRepositoryInterface;
|
use Flarum\Settings\SettingsRepositoryInterface;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
use Illuminate\Contracts\Mail\Mailer;
|
use Illuminate\Contracts\Mail\Mailer;
|
||||||
|
use Illuminate\Contracts\Translation\Translator;
|
||||||
use Illuminate\Mail\Message;
|
use Illuminate\Mail\Message;
|
||||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||||
|
|
||||||
|
@ -23,7 +24,7 @@ class NotificationMailer
|
||||||
protected $mailer;
|
protected $mailer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var TranslatorInterface
|
* @var TranslatorInterface&Translator
|
||||||
*/
|
*/
|
||||||
protected $translator;
|
protected $translator;
|
||||||
|
|
||||||
|
@ -33,9 +34,7 @@ class NotificationMailer
|
||||||
protected $settings;
|
protected $settings;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Mailer $mailer
|
* @param TranslatorInterface&Translator $translator
|
||||||
* @param TranslatorInterface $translator
|
|
||||||
* @param SettingsRepositoryInterface $settings
|
|
||||||
*/
|
*/
|
||||||
public function __construct(Mailer $mailer, TranslatorInterface $translator, SettingsRepositoryInterface $settings)
|
public function __construct(Mailer $mailer, TranslatorInterface $translator, SettingsRepositoryInterface $settings)
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,7 +24,8 @@ class NotificationRepository
|
||||||
*/
|
*/
|
||||||
public function findByUser(User $user, $limit = null, $offset = 0)
|
public function findByUser(User $user, $limit = null, $offset = 0)
|
||||||
{
|
{
|
||||||
$primaries = Notification::selectRaw('MAX(id) AS id')
|
$primaries = Notification::query()
|
||||||
|
->selectRaw('MAX(id) AS id')
|
||||||
->selectRaw('SUM(read_at IS NULL) AS unread_count')
|
->selectRaw('SUM(read_at IS NULL) AS unread_count')
|
||||||
->where('user_id', $user->id)
|
->where('user_id', $user->id)
|
||||||
->whereIn('type', $user->getAlertableNotificationTypes())
|
->whereIn('type', $user->getAlertableNotificationTypes())
|
||||||
|
@ -35,7 +36,8 @@ class NotificationRepository
|
||||||
->skip($offset)
|
->skip($offset)
|
||||||
->take($limit);
|
->take($limit);
|
||||||
|
|
||||||
return Notification::select('notifications.*', 'p.unread_count')
|
return Notification::query()
|
||||||
|
->select('notifications.*', 'p.unread_count')
|
||||||
->joinSub($primaries, 'p', 'notifications.id', '=', 'p.id')
|
->joinSub($primaries, 'p', 'notifications.id', '=', 'p.id')
|
||||||
->latest()
|
->latest()
|
||||||
->get();
|
->get();
|
||||||
|
|
|
@ -23,7 +23,7 @@ interface MergeableInterface
|
||||||
* passed model.
|
* passed model.
|
||||||
*
|
*
|
||||||
* @param \Flarum\Post\Post|null $previous
|
* @param \Flarum\Post\Post|null $previous
|
||||||
* @return Post The model resulting after the merge. If the merge is
|
* @return static The model resulting after the merge. If the merge is
|
||||||
* unsuccessful, this should be the current model instance. Otherwise,
|
* unsuccessful, this should be the current model instance. Otherwise,
|
||||||
* it should be the model that was merged into.
|
* it should be the model that was merged into.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,14 +16,13 @@ use Flarum\Foundation\EventGeneratorTrait;
|
||||||
use Flarum\Notification\Notification;
|
use Flarum\Notification\Notification;
|
||||||
use Flarum\Post\Event\Deleted;
|
use Flarum\Post\Event\Deleted;
|
||||||
use Flarum\User\User;
|
use Flarum\User\User;
|
||||||
use Illuminate\Database\ConnectionInterface;
|
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Query\Expression;
|
use Illuminate\Database\Query\Expression;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @property int $id
|
* @property int $id
|
||||||
* @property int $discussion_id
|
* @property int $discussion_id
|
||||||
* @property int $number
|
* @property int|Expression $number
|
||||||
* @property \Carbon\Carbon $created_at
|
* @property \Carbon\Carbon $created_at
|
||||||
* @property int|null $user_id
|
* @property int|null $user_id
|
||||||
* @property string|null $type
|
* @property string|null $type
|
||||||
|
@ -94,8 +93,8 @@ class Post extends AbstractModel
|
||||||
static::creating(function (self $post) {
|
static::creating(function (self $post) {
|
||||||
$post->type = $post::$type;
|
$post->type = $post::$type;
|
||||||
|
|
||||||
/** @var ConnectionInterface $db */
|
$db = static::getConnectionResolver()->connection();
|
||||||
$db = static::getConnectionResolver();
|
|
||||||
$post->number = new Expression('('.
|
$post->number = new Expression('('.
|
||||||
$db->table('posts', 'pn')
|
$db->table('posts', 'pn')
|
||||||
->whereRaw($db->getTablePrefix().'pn.discussion_id = '.intval($post->discussion_id))
|
->whereRaw($db->getTablePrefix().'pn.discussion_id = '.intval($post->discussion_id))
|
||||||
|
|
|
@ -18,7 +18,7 @@ class PostRepository
|
||||||
/**
|
/**
|
||||||
* Get a new query builder for the posts table.
|
* Get a new query builder for the posts table.
|
||||||
*
|
*
|
||||||
* @return Builder
|
* @return Builder<Post>
|
||||||
*/
|
*/
|
||||||
public function query()
|
public function query()
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,7 @@ class PostRepository
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User|null $user
|
* @param User|null $user
|
||||||
* @return Builder
|
* @return Builder<Post>
|
||||||
*/
|
*/
|
||||||
protected function queryVisibleTo(User $user = null)
|
protected function queryVisibleTo(User $user = null)
|
||||||
{
|
{
|
||||||
|
@ -45,8 +45,8 @@ class PostRepository
|
||||||
* user, or throw an exception.
|
* user, or throw an exception.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int $id
|
||||||
* @param \Flarum\User\User $actor
|
* @param \Flarum\User\User|null $actor
|
||||||
* @return \Flarum\Post\Post
|
* @return Post
|
||||||
*
|
*
|
||||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||||
*/
|
*/
|
||||||
|
@ -126,7 +126,7 @@ class PostRepository
|
||||||
/**
|
/**
|
||||||
* @param array $ids
|
* @param array $ids
|
||||||
* @param User|null $actor
|
* @param User|null $actor
|
||||||
* @return Builder
|
* @return Builder<Post>
|
||||||
*/
|
*/
|
||||||
protected function queryIds(array $ids, User $actor = null)
|
protected function queryIds(array $ids, User $actor = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -42,9 +42,9 @@ class ExceptionHandler implements ExceptionHandling
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Http\Request $request
|
* @param \Illuminate\Http\Request $request
|
||||||
* @param Throwable $e
|
* @param Throwable $e
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function render($request, Throwable $e)
|
public function render($request, Throwable $e) /** @phpstan-ignore-line */
|
||||||
{
|
{
|
||||||
// TODO: Implement render() method.
|
// TODO: Implement render() method.
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class QueueFactory implements Factory
|
||||||
/**
|
/**
|
||||||
* The cached queue instance.
|
* The cached queue instance.
|
||||||
*
|
*
|
||||||
* @var \Illuminate\Contracts\Queue\Queue
|
* @var \Illuminate\Contracts\Queue\Queue|null
|
||||||
*/
|
*/
|
||||||
private $queue;
|
private $queue;
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ use Flarum\Foundation\Config;
|
||||||
use Flarum\Foundation\ErrorHandling\Registry;
|
use Flarum\Foundation\ErrorHandling\Registry;
|
||||||
use Flarum\Foundation\ErrorHandling\Reporter;
|
use Flarum\Foundation\ErrorHandling\Reporter;
|
||||||
use Flarum\Foundation\Paths;
|
use Flarum\Foundation\Paths;
|
||||||
|
use Illuminate\Container\Container as ContainerImplementation;
|
||||||
use Illuminate\Contracts\Cache\Factory as CacheFactory;
|
use Illuminate\Contracts\Cache\Factory as CacheFactory;
|
||||||
use Illuminate\Contracts\Container\Container;
|
use Illuminate\Contracts\Container\Container;
|
||||||
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling;
|
use Illuminate\Contracts\Debug\ExceptionHandler as ExceptionHandling;
|
||||||
|
@ -52,7 +53,7 @@ class QueueServiceProvider extends AbstractServiceProvider
|
||||||
|
|
||||||
// Extensions can override this binding if they want to make Flarum use
|
// Extensions can override this binding if they want to make Flarum use
|
||||||
// a different queuing backend.
|
// a different queuing backend.
|
||||||
$this->container->singleton('flarum.queue.connection', function (Container $container) {
|
$this->container->singleton('flarum.queue.connection', function (ContainerImplementation $container) {
|
||||||
$queue = new SyncQueue;
|
$queue = new SyncQueue;
|
||||||
$queue->setContainer($container);
|
$queue->setContainer($container);
|
||||||
|
|
||||||
|
@ -90,7 +91,12 @@ class QueueServiceProvider extends AbstractServiceProvider
|
||||||
// Bind a simple cache manager that returns the cache store.
|
// Bind a simple cache manager that returns the cache store.
|
||||||
$this->container->singleton('cache', function (Container $container) {
|
$this->container->singleton('cache', function (Container $container) {
|
||||||
return new class($container) implements CacheFactory {
|
return new class($container) implements CacheFactory {
|
||||||
public function __construct($container)
|
/**
|
||||||
|
* @var Container
|
||||||
|
*/
|
||||||
|
private $container;
|
||||||
|
|
||||||
|
public function __construct(Container $container)
|
||||||
{
|
{
|
||||||
$this->container = $container;
|
$this->container = $container;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,13 +34,15 @@ abstract class AbstractRegexGambit implements GambitInterface
|
||||||
* Match the bit against this gambit.
|
* Match the bit against this gambit.
|
||||||
*
|
*
|
||||||
* @param string $bit
|
* @param string $bit
|
||||||
* @return array
|
* @return array|null
|
||||||
*/
|
*/
|
||||||
protected function match($bit)
|
protected function match($bit)
|
||||||
{
|
{
|
||||||
if (preg_match('/^(-?)'.$this->getGambitPattern().'$/i', $bit, $matches)) {
|
if (preg_match('/^(-?)'.$this->getGambitPattern().'$/i', $bit, $matches)) {
|
||||||
return $matches;
|
return $matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -43,7 +43,6 @@ abstract class AbstractSearcher
|
||||||
* @param int $offset
|
* @param int $offset
|
||||||
*
|
*
|
||||||
* @return QueryResults
|
* @return QueryResults
|
||||||
* @throws InvalidArgumentException
|
|
||||||
*/
|
*/
|
||||||
public function search(QueryCriteria $criteria, $limit = null, $offset = 0): QueryResults
|
public function search(QueryCriteria $criteria, $limit = null, $offset = 0): QueryResults
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,9 +26,6 @@ class GambitManager
|
||||||
*/
|
*/
|
||||||
protected $fulltextGambit;
|
protected $fulltextGambit;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param GambitInterface $gambit
|
|
||||||
*/
|
|
||||||
public function __construct(GambitInterface $fulltextGambit)
|
public function __construct(GambitInterface $fulltextGambit)
|
||||||
{
|
{
|
||||||
$this->fulltextGambit = $fulltextGambit;
|
$this->fulltextGambit = $fulltextGambit;
|
||||||
|
|
|
@ -28,10 +28,6 @@ class IndexController extends AbstractHtmlController
|
||||||
$this->view = $view;
|
$this->view = $view;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Request $request
|
|
||||||
* @return \Psr\Http\Message\ResponseInterface
|
|
||||||
*/
|
|
||||||
public function render(Request $request)
|
public function render(Request $request)
|
||||||
{
|
{
|
||||||
$view = $this->view->make('flarum.update::app')->with('title', 'Update Flarum');
|
$view = $this->view->make('flarum.update::app')->with('title', 'Update Flarum');
|
||||||
|
|
|
@ -40,13 +40,11 @@ abstract class AbstractPolicy
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $user
|
|
||||||
* @param string $ability
|
|
||||||
* @param $instance
|
|
||||||
* @return string|void
|
* @return string|void
|
||||||
*/
|
*/
|
||||||
public function checkAbility(User $actor, string $ability, $instance)
|
public function checkAbility(User $actor, string $ability, $instance)
|
||||||
{ // If a specific method for this ability is defined,
|
{
|
||||||
|
// If a specific method for this ability is defined,
|
||||||
// call that and return any non-null results
|
// call that and return any non-null results
|
||||||
if (method_exists($this, $ability)) {
|
if (method_exists($this, $ability)) {
|
||||||
$result = $this->sanitizeResult(call_user_func_array([$this, $ability], [$actor, $instance]));
|
$result = $this->sanitizeResult(call_user_func_array([$this, $ability], [$actor, $instance]));
|
||||||
|
@ -73,7 +71,7 @@ abstract class AbstractPolicy
|
||||||
* `return SOME_BOOLEAN_LOGIC;
|
* `return SOME_BOOLEAN_LOGIC;
|
||||||
*
|
*
|
||||||
* @param mixed $result
|
* @param mixed $result
|
||||||
* @return string|void
|
* @return string|void|null
|
||||||
*/
|
*/
|
||||||
public function sanitizeResult($result)
|
public function sanitizeResult($result)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,12 +54,6 @@ class RegisterUserHandler
|
||||||
*/
|
*/
|
||||||
protected $imageManager;
|
protected $imageManager;
|
||||||
|
|
||||||
/**
|
|
||||||
* @param Dispatcher $events
|
|
||||||
* @param SettingsRepositoryInterface $settings
|
|
||||||
* @param UserValidator $validator
|
|
||||||
* @param AvatarUploader $avatarUploader
|
|
||||||
*/
|
|
||||||
public function __construct(Dispatcher $events, SettingsRepositoryInterface $settings, UserValidator $userValidator, AvatarUploader $avatarUploader, Factory $validator, ImageManager $imageManager)
|
public function __construct(Dispatcher $events, SettingsRepositoryInterface $settings, UserValidator $userValidator, AvatarUploader $avatarUploader, Factory $validator, ImageManager $imageManager)
|
||||||
{
|
{
|
||||||
$this->events = $events;
|
$this->events = $events;
|
||||||
|
@ -91,6 +85,7 @@ class RegisterUserHandler
|
||||||
// If a valid authentication token was provided as an attribute,
|
// If a valid authentication token was provided as an attribute,
|
||||||
// then we won't require the user to choose a password.
|
// then we won't require the user to choose a password.
|
||||||
if (isset($data['attributes']['token'])) {
|
if (isset($data['attributes']['token'])) {
|
||||||
|
/** @var RegistrationToken $token */
|
||||||
$token = RegistrationToken::validOrFail($data['attributes']['token']);
|
$token = RegistrationToken::validOrFail($data['attributes']['token']);
|
||||||
|
|
||||||
$password = $password ?: Str::random(20);
|
$password = $password ?: Str::random(20);
|
||||||
|
|
|
@ -81,7 +81,7 @@ class EmailToken extends AbstractModel
|
||||||
*/
|
*/
|
||||||
public function scopeValidOrFail($query, $id)
|
public function scopeValidOrFail($query, $id)
|
||||||
{
|
{
|
||||||
/** @var EmailToken $token */
|
/** @var static|null $token */
|
||||||
$token = $query->find($id);
|
$token = $query->find($id);
|
||||||
|
|
||||||
if (! $token || $token->created_at->diffInDays() >= 1) {
|
if (! $token || $token->created_at->diffInDays() >= 1) {
|
||||||
|
|
|
@ -12,6 +12,9 @@ namespace Flarum\User;
|
||||||
use Flarum\Database\AbstractModel;
|
use Flarum\Database\AbstractModel;
|
||||||
use Flarum\Http\SlugDriverInterface;
|
use Flarum\Http\SlugDriverInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements SlugDriverInterface<User>
|
||||||
|
*/
|
||||||
class IdSlugDriver implements SlugDriverInterface
|
class IdSlugDriver implements SlugDriverInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -24,11 +27,17 @@ class IdSlugDriver implements SlugDriverInterface
|
||||||
$this->users = $users;
|
$this->users = $users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $instance
|
||||||
|
*/
|
||||||
public function toSlug(AbstractModel $instance): string
|
public function toSlug(AbstractModel $instance): string
|
||||||
{
|
{
|
||||||
return $instance->id;
|
return (string) $instance->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
public function fromSlug(string $slug, User $actor): AbstractModel
|
public function fromSlug(string $slug, User $actor): AbstractModel
|
||||||
{
|
{
|
||||||
return $this->users->findOrFail($slug, $actor);
|
return $this->users->findOrFail($slug, $actor);
|
||||||
|
|
|
@ -21,6 +21,8 @@ use Illuminate\Support\Str;
|
||||||
* @property array $user_attributes
|
* @property array $user_attributes
|
||||||
* @property array $payload
|
* @property array $payload
|
||||||
* @property \Carbon\Carbon $created_at
|
* @property \Carbon\Carbon $created_at
|
||||||
|
*
|
||||||
|
* @method static self validOrFail(string $token)
|
||||||
*/
|
*/
|
||||||
class RegistrationToken extends AbstractModel
|
class RegistrationToken extends AbstractModel
|
||||||
{
|
{
|
||||||
|
@ -74,7 +76,7 @@ class RegistrationToken extends AbstractModel
|
||||||
/**
|
/**
|
||||||
* Find the token with the given ID, and assert that it has not expired.
|
* Find the token with the given ID, and assert that it has not expired.
|
||||||
*
|
*
|
||||||
* @param \Illuminate\Database\Eloquent\Builder $query
|
* @param \Illuminate\Database\Eloquent\Builder<self> $query
|
||||||
* @param string $token
|
* @param string $token
|
||||||
*
|
*
|
||||||
* @throws InvalidConfirmationTokenException
|
* @throws InvalidConfirmationTokenException
|
||||||
|
@ -83,7 +85,7 @@ class RegistrationToken extends AbstractModel
|
||||||
*/
|
*/
|
||||||
public function scopeValidOrFail($query, string $token)
|
public function scopeValidOrFail($query, string $token)
|
||||||
{
|
{
|
||||||
/** @var RegistrationToken $token */
|
/** @var RegistrationToken|null $token */
|
||||||
$token = $query->find($token);
|
$token = $query->find($token);
|
||||||
|
|
||||||
if (! $token || $token->created_at->lessThan(Carbon::now()->subDay())) {
|
if (! $token || $token->created_at->lessThan(Carbon::now()->subDay())) {
|
||||||
|
|
|
@ -50,5 +50,7 @@ class FulltextGambit implements GambitInterface
|
||||||
'id',
|
'id',
|
||||||
$this->getUserSearchSubQuery($searchValue)
|
$this->getUserSearchSubQuery($searchValue)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,7 +109,7 @@ class User extends AbstractModel
|
||||||
/**
|
/**
|
||||||
* The access gate.
|
* The access gate.
|
||||||
*
|
*
|
||||||
* @var Gate
|
* @var Access\Gate
|
||||||
*/
|
*/
|
||||||
protected static $gate;
|
protected static $gate;
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ class User extends AbstractModel
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Gate $gate
|
* @param Access\Gate $gate
|
||||||
*/
|
*/
|
||||||
public static function setGate($gate)
|
public static function setGate($gate)
|
||||||
{
|
{
|
||||||
|
@ -296,7 +296,7 @@ class User extends AbstractModel
|
||||||
/**
|
/**
|
||||||
* Change the path of the user avatar.
|
* Change the path of the user avatar.
|
||||||
*
|
*
|
||||||
* @param string $path
|
* @param string|null $path
|
||||||
* @return $this
|
* @return $this
|
||||||
*/
|
*/
|
||||||
public function changeAvatarPath($path)
|
public function changeAvatarPath($path)
|
||||||
|
@ -311,7 +311,6 @@ class User extends AbstractModel
|
||||||
/**
|
/**
|
||||||
* Get the URL of the user's avatar.
|
* Get the URL of the user's avatar.
|
||||||
*
|
*
|
||||||
* @todo Allow different storage locations to be used
|
|
||||||
* @param string|null $value
|
* @param string|null $value
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
|
@ -410,15 +409,6 @@ class User extends AbstractModel
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function checkForDeprecatedPermissions($permission)
|
|
||||||
{
|
|
||||||
foreach (['viewDiscussions', 'viewUserList'] as $deprecated) {
|
|
||||||
if (strpos($permission, $deprecated) !== false) {
|
|
||||||
trigger_error('The `viewDiscussions` and `viewUserList` permissions have been renamed to `viewForum` and `searchUsers` respectively. Please use those instead.', E_USER_DEPRECATED);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the notification types that should be alerted to this user, according
|
* Get the notification types that should be alerted to this user, according
|
||||||
* to their preferences.
|
* to their preferences.
|
||||||
|
@ -482,7 +472,7 @@ class User extends AbstractModel
|
||||||
* Get the values of all registered preferences for this user, by
|
* Get the values of all registered preferences for this user, by
|
||||||
* transforming their stored preferences and merging them with the defaults.
|
* transforming their stored preferences and merging them with the defaults.
|
||||||
*
|
*
|
||||||
* @param string $value
|
* @param string|null $value
|
||||||
* @return array
|
* @return array
|
||||||
*/
|
*/
|
||||||
public function getPreferencesAttribute($value)
|
public function getPreferencesAttribute($value)
|
||||||
|
@ -679,7 +669,7 @@ class User extends AbstractModel
|
||||||
/**
|
/**
|
||||||
* Define the relationship with the user's read discussions.
|
* Define the relationship with the user's read discussions.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<Discussion>
|
||||||
*/
|
*/
|
||||||
public function read()
|
public function read()
|
||||||
{
|
{
|
||||||
|
@ -838,7 +828,7 @@ class User extends AbstractModel
|
||||||
* Register a callback that processes a user's list of groups.
|
* Register a callback that processes a user's list of groups.
|
||||||
*
|
*
|
||||||
* @param callable $callback
|
* @param callable $callback
|
||||||
* @return array $groupIds
|
* @return void
|
||||||
*
|
*
|
||||||
* @internal
|
* @internal
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -16,7 +16,7 @@ class UserRepository
|
||||||
/**
|
/**
|
||||||
* Get a new query builder for the users table.
|
* Get a new query builder for the users table.
|
||||||
*
|
*
|
||||||
* @return \Illuminate\Database\Eloquent\Builder
|
* @return Builder<User>
|
||||||
*/
|
*/
|
||||||
public function query()
|
public function query()
|
||||||
{
|
{
|
||||||
|
@ -27,15 +27,15 @@ class UserRepository
|
||||||
* Find a user by ID, optionally making sure it is visible to a certain
|
* Find a user by ID, optionally making sure it is visible to a certain
|
||||||
* user, or throw an exception.
|
* user, or throw an exception.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param int|string $id
|
||||||
* @param User $actor
|
* @param User|null $actor
|
||||||
* @return User
|
* @return User
|
||||||
*
|
*
|
||||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||||
*/
|
*/
|
||||||
public function findOrFail($id, User $actor = null)
|
public function findOrFail($id, User $actor = null)
|
||||||
{
|
{
|
||||||
$query = User::where('id', $id);
|
$query = $this->query()->where('id', $id);
|
||||||
|
|
||||||
return $this->scopeVisibleTo($query, $actor)->firstOrFail();
|
return $this->scopeVisibleTo($query, $actor)->firstOrFail();
|
||||||
}
|
}
|
||||||
|
@ -44,15 +44,15 @@ class UserRepository
|
||||||
* Find a user by username, optionally making sure it is visible to a certain
|
* Find a user by username, optionally making sure it is visible to a certain
|
||||||
* user, or throw an exception.
|
* user, or throw an exception.
|
||||||
*
|
*
|
||||||
* @param int $id
|
* @param string $username
|
||||||
* @param User $actor
|
* @param User|null $actor
|
||||||
* @return User
|
* @return User
|
||||||
*
|
*
|
||||||
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
|
||||||
*/
|
*/
|
||||||
public function findOrFailByUsername($username, User $actor = null)
|
public function findOrFailByUsername($username, User $actor = null)
|
||||||
{
|
{
|
||||||
$query = User::where('username', $username);
|
$query = $this->query()->where('username', $username);
|
||||||
|
|
||||||
return $this->scopeVisibleTo($query, $actor)->firstOrFail();
|
return $this->scopeVisibleTo($query, $actor)->firstOrFail();
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ class UserRepository
|
||||||
{
|
{
|
||||||
$field = filter_var($identification, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
|
$field = filter_var($identification, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
|
||||||
|
|
||||||
return User::where($field, $identification)->first();
|
return $this->query()->where($field, $identification)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,7 +78,7 @@ class UserRepository
|
||||||
*/
|
*/
|
||||||
public function findByEmail($email)
|
public function findByEmail($email)
|
||||||
{
|
{
|
||||||
return User::where('email', $email)->first();
|
return $this->query()->where('email', $email)->first();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,7 +90,7 @@ class UserRepository
|
||||||
*/
|
*/
|
||||||
public function getIdForUsername($username, User $actor = null)
|
public function getIdForUsername($username, User $actor = null)
|
||||||
{
|
{
|
||||||
$query = User::where('username', $username);
|
$query = $this->query()->where('username', $username);
|
||||||
|
|
||||||
return $this->scopeVisibleTo($query, $actor)->value('id');
|
return $this->scopeVisibleTo($query, $actor)->value('id');
|
||||||
}
|
}
|
||||||
|
@ -107,7 +107,7 @@ class UserRepository
|
||||||
{
|
{
|
||||||
$string = $this->escapeLikeString($string);
|
$string = $this->escapeLikeString($string);
|
||||||
|
|
||||||
$query = User::where('username', 'like', '%'.$string.'%')
|
$query = $this->query()->where('username', 'like', '%'.$string.'%')
|
||||||
->orderByRaw('username = ? desc', [$string])
|
->orderByRaw('username = ? desc', [$string])
|
||||||
->orderByRaw('username like ? desc', [$string.'%']);
|
->orderByRaw('username like ? desc', [$string.'%']);
|
||||||
|
|
||||||
|
@ -117,9 +117,9 @@ class UserRepository
|
||||||
/**
|
/**
|
||||||
* Scope a query to only include records that are visible to a user.
|
* Scope a query to only include records that are visible to a user.
|
||||||
*
|
*
|
||||||
* @param Builder $query
|
* @param Builder<User> $query
|
||||||
* @param User $actor
|
* @param User|null $actor
|
||||||
* @return Builder
|
* @return Builder<User>
|
||||||
*/
|
*/
|
||||||
protected function scopeVisibleTo(Builder $query, User $actor = null)
|
protected function scopeVisibleTo(Builder $query, User $actor = null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -109,6 +109,9 @@ class UserServiceProvider extends AbstractServiceProvider
|
||||||
User::addGroupProcessor(ContainerUtil::wrapCallback($callback, $container));
|
User::addGroupProcessor(ContainerUtil::wrapCallback($callback, $container));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var \Illuminate\Container\Container $container
|
||||||
|
*/
|
||||||
User::setHasher($container->make('hash'));
|
User::setHasher($container->make('hash'));
|
||||||
User::setPasswordCheckers($container->make('flarum.user.password_checkers'));
|
User::setPasswordCheckers($container->make('flarum.user.password_checkers'));
|
||||||
User::setGate($container->makeWith(Access\Gate::class, ['policyClasses' => $container->make('flarum.policies')]));
|
User::setGate($container->makeWith(Access\Gate::class, ['policyClasses' => $container->make('flarum.policies')]));
|
||||||
|
|
|
@ -14,7 +14,7 @@ use Flarum\Foundation\AbstractValidator;
|
||||||
class UserValidator extends AbstractValidator
|
class UserValidator extends AbstractValidator
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @var User
|
* @var User|null
|
||||||
*/
|
*/
|
||||||
protected $user;
|
protected $user;
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,9 @@ namespace Flarum\User;
|
||||||
use Flarum\Database\AbstractModel;
|
use Flarum\Database\AbstractModel;
|
||||||
use Flarum\Http\SlugDriverInterface;
|
use Flarum\Http\SlugDriverInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @implements SlugDriverInterface<User>
|
||||||
|
*/
|
||||||
class UsernameSlugDriver implements SlugDriverInterface
|
class UsernameSlugDriver implements SlugDriverInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -24,11 +27,17 @@ class UsernameSlugDriver implements SlugDriverInterface
|
||||||
$this->users = $users;
|
$this->users = $users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param User $instance
|
||||||
|
*/
|
||||||
public function toSlug(AbstractModel $instance): string
|
public function toSlug(AbstractModel $instance): string
|
||||||
{
|
{
|
||||||
return $instance->username;
|
return $instance->username;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return User
|
||||||
|
*/
|
||||||
public function fromSlug(string $slug, User $actor): AbstractModel
|
public function fromSlug(string $slug, User $actor): AbstractModel
|
||||||
{
|
{
|
||||||
return $this->users->findOrFailByUsername($slug, $actor);
|
return $this->users->findOrFailByUsername($slug, $actor);
|
||||||
|
|
|
@ -16,11 +16,11 @@ if (! function_exists('resolve')) {
|
||||||
* Resolve a service from the container.
|
* Resolve a service from the container.
|
||||||
*
|
*
|
||||||
* @template T
|
* @template T
|
||||||
* @param class-string<T>|string $name
|
* @param string|class-string<T> $name
|
||||||
* @param array $parameters
|
* @param array $parameters
|
||||||
* @return T|mixed
|
* @return T|mixed
|
||||||
*/
|
*/
|
||||||
function resolve($name, $parameters = [])
|
function resolve(string $name, array $parameters = [])
|
||||||
{
|
{
|
||||||
return Container::getInstance()->make($name, $parameters);
|
return Container::getInstance()->make($name, $parameters);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"require": {
|
"require": {
|
||||||
"phpstan/phpstan-php-parser": "^1.0",
|
"phpstan/phpstan": "^1.2",
|
||||||
"phpstan/phpstan": "^1.2"
|
"nunomaduro/larastan": "^1.0"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
|
|
|
@ -1,291 +1,17 @@
|
||||||
includes:
|
includes:
|
||||||
- vendor/phpstan/phpstan-php-parser/extension.neon
|
- larastan-extension.neon
|
||||||
|
- phpstan-baseline.neon
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
stubFiles:
|
stubFiles:
|
||||||
- stubs/Illuminate/Enumerable.stub
|
- stubs/Illuminate/Contracts/Container/Container.stub
|
||||||
- stubs/Illuminate/Database/EloquentBuilder.stub
|
- stubs/Illuminate/Queue/ListenerOptions.stub
|
||||||
- stubs/Illuminate/Collection.stub
|
- stubs/Illuminate/Support/ServiceProvider.stub
|
||||||
- stubs/Illuminate/Database/EloquentCollection.stub
|
- stubs/Illuminate/Filesystem/Filesystem.stub
|
||||||
- stubs/Illuminate/Database/Factory.stub
|
- stubs/Illuminate/Filesystem/FilesystemManager.stub
|
||||||
- stubs/Illuminate/Database/Model.stub
|
|
||||||
- stubs/Illuminate/Database/Gate.stub
|
|
||||||
- stubs/Illuminate/Database/Relation.stub
|
|
||||||
- stubs/Illuminate/Database/BelongsTo.stub
|
|
||||||
- stubs/Illuminate/Database/BelongsToMany.stub
|
|
||||||
- stubs/Illuminate/Database/HasOneOrMany.stub
|
|
||||||
- stubs/Illuminate/Database/HasMany.stub
|
|
||||||
- stubs/Illuminate/Database/HasOne.stub
|
|
||||||
- stubs/Illuminate/Database/HasOneThrough.stub
|
|
||||||
- stubs/Illuminate/Database/HasManyThrough.stub
|
|
||||||
- stubs/Illuminate/Database/MorphTo.stub
|
|
||||||
- stubs/Illuminate/Database/MorphToMany.stub
|
|
||||||
- stubs/Illuminate/Database/MorphMany.stub
|
|
||||||
- stubs/Illuminate/Database/MorphOne.stub
|
|
||||||
- stubs/Illuminate/Database/MorphOneOrMany.stub
|
|
||||||
- stubs/Illuminate/HigherOrderProxies.stub
|
|
||||||
- stubs/Illuminate/Database/QueryBuilder.stub
|
|
||||||
- stubs/Illuminate/EnumeratesValues.stub
|
|
||||||
- stubs/Contracts/Support.stub
|
|
||||||
universalObjectCratesClasses:
|
|
||||||
- Illuminate\Http\Request
|
|
||||||
mixinExcludeClasses:
|
|
||||||
- Eloquent
|
|
||||||
earlyTerminatingFunctionCalls:
|
|
||||||
- abort
|
|
||||||
- dd
|
|
||||||
excludePaths:
|
|
||||||
- *.blade.php
|
|
||||||
checkGenericClassInNonGenericObjectType: false
|
|
||||||
checkModelProperties: false
|
|
||||||
databaseMigrationsPath: []
|
|
||||||
|
|
||||||
parametersSchema:
|
# We're changing the disk return type from Filesystem to Cloud,
|
||||||
databaseMigrationsPath: listOf(string())
|
# rather than hacking every bit of the codebase with a phpdoc @var.
|
||||||
checkModelProperties: bool()
|
- stubs/Illuminate/Contracts/Filesystem/Factory.stub
|
||||||
|
- stubs/Illuminate/Contracts/Filesystem/Cloud.stub
|
||||||
services:
|
- stubs/Illuminate/Contracts/Filesystem/Filesystem.stub
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\RelationForwardsCallsExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.methodsClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\ModelForwardsCallsExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.methodsClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\EloquentBuilderForwardsCallsExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.methodsClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\HigherOrderTapProxyExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.methodsClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\HigherOrderCollectionProxyExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.methodsClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\StorageMethodsClassReflectionExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.methodsClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\Extension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.methodsClassReflectionExtension
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\ModelFactoryMethodsClassReflectionExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.methodsClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Properties\ModelAccessorExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.propertiesClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Properties\ModelPropertyExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.propertiesClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Properties\HigherOrderCollectionProxyPropertyExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.propertiesClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\RelationDynamicMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\ModelRelationsDynamicMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\HigherOrderTapProxyExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
arguments:
|
|
||||||
className: Illuminate\Contracts\Container\Container
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
arguments:
|
|
||||||
className: Illuminate\Container\Container
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
arguments:
|
|
||||||
className: Illuminate\Foundation\Application
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
arguments:
|
|
||||||
className: Illuminate\Contracts\Foundation\Application
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Properties\ModelRelationsExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.propertiesClassReflectionExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\ModelFactoryDynamicStaticMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\ModelExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\RequestExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\EloquentBuilderExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\RelationFindExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\RelationCollectionExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\ModelFindExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\BuilderModelFindExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\TestCaseExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\CollectionMakeDynamicStaticMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Support\CollectionHelper
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\Helpers\CollectExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\Helpers\TransExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\Helpers\ValidatorExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\CollectionFilterDynamicReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\AbortIfFunctionTypeSpecifyingExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
|
||||||
arguments:
|
|
||||||
methodName: 'abort'
|
|
||||||
negate: false
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\AbortIfFunctionTypeSpecifyingExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
|
||||||
arguments:
|
|
||||||
methodName: 'abort'
|
|
||||||
negate: true
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\AbortIfFunctionTypeSpecifyingExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
|
||||||
arguments:
|
|
||||||
methodName: throw
|
|
||||||
negate: false
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\AbortIfFunctionTypeSpecifyingExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
|
||||||
arguments:
|
|
||||||
methodName: throw
|
|
||||||
negate: true
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\Helpers\AppExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\Helpers\ValueExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\Helpers\TapExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\ReturnTypes\StorageDynamicStaticMethodReturnTypeExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\GenericEloquentCollectionTypeNodeResolverExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.phpDoc.typeNodeResolverExtension
|
|
||||||
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\ViewStringTypeNodeResolverExtension
|
|
||||||
tags:
|
|
||||||
- phpstan.phpDoc.typeNodeResolverExtension
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Methods\BuilderHelper
|
|
||||||
arguments:
|
|
||||||
checkProperties: %checkModelProperties%
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Properties\MigrationHelper
|
|
||||||
arguments:
|
|
||||||
databaseMigrationPath: %databaseMigrationsPath%
|
|
||||||
parser: @currentPhpVersionSimpleDirectParser
|
|
||||||
-
|
|
||||||
class: Flarum\PHPStan\Types\RelationParserHelper
|
|
||||||
arguments:
|
|
||||||
parser: @currentPhpVersionSimpleDirectParser
|
|
||||||
|
|
439
php-packages/phpstan/larastan-extension.neon
Normal file
439
php-packages/phpstan/larastan-extension.neon
Normal file
|
@ -0,0 +1,439 @@
|
||||||
|
parameters:
|
||||||
|
stubFiles:
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Enumerable.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/EloquentBuilder.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Collection.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/EloquentCollection.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Factory.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Model.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Gate.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Relation.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/BelongsTo.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/BelongsToMany.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/HasOneOrMany.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/HasMany.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/HasOne.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/HasOneThrough.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/HasManyThrough.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Mailable.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/MorphOne.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/MorphOneOrMany.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/MorphTo.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/MorphToMany.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/MorphMany.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Helpers.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/HigherOrderProxies.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/QueryBuilder.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Facades.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Pagination.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Contracts/Pagination.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Contracts/Support.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Redis/Connection.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/Logger.stub
|
||||||
|
- ../../vendor/nunomaduro/larastan/stubs/EnumeratesValues.stub
|
||||||
|
universalObjectCratesClasses:
|
||||||
|
- Illuminate\Http\Request
|
||||||
|
earlyTerminatingFunctionCalls:
|
||||||
|
- abort
|
||||||
|
- dd
|
||||||
|
excludePaths:
|
||||||
|
- *.blade.php
|
||||||
|
mixinExcludeClasses:
|
||||||
|
- Eloquent
|
||||||
|
# bootstrapFiles:
|
||||||
|
# - bootstrap.php
|
||||||
|
checkGenericClassInNonGenericObjectType: false
|
||||||
|
checkOctaneCompatibility: false
|
||||||
|
noModelMake: true
|
||||||
|
noUnnecessaryCollectionCall: true
|
||||||
|
noUnnecessaryCollectionCallOnly: []
|
||||||
|
noUnnecessaryCollectionCallExcept: []
|
||||||
|
databaseMigrationsPath: []
|
||||||
|
checkModelProperties: false
|
||||||
|
checkPhpDocMissingReturn: false
|
||||||
|
|
||||||
|
parametersSchema:
|
||||||
|
checkOctaneCompatibility: bool()
|
||||||
|
noModelMake: bool()
|
||||||
|
noUnnecessaryCollectionCall: bool()
|
||||||
|
noUnnecessaryCollectionCallOnly: listOf(string())
|
||||||
|
noUnnecessaryCollectionCallExcept: listOf(string())
|
||||||
|
databaseMigrationsPath: listOf(string())
|
||||||
|
checkModelProperties: bool()
|
||||||
|
|
||||||
|
conditionalTags:
|
||||||
|
NunoMaduro\Larastan\Rules\NoModelMakeRule:
|
||||||
|
phpstan.rules.rule: %noModelMake%
|
||||||
|
NunoMaduro\Larastan\Rules\NoUnnecessaryCollectionCallRule:
|
||||||
|
phpstan.rules.rule: %noUnnecessaryCollectionCall%
|
||||||
|
NunoMaduro\Larastan\Rules\OctaneCompatibilityRule:
|
||||||
|
phpstan.rules.rule: %checkOctaneCompatibility%
|
||||||
|
NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertyRule:
|
||||||
|
phpstan.rules.rule: %checkModelProperties%
|
||||||
|
NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertyStaticCallRule:
|
||||||
|
phpstan.rules.rule: %checkModelProperties%
|
||||||
|
|
||||||
|
services:
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\RelationForwardsCallsExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\ModelForwardsCallsExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\EloquentBuilderForwardsCallsExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\HigherOrderTapProxyExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\HigherOrderCollectionProxyExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\StorageMethodsClassReflectionExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\Extension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\ModelFactoryMethodsClassReflectionExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\RedirectResponseMethodsClassReflectionExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.methodsClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Properties\ModelAccessorExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.propertiesClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Properties\ModelPropertyExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.propertiesClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Properties\HigherOrderCollectionProxyPropertyExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.propertiesClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\RelationDynamicMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\ModelRelationsDynamicMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\HigherOrderTapProxyExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
arguments:
|
||||||
|
className: Illuminate\Contracts\Container\Container
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
arguments:
|
||||||
|
className: Illuminate\Container\Container
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
arguments:
|
||||||
|
className: Illuminate\Foundation\Application
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\ContainerArrayAccessDynamicMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
arguments:
|
||||||
|
className: Illuminate\Contracts\Foundation\Application
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Properties\ModelRelationsExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.propertiesClassReflectionExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\ModelFactoryDynamicStaticMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\ModelExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\AuthExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\GuardDynamicStaticMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\AuthManagerExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\GuardExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\RequestExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\EloquentBuilderExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\RelationFindExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\RelationCollectionExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\ModelFindExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\BuilderModelFindExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\TestCaseExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\CollectionMakeDynamicStaticMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Support\CollectionHelper
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\AuthExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\CollectExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\CookieExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\ResponseExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\RequestExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\RedirectExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\UrlExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\ViewExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\TransExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\ValidatorExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\CollectionFilterDynamicReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\AbortIfFunctionTypeSpecifyingExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||||
|
arguments:
|
||||||
|
methodName: 'abort'
|
||||||
|
negate: false
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\AbortIfFunctionTypeSpecifyingExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||||
|
arguments:
|
||||||
|
methodName: 'abort'
|
||||||
|
negate: true
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\AbortIfFunctionTypeSpecifyingExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||||
|
arguments:
|
||||||
|
methodName: throw
|
||||||
|
negate: false
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\AbortIfFunctionTypeSpecifyingExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.typeSpecifier.functionTypeSpecifyingExtension
|
||||||
|
arguments:
|
||||||
|
methodName: throw
|
||||||
|
negate: true
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\AppExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\ValueExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\Helpers\TapExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicFunctionReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\ReturnTypes\StorageDynamicStaticMethodReturnTypeExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.broker.dynamicStaticMethodReturnTypeExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\GenericEloquentCollectionTypeNodeResolverExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.phpDoc.typeNodeResolverExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\ViewStringTypeNodeResolverExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.phpDoc.typeNodeResolverExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\OctaneCompatibilityRule
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\NoModelMakeRule
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\NoUnnecessaryCollectionCallRule
|
||||||
|
arguments:
|
||||||
|
onlyMethods: %noUnnecessaryCollectionCallOnly%
|
||||||
|
excludeMethods: %noUnnecessaryCollectionCallExcept%
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertyRule
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertyStaticCallRule
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\GenericEloquentBuilderTypeNodeResolverExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.phpDoc.typeNodeResolverExtension
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\ModelProperty\ModelPropertyTypeNodeResolverExtension
|
||||||
|
tags:
|
||||||
|
- phpstan.phpDoc.typeNodeResolverExtension
|
||||||
|
arguments:
|
||||||
|
active: %checkModelProperties%
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Types\RelationParserHelper
|
||||||
|
arguments:
|
||||||
|
parser: @currentPhpVersionSimpleDirectParser
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Properties\MigrationHelper
|
||||||
|
arguments:
|
||||||
|
databaseMigrationPath: %databaseMigrationsPath%
|
||||||
|
parser: @currentPhpVersionSimpleDirectParser
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\ModelProperties\ModelPropertiesRuleHelper
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\ModelRuleHelper
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Methods\BuilderHelper
|
||||||
|
arguments:
|
||||||
|
checkProperties: %checkModelProperties%
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\RelationExistenceRule
|
||||||
|
tags:
|
||||||
|
- phpstan.rule
|
||||||
|
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\CheckDispatchArgumentTypesCompatibleWithClassConstructorRule
|
||||||
|
arguments:
|
||||||
|
dispatchableClass: Illuminate\Foundation\Bus\Dispatchable
|
||||||
|
tags:
|
||||||
|
- phpstan.rules.rule
|
||||||
|
-
|
||||||
|
class: NunoMaduro\Larastan\Rules\CheckDispatchArgumentTypesCompatibleWithClassConstructorRule
|
||||||
|
arguments:
|
||||||
|
dispatchableClass: Illuminate\Foundation\Events\Dispatchable
|
||||||
|
tags:
|
||||||
|
- phpstan.rules.rule
|
||||||
|
rules:
|
||||||
|
- NunoMaduro\Larastan\Rules\RelationExistenceRule
|
17
php-packages/phpstan/phpstan-baseline.neon
Normal file
17
php-packages/phpstan/phpstan-baseline.neon
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
parameters:
|
||||||
|
ignoreErrors:
|
||||||
|
# Remove this group below with larastan 2.0 (i.e Flarum 2.0)
|
||||||
|
- "#Relation '[A-z_-]+' is not found in [A-z\_]+ model.#"
|
||||||
|
- '#^Parameter \#1 \$query of method [A-z_<>\\]+\:\:union\(\) expects [A-z_<> .,|\\]+ given\.$#'
|
||||||
|
- '#^Parameter \#1 \$query of method [A-z_<>\\]+\:\:joinSub\(\) expects [A-z_<> .,|\\]+ given\.$#'
|
||||||
|
|
||||||
|
# We ignore this because resolve can either take a class name as the generic return type or just a binding name.
|
||||||
|
- "#Template type T of function resolve[()]{2} is not referenced in a parameter.#"
|
||||||
|
|
||||||
|
# We ignore new static errors because we want extensibility.
|
||||||
|
# @TODO: needs discussion.
|
||||||
|
- "#^Unsafe usage of new static[()]{2}.$#"
|
||||||
|
|
||||||
|
# ConnectionInterface lacks methods that exist in the implementation,
|
||||||
|
# yet we don't want to inject the implementation.
|
||||||
|
- '#^Call to an undefined method Illuminate\\Database\\ConnectionInterface\:\:[A-z0-9_]+\(\)\.$#'
|
|
@ -1,72 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Concerns;
|
|
||||||
|
|
||||||
use Illuminate\Container\Container;
|
|
||||||
use Illuminate\Contracts\Container\BindingResolutionException;
|
|
||||||
use Illuminate\Contracts\Container\Container as ContainerContract;
|
|
||||||
use Psr\Container\NotFoundExceptionInterface;
|
|
||||||
use ReflectionException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
trait HasContainer
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var ?\Illuminate\Contracts\Container\Container
|
|
||||||
*/
|
|
||||||
protected $container;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \Illuminate\Contracts\Container\Container $container
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setContainer(ContainerContract $container): void
|
|
||||||
{
|
|
||||||
$this->container = $container;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the current broker.
|
|
||||||
*
|
|
||||||
* @return \Illuminate\Contracts\Container\Container
|
|
||||||
*/
|
|
||||||
public function getContainer(): ContainerContract
|
|
||||||
{
|
|
||||||
return $this->container ?? Container::getInstance();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resolve the given type from the container.
|
|
||||||
*
|
|
||||||
* @param string $abstract
|
|
||||||
* @return mixed
|
|
||||||
*/
|
|
||||||
public function resolve(string $abstract)
|
|
||||||
{
|
|
||||||
$concrete = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
$concrete = $this->getContainer()
|
|
||||||
->make($abstract);
|
|
||||||
} catch (ReflectionException $exception) {
|
|
||||||
// ..
|
|
||||||
} catch (BindingResolutionException $exception) {
|
|
||||||
// ..
|
|
||||||
} catch (NotFoundExceptionInterface $exception) {
|
|
||||||
// ..
|
|
||||||
}
|
|
||||||
|
|
||||||
return $concrete;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Concerns;
|
|
||||||
|
|
||||||
use Illuminate\Config\Repository as ConfigRepository;
|
|
||||||
|
|
||||||
trait LoadsAuthModel
|
|
||||||
{
|
|
||||||
/** @phpstan-return class-string|null */
|
|
||||||
private function getAuthModel(ConfigRepository $config, ?string $guard = null): ?string
|
|
||||||
{
|
|
||||||
if (
|
|
||||||
($guard === null && ! ($guard = $config->get('auth.defaults.guard'))) ||
|
|
||||||
! ($provider = $config->get('auth.guards.'.$guard.'.provider')) ||
|
|
||||||
! ($authModel = $config->get('auth.providers.'.$provider.'.model'))
|
|
||||||
) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $authModel;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,96 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Contracts\Methods;
|
|
||||||
|
|
||||||
use Illuminate\Contracts\Container\Container as ContainerContract;
|
|
||||||
use PHPStan\Reflection\ClassReflection;
|
|
||||||
use PHPStan\Reflection\MethodReflection;
|
|
||||||
use PHPStan\Reflection\Php\PhpMethodReflectionFactory;
|
|
||||||
use PHPStan\Reflection\ReflectionProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
interface PassableContract
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param \Illuminate\Contracts\Container\Container $container
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setContainer(ContainerContract $container): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \PHPStan\Reflection\ClassReflection
|
|
||||||
*/
|
|
||||||
public function getClassReflection(): ClassReflection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \PHPStan\Reflection\ClassReflection $classReflection
|
|
||||||
* @return PassableContract
|
|
||||||
*/
|
|
||||||
public function setClassReflection(ClassReflection $classReflection): PassableContract;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getMethodName(): string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function hasFound(): bool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $class
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function searchOn(string $class): bool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \PHPStan\Reflection\MethodReflection
|
|
||||||
*
|
|
||||||
* @throws \LogicException
|
|
||||||
*/
|
|
||||||
public function getMethodReflection(): MethodReflection;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \PHPStan\Reflection\MethodReflection $methodReflection
|
|
||||||
*/
|
|
||||||
public function setMethodReflection(MethodReflection $methodReflection): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Declares that the provided method can be called statically.
|
|
||||||
*
|
|
||||||
* @param bool $staticAllowed
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setStaticAllowed(bool $staticAllowed): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the method can be called statically.
|
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function isStaticAllowed(): bool;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param class-string $class
|
|
||||||
* @param bool $staticAllowed
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function sendToPipeline(string $class, $staticAllowed = false): bool;
|
|
||||||
|
|
||||||
public function getReflectionProvider(): ReflectionProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return \PHPStan\Reflection\Php\PhpMethodReflectionFactory
|
|
||||||
*/
|
|
||||||
public function getMethodReflectionFactory(): PhpMethodReflectionFactory;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Contracts\Methods\Pipes;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Flarum\PHPStan\Contracts\Methods\PassableContract;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
interface PipeContract
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param \Flarum\PHPStan\Contracts\Methods\PassableContract $passable
|
|
||||||
* @param \Closure $next
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function handle(PassableContract $passable, Closure $next): void;
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Contracts\Types;
|
|
||||||
|
|
||||||
use PHPStan\Type\Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
interface PassableContract
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @return \PHPStan\Type\Type
|
|
||||||
*/
|
|
||||||
public function getType(): Type;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param \PHPStan\Type\Type $type
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function setType(Type $type): void;
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Contracts\Types\Pipes;
|
|
||||||
|
|
||||||
use Closure;
|
|
||||||
use Flarum\PHPStan\Contracts\Types\PassableContract;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
interface PipeContract
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @param \Flarum\PHPStan\Contracts\Types\PassableContract $passable
|
|
||||||
* @param \Closure $next
|
|
||||||
* @return void
|
|
||||||
*/
|
|
||||||
public function handle(PassableContract $passable, Closure $next): void;
|
|
||||||
}
|
|
|
@ -1,241 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Methods;
|
|
||||||
|
|
||||||
use Flarum\PHPStan\Reflection\AnnotationScopeMethodParameterReflection;
|
|
||||||
use Flarum\PHPStan\Reflection\AnnotationScopeMethodReflection;
|
|
||||||
use Flarum\PHPStan\Reflection\DynamicWhereParameterReflection;
|
|
||||||
use Flarum\PHPStan\Reflection\EloquentBuilderMethodReflection;
|
|
||||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
|
||||||
use Illuminate\Database\Query\Builder as QueryBuilder;
|
|
||||||
use Illuminate\Support\Str;
|
|
||||||
use PHPStan\Reflection\ClassReflection;
|
|
||||||
use PHPStan\Reflection\MethodReflection;
|
|
||||||
use PHPStan\Reflection\MissingMethodFromReflectionException;
|
|
||||||
use PHPStan\Reflection\ParametersAcceptorSelector;
|
|
||||||
use PHPStan\Reflection\ReflectionProvider;
|
|
||||||
use PHPStan\ShouldNotHappenException;
|
|
||||||
use PHPStan\TrinaryLogic;
|
|
||||||
use PHPStan\Type\Generic\GenericObjectType;
|
|
||||||
use PHPStan\Type\ObjectType;
|
|
||||||
use PHPStan\Type\Type;
|
|
||||||
use PHPStan\Type\VerbosityLevel;
|
|
||||||
|
|
||||||
class BuilderHelper
|
|
||||||
{
|
|
||||||
/** @var string[] */
|
|
||||||
public const MODEL_RETRIEVAL_METHODS = ['first', 'find', 'findMany', 'findOrFail', 'firstOrFail', 'sole'];
|
|
||||||
|
|
||||||
/** @var string[] */
|
|
||||||
public const MODEL_CREATION_METHODS = ['make', 'create', 'forceCreate', 'findOrNew', 'firstOrNew', 'updateOrCreate', 'firstOrCreate'];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The methods that should be returned from query builder.
|
|
||||||
*
|
|
||||||
* @var string[]
|
|
||||||
*/
|
|
||||||
public $passthru = [
|
|
||||||
'average', 'avg',
|
|
||||||
'count',
|
|
||||||
'dd', 'dump',
|
|
||||||
'doesntExist', 'exists',
|
|
||||||
'getBindings', 'getConnection', 'getGrammar',
|
|
||||||
'insert', 'insertGetId', 'insertOrIgnore', 'insertUsing',
|
|
||||||
'max', 'min',
|
|
||||||
'raw',
|
|
||||||
'sum',
|
|
||||||
'toSql',
|
|
||||||
];
|
|
||||||
|
|
||||||
/** @var ReflectionProvider */
|
|
||||||
private $reflectionProvider;
|
|
||||||
|
|
||||||
/** @var bool */
|
|
||||||
private $checkProperties;
|
|
||||||
|
|
||||||
public function __construct(ReflectionProvider $reflectionProvider, bool $checkProperties)
|
|
||||||
{
|
|
||||||
$this->reflectionProvider = $reflectionProvider;
|
|
||||||
$this->checkProperties = $checkProperties;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function dynamicWhere(
|
|
||||||
string $methodName,
|
|
||||||
Type $returnObject
|
|
||||||
): ?EloquentBuilderMethodReflection {
|
|
||||||
if (! Str::startsWith($methodName, 'where')) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($returnObject instanceof GenericObjectType && $this->checkProperties) {
|
|
||||||
$returnClassReflection = $returnObject->getClassReflection();
|
|
||||||
|
|
||||||
if ($returnClassReflection !== null) {
|
|
||||||
$modelType = $returnClassReflection->getActiveTemplateTypeMap()->getType('TModelClass');
|
|
||||||
|
|
||||||
if ($modelType === null) {
|
|
||||||
$modelType = $returnClassReflection->getActiveTemplateTypeMap()->getType('TRelatedModel');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($modelType !== null) {
|
|
||||||
$finder = substr($methodName, 5);
|
|
||||||
|
|
||||||
$segments = preg_split(
|
|
||||||
'/(And|Or)(?=[A-Z])/',
|
|
||||||
$finder,
|
|
||||||
-1,
|
|
||||||
PREG_SPLIT_DELIM_CAPTURE
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($segments !== false) {
|
|
||||||
$trinaryLogic = TrinaryLogic::createYes();
|
|
||||||
|
|
||||||
foreach ($segments as $segment) {
|
|
||||||
if ($segment !== 'And' && $segment !== 'Or') {
|
|
||||||
$trinaryLogic = $trinaryLogic->and($modelType->hasProperty(Str::snake($segment)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (! $trinaryLogic->yes()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$classReflection = $this->reflectionProvider->getClass(QueryBuilder::class);
|
|
||||||
|
|
||||||
$methodReflection = $classReflection->getNativeMethod('dynamicWhere');
|
|
||||||
|
|
||||||
return new EloquentBuilderMethodReflection(
|
|
||||||
$methodName,
|
|
||||||
$classReflection,
|
|
||||||
$methodReflection,
|
|
||||||
[new DynamicWhereParameterReflection],
|
|
||||||
$returnObject,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method mimics the `EloquentBuilder::__call` method.
|
|
||||||
* Does not handle the case where $methodName exists in `EloquentBuilder`,
|
|
||||||
* that should be checked by caller before calling this method.
|
|
||||||
*
|
|
||||||
* @param ClassReflection $eloquentBuilder Can be `EloquentBuilder` or a custom builder extending it.
|
|
||||||
* @param string $methodName
|
|
||||||
* @param ClassReflection $model
|
|
||||||
* @return MethodReflection|null
|
|
||||||
*
|
|
||||||
* @throws MissingMethodFromReflectionException
|
|
||||||
* @throws ShouldNotHappenException
|
|
||||||
*/
|
|
||||||
public function searchOnEloquentBuilder(ClassReflection $eloquentBuilder, string $methodName, ClassReflection $model): ?MethodReflection
|
|
||||||
{
|
|
||||||
// Check for local query scopes
|
|
||||||
if (array_key_exists('scope'.ucfirst($methodName), $model->getMethodTags())) {
|
|
||||||
$methodTag = $model->getMethodTags()['scope'.ucfirst($methodName)];
|
|
||||||
|
|
||||||
$parameters = [];
|
|
||||||
foreach ($methodTag->getParameters() as $parameterName => $parameterTag) {
|
|
||||||
$parameters[] = new AnnotationScopeMethodParameterReflection($parameterName, $parameterTag->getType(), $parameterTag->passedByReference(), $parameterTag->isOptional(), $parameterTag->isVariadic(), $parameterTag->getDefaultValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
// We shift the parameters,
|
|
||||||
// because first parameter is the Builder
|
|
||||||
array_shift($parameters);
|
|
||||||
|
|
||||||
return new EloquentBuilderMethodReflection(
|
|
||||||
'scope'.ucfirst($methodName),
|
|
||||||
$model,
|
|
||||||
new AnnotationScopeMethodReflection('scope'.ucfirst($methodName), $model, $methodTag->getReturnType(), $parameters, $methodTag->isStatic(), false),
|
|
||||||
$parameters,
|
|
||||||
$methodTag->getReturnType()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($model->hasNativeMethod('scope'.ucfirst($methodName))) {
|
|
||||||
$methodReflection = $model->getNativeMethod('scope'.ucfirst($methodName));
|
|
||||||
$parametersAcceptor = ParametersAcceptorSelector::selectSingle($methodReflection->getVariants());
|
|
||||||
|
|
||||||
$parameters = $parametersAcceptor->getParameters();
|
|
||||||
// We shift the parameters,
|
|
||||||
// because first parameter is the Builder
|
|
||||||
array_shift($parameters);
|
|
||||||
|
|
||||||
$returnType = $parametersAcceptor->getReturnType();
|
|
||||||
|
|
||||||
return new EloquentBuilderMethodReflection(
|
|
||||||
'scope'.ucfirst($methodName),
|
|
||||||
$methodReflection->getDeclaringClass(),
|
|
||||||
$methodReflection,
|
|
||||||
$parameters,
|
|
||||||
$returnType,
|
|
||||||
$parametersAcceptor->isVariadic()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
$queryBuilderReflection = $this->reflectionProvider->getClass(QueryBuilder::class);
|
|
||||||
|
|
||||||
if (in_array($methodName, $this->passthru, true)) {
|
|
||||||
return $queryBuilderReflection->getNativeMethod($methodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($queryBuilderReflection->hasNativeMethod($methodName)) {
|
|
||||||
return $queryBuilderReflection->getNativeMethod($methodName);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->dynamicWhere($methodName, new GenericObjectType($eloquentBuilder->getName(), [new ObjectType($model->getName())]));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param string $modelClassName
|
|
||||||
* @return string
|
|
||||||
*
|
|
||||||
* @throws MissingMethodFromReflectionException
|
|
||||||
* @throws ShouldNotHappenException
|
|
||||||
*/
|
|
||||||
public function determineBuilderName(string $modelClassName): string
|
|
||||||
{
|
|
||||||
$method = $this->reflectionProvider->getClass($modelClassName)->getNativeMethod('newEloquentBuilder');
|
|
||||||
|
|
||||||
$returnType = ParametersAcceptorSelector::selectSingle($method->getVariants())->getReturnType();
|
|
||||||
|
|
||||||
if (in_array(EloquentBuilder::class, $returnType->getReferencedClasses(), true)) {
|
|
||||||
return EloquentBuilder::class;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($returnType instanceof ObjectType) {
|
|
||||||
return $returnType->getClassName();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnType->describe(VerbosityLevel::value());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws MissingMethodFromReflectionException
|
|
||||||
* @throws ShouldNotHappenException
|
|
||||||
*/
|
|
||||||
public function determineCollectionClassName(string $modelClassName): string
|
|
||||||
{
|
|
||||||
$newCollectionMethod = $this->reflectionProvider->getClass($modelClassName)->getNativeMethod('newCollection');
|
|
||||||
|
|
||||||
$returnType = ParametersAcceptorSelector::selectSingle($newCollectionMethod->getVariants())->getReturnType();
|
|
||||||
|
|
||||||
if ($returnType instanceof ObjectType) {
|
|
||||||
return $returnType->getClassName();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $returnType->describe(VerbosityLevel::value());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,161 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Methods;
|
|
||||||
|
|
||||||
use Flarum\PHPStan\Reflection\EloquentBuilderMethodReflection;
|
|
||||||
use Illuminate\Database\Eloquent\Builder as EloquentBuilder;
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
|
||||||
use PHPStan\Analyser\OutOfClassScope;
|
|
||||||
use PHPStan\Reflection\ClassReflection;
|
|
||||||
use PHPStan\Reflection\MethodReflection;
|
|
||||||
use PHPStan\Reflection\MethodsClassReflectionExtension;
|
|
||||||
use PHPStan\Reflection\MissingMethodFromReflectionException;
|
|
||||||
use PHPStan\Reflection\ParametersAcceptorSelector;
|
|
||||||
use PHPStan\Reflection\ReflectionProvider;
|
|
||||||
use PHPStan\ShouldNotHappenException;
|
|
||||||
use PHPStan\Type\Generic\GenericObjectType;
|
|
||||||
use PHPStan\Type\Generic\TemplateMixedType;
|
|
||||||
use PHPStan\Type\Generic\TemplateObjectType;
|
|
||||||
use PHPStan\Type\ObjectType;
|
|
||||||
use PHPStan\Type\Type;
|
|
||||||
use PHPStan\Type\TypeWithClassName;
|
|
||||||
|
|
||||||
final class EloquentBuilderForwardsCallsExtension implements MethodsClassReflectionExtension
|
|
||||||
{
|
|
||||||
/** @var array<string, MethodReflection> */
|
|
||||||
private $cache = [];
|
|
||||||
|
|
||||||
/** @var BuilderHelper */
|
|
||||||
private $builderHelper;
|
|
||||||
|
|
||||||
/** @var ReflectionProvider */
|
|
||||||
private $reflectionProvider;
|
|
||||||
|
|
||||||
public function __construct(BuilderHelper $builderHelper, ReflectionProvider $reflectionProvider)
|
|
||||||
{
|
|
||||||
$this->builderHelper = $builderHelper;
|
|
||||||
$this->reflectionProvider = $reflectionProvider;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws ShouldNotHappenException
|
|
||||||
* @throws MissingMethodFromReflectionException
|
|
||||||
*/
|
|
||||||
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
|
|
||||||
{
|
|
||||||
if (array_key_exists($classReflection->getCacheKey().'-'.$methodName, $this->cache)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$methodReflection = $this->findMethod($classReflection, $methodName);
|
|
||||||
|
|
||||||
if ($methodReflection !== null && $classReflection->isGeneric()) {
|
|
||||||
$this->cache[$classReflection->getCacheKey().'-'.$methodName] = $methodReflection;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
|
|
||||||
{
|
|
||||||
return $this->cache[$classReflection->getCacheKey().'-'.$methodName];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws MissingMethodFromReflectionException
|
|
||||||
* @throws ShouldNotHappenException
|
|
||||||
*/
|
|
||||||
private function findMethod(ClassReflection $classReflection, string $methodName): ?MethodReflection
|
|
||||||
{
|
|
||||||
if ($classReflection->getName() !== EloquentBuilder::class && ! $classReflection->isSubclassOf(EloquentBuilder::class)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @var Type|TemplateMixedType|null $modelType */
|
|
||||||
$modelType = $classReflection->getActiveTemplateTypeMap()->getType('TModelClass');
|
|
||||||
|
|
||||||
// Generic type is not specified
|
|
||||||
if ($modelType === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($modelType instanceof TemplateObjectType) {
|
|
||||||
$modelType = $modelType->getBound();
|
|
||||||
|
|
||||||
if ($modelType->equals(new ObjectType(Model::class))) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($modelType instanceof TypeWithClassName) {
|
|
||||||
$modelReflection = $modelType->getClassReflection();
|
|
||||||
} else {
|
|
||||||
$modelReflection = $this->reflectionProvider->getClass(Model::class);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($modelReflection === null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$ref = $this->builderHelper->searchOnEloquentBuilder($classReflection, $methodName, $modelReflection);
|
|
||||||
|
|
||||||
if ($ref === null) {
|
|
||||||
// Special case for `SoftDeletes` trait
|
|
||||||
if (
|
|
||||||
in_array($methodName, ['withTrashed', 'onlyTrashed', 'withoutTrashed'], true) &&
|
|
||||||
in_array(SoftDeletes::class, array_keys($modelReflection->getTraits(true)))
|
|
||||||
) {
|
|
||||||
$ref = $this->reflectionProvider->getClass(SoftDeletes::class)->getMethod($methodName, new OutOfClassScope());
|
|
||||||
|
|
||||||
return new EloquentBuilderMethodReflection(
|
|
||||||
$methodName,
|
|
||||||
$classReflection,
|
|
||||||
$ref,
|
|
||||||
ParametersAcceptorSelector::selectSingle($ref->getVariants())->getParameters(),
|
|
||||||
new GenericObjectType($classReflection->getName(), [$modelType]),
|
|
||||||
ParametersAcceptorSelector::selectSingle($ref->getVariants())->isVariadic()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
$parametersAcceptor = ParametersAcceptorSelector::selectSingle($ref->getVariants());
|
|
||||||
|
|
||||||
if (in_array($methodName, $this->builderHelper->passthru, true)) {
|
|
||||||
$returnType = $parametersAcceptor->getReturnType();
|
|
||||||
|
|
||||||
return new EloquentBuilderMethodReflection(
|
|
||||||
$methodName,
|
|
||||||
$classReflection,
|
|
||||||
$ref,
|
|
||||||
$parametersAcceptor->getParameters(),
|
|
||||||
$returnType,
|
|
||||||
$parametersAcceptor->isVariadic()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returning custom reflection
|
|
||||||
// to ensure return type is always `EloquentBuilder<Model>`
|
|
||||||
return new EloquentBuilderMethodReflection(
|
|
||||||
$methodName,
|
|
||||||
$classReflection,
|
|
||||||
$ref,
|
|
||||||
$parametersAcceptor->getParameters(),
|
|
||||||
new GenericObjectType($classReflection->getName(), [$modelType]),
|
|
||||||
$parametersAcceptor->isVariadic()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Methods;
|
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Model;
|
|
||||||
use PHPStan\Reflection\ClassReflection;
|
|
||||||
use PHPStan\Reflection\MethodReflection;
|
|
||||||
use PHPStan\Reflection\MethodsClassReflectionExtension;
|
|
||||||
use PHPStan\Reflection\Php\PhpMethodReflectionFactory;
|
|
||||||
use PHPStan\Reflection\ReflectionProvider;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @internal
|
|
||||||
*/
|
|
||||||
final class Extension implements MethodsClassReflectionExtension
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @var Kernel
|
|
||||||
*/
|
|
||||||
private $kernel;
|
|
||||||
|
|
||||||
/** @var MethodReflection[] */
|
|
||||||
private $methodReflections = [];
|
|
||||||
|
|
||||||
public function __construct(PhpMethodReflectionFactory $methodReflectionFactory, ReflectionProvider $reflectionProvider, Kernel $kernel = null)
|
|
||||||
{
|
|
||||||
$this->kernel = $kernel ?? new Kernel($methodReflectionFactory, $reflectionProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
|
|
||||||
{
|
|
||||||
if ($classReflection->getName() === Model::class) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (array_key_exists($methodName.'-'.$classReflection->getName(), $this->methodReflections)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
$passable = $this->kernel->handle($classReflection, $methodName);
|
|
||||||
|
|
||||||
$found = $passable->hasFound();
|
|
||||||
|
|
||||||
if ($found) {
|
|
||||||
$this->methodReflections[$methodName.'-'.$classReflection->getName()] = $passable->getMethodReflection();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $found;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMethod(ClassReflection $classReflection, string $methodName): MethodReflection
|
|
||||||
{
|
|
||||||
return $this->methodReflections[$methodName.'-'.$classReflection->getName()];
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,149 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Methods;
|
|
||||||
|
|
||||||
use Flarum\PHPStan\Support\HigherOrderCollectionProxyHelper;
|
|
||||||
use PHPStan\Analyser\OutOfClassScope;
|
|
||||||
use PHPStan\Reflection\ClassReflection;
|
|
||||||
use PHPStan\Reflection\FunctionVariant;
|
|
||||||
use PHPStan\Reflection\MethodReflection;
|
|
||||||
use PHPStan\Reflection\MethodsClassReflectionExtension;
|
|
||||||
use PHPStan\Reflection\ParametersAcceptorSelector;
|
|
||||||
use PHPStan\TrinaryLogic;
|
|
||||||
use PHPStan\Type;
|
|
||||||
|
|
||||||
final class HigherOrderCollectionProxyExtension implements MethodsClassReflectionExtension
|
|
||||||
{
|
|
||||||
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
|
|
||||||
{
|
|
||||||
return HigherOrderCollectionProxyHelper::hasPropertyOrMethod($classReflection, $methodName, 'method');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMethod(
|
|
||||||
ClassReflection $classReflection,
|
|
||||||
string $methodName
|
|
||||||
): MethodReflection {
|
|
||||||
$activeTemplateTypeMap = $classReflection->getActiveTemplateTypeMap();
|
|
||||||
|
|
||||||
/** @var Type\Constant\ConstantStringType $methodType */
|
|
||||||
$methodType = $activeTemplateTypeMap->getType('T');
|
|
||||||
|
|
||||||
/** @var Type\ObjectType $valueType */
|
|
||||||
$valueType = $activeTemplateTypeMap->getType('TValue');
|
|
||||||
|
|
||||||
$modelMethodReflection = $valueType->getMethod($methodName, new OutOfClassScope());
|
|
||||||
|
|
||||||
$modelMethodReturnType = ParametersAcceptorSelector::selectSingle($modelMethodReflection->getVariants())->getReturnType();
|
|
||||||
|
|
||||||
$returnType = HigherOrderCollectionProxyHelper::determineReturnType($methodType->getValue(), $valueType, $modelMethodReturnType);
|
|
||||||
|
|
||||||
return new class($classReflection, $methodName, $modelMethodReflection, $returnType) implements MethodReflection {
|
|
||||||
/** @var ClassReflection */
|
|
||||||
private $classReflection;
|
|
||||||
|
|
||||||
/** @var string */
|
|
||||||
private $methodName;
|
|
||||||
|
|
||||||
/** @var MethodReflection */
|
|
||||||
private $modelMethodReflection;
|
|
||||||
|
|
||||||
/** @var Type\Type */
|
|
||||||
private $returnType;
|
|
||||||
|
|
||||||
public function __construct(ClassReflection $classReflection, string $methodName, MethodReflection $modelMethodReflection, Type\Type $returnType)
|
|
||||||
{
|
|
||||||
$this->classReflection = $classReflection;
|
|
||||||
$this->methodName = $methodName;
|
|
||||||
$this->modelMethodReflection = $modelMethodReflection;
|
|
||||||
$this->returnType = $returnType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDeclaringClass(): \PHPStan\Reflection\ClassReflection
|
|
||||||
{
|
|
||||||
return $this->classReflection;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isStatic(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isPrivate(): bool
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isPublic(): bool
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDocComment(): ?string
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getName(): string
|
|
||||||
{
|
|
||||||
return $this->methodName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPrototype(): \PHPStan\Reflection\ClassMemberReflection
|
|
||||||
{
|
|
||||||
return $this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getVariants(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
new FunctionVariant(
|
|
||||||
ParametersAcceptorSelector::selectSingle($this->modelMethodReflection->getVariants())->getTemplateTypeMap(),
|
|
||||||
ParametersAcceptorSelector::selectSingle($this->modelMethodReflection->getVariants())->getResolvedTemplateTypeMap(),
|
|
||||||
ParametersAcceptorSelector::selectSingle($this->modelMethodReflection->getVariants())->getParameters(),
|
|
||||||
ParametersAcceptorSelector::selectSingle($this->modelMethodReflection->getVariants())->isVariadic(),
|
|
||||||
$this->returnType
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isDeprecated(): TrinaryLogic
|
|
||||||
{
|
|
||||||
return TrinaryLogic::createNo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getDeprecatedDescription(): ?string
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isFinal(): TrinaryLogic
|
|
||||||
{
|
|
||||||
return TrinaryLogic::createNo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function isInternal(): TrinaryLogic
|
|
||||||
{
|
|
||||||
return TrinaryLogic::createNo();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getThrowType(): ?\PHPStan\Type\Type
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function hasSideEffects(): TrinaryLogic
|
|
||||||
{
|
|
||||||
return TrinaryLogic::createMaybe();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,56 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This file is part of Flarum.
|
|
||||||
*
|
|
||||||
* For detailed copyright and license information, please view the
|
|
||||||
* LICENSE file that was distributed with this source code.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Flarum\PHPStan\Methods;
|
|
||||||
|
|
||||||
use Illuminate\Support\HigherOrderTapProxy;
|
|
||||||
use PHPStan\Analyser\OutOfClassScope;
|
|
||||||
use PHPStan\Reflection\ClassReflection;
|
|
||||||
use PHPStan\Reflection\MethodReflection;
|
|
||||||
use PHPStan\Reflection\MethodsClassReflectionExtension;
|
|
||||||
use PHPStan\Type\ObjectType;
|
|
||||||
|
|
||||||
final class HigherOrderTapProxyExtension implements MethodsClassReflectionExtension
|
|
||||||
{
|
|
||||||
public function hasMethod(ClassReflection $classReflection, string $methodName): bool
|
|
||||||
{
|
|
||||||
if ($classReflection->getName() !== HigherOrderTapProxy::class) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$templateTypeMap = $classReflection->getActiveTemplateTypeMap();
|
|
||||||
|
|
||||||
$templateType = $templateTypeMap->getType('TClass');
|
|
||||||
|
|
||||||
if (! $templateType instanceof ObjectType) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($templateType->getClassReflection() === null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $templateType->hasMethod($methodName)->yes();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMethod(
|
|
||||||
ClassReflection $classReflection,
|
|
||||||
string $methodName
|
|
||||||
): MethodReflection {
|
|
||||||
/** @var ObjectType $templateType */
|
|
||||||
$templateType = $classReflection->getActiveTemplateTypeMap()->getType('TClass');
|
|
||||||
|
|
||||||
/** @var ClassReflection $reflection */
|
|
||||||
$reflection = $templateType->getClassReflection();
|
|
||||||
|
|
||||||
return $reflection->getMethod($methodName, new OutOfClassScope());
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user