Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

composer: Update PHPStan to 2.0 #1505

Merged
merged 9 commits into from
Nov 23, 2024
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"php-parallel-lint/php-parallel-lint": "^1.0",
"phpstan/phpstan": "^1.9",
"phpstan/phpstan": "^2.0",
"phpstan/phpstan-deprecation-rules": "^2.0",
"symfony/phpunit-bridge": "^7.0"
},
"license": "GPL-3.0",
Expand Down
61 changes: 54 additions & 7 deletions composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,6 @@ parameters:
typeAliases:
SpoutParameterInfo: 'array{title: string, type: spouts\Parameter::TYPE_*, default: string, required: bool, validation: array<spouts\Parameter::VALIDATION_*>, values?: array<string, string>}'
SpoutParameters: 'array<string, SpoutParameterInfo>'

includes:
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
2 changes: 1 addition & 1 deletion src/controllers/Index.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ public function home(): void {
* @return array{entries: array<array{title: string, strippedTitle: string, content: string, wordCount: int, lengthWithoutTags: int, datetime: string, updatetime: string, sourcetitle: string, tags: StringKeyedArray<array{backColor: string, foreColor: string}>}>, hasMore: bool} html with items
*/
private function loadItems(array $params, array $tags) {
$options = ItemOptions::fromUser($params);
$options = new ItemOptions($params);
$entries = [];
foreach ($this->itemsDao->get($options) as $item) {
$entries[] = $this->viewHelper->preprocessEntry($item, $this->tagsController, $tags, $options->search);
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/Items.php
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ public function listItems(): void {
$this->authentication->needsLoggedInOrPublicMode();

// parse params
$options = ItemOptions::fromUser($_GET);
$options = new ItemOptions($_GET);

// get items
$items = $this->itemsDao->get($options);
Expand Down
26 changes: 23 additions & 3 deletions src/controllers/Items/Sync.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,29 @@ public function sync(): void {
public function updateStatuses(): void {
$this->authentication->needsLoggedIn();

if (isset($_POST['updatedStatuses'])
&& is_array($_POST['updatedStatuses'])) {
$this->itemsDao->bulkStatusUpdate($_POST['updatedStatuses']);
if (isset($_POST['updatedStatuses'])) {
$updatedStatuses = $_POST['updatedStatuses'];
if (!is_array($updatedStatuses)) {
$this->view->jsonError(['updatedStatuses' => 'not an array']);
}

foreach ($updatedStatuses as $index => $status) {
if (!is_array($status)) {
$this->view->jsonError(["updatedStatuses[$index]" => 'not an array']);
}

if (!array_key_exists('id', $status)) {
$this->view->jsonError(["updatedStatuses[$index]" => 'missing id argument']);
}

$id = (int) $status['id'];
if ((string) $id !== $status['id']) {
$this->view->jsonError(["updatedStatuses[$index]['id']" => 'not a number']);
}
$status['id'] = $id;
}

$this->itemsDao->bulkStatusUpdate($updatedStatuses);
}

$this->sync();
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/Rss.php
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public function rss(): void {
$lastSourceId = 0;
$lastSourceName = '';

$options = ItemOptions::fromUser($_GET);
$options = new ItemOptions($_GET);

// get items
$newestEntryDate = null;
Expand Down
74 changes: 46 additions & 28 deletions src/daos/ItemOptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,96 +11,114 @@
*/
final class ItemOptions {
/** @readonly */
public ?int $offset = 0;
public ?int $offset;

/** @readonly */
public ?string $search = null;
public ?string $search;

/**
* Maximum number of items to fetch from the database (unbounded)
*
* @readonly
*/
public ?int $pageSize = null;
public ?int $pageSize;

/** @readonly */
public ?DateTime $fromDatetime = null;
public ?DateTime $fromDatetime;

/** @readonly */
public ?int $fromId = null;
public ?int $fromId;

/** @readonly */
public ?DateTime $updatedSince = null;
public ?DateTime $updatedSince;

/** @readonly */
public ?string $tag = null;
public ?string $tag;

/**
* @var 'starred'|'unread'|null
*
* @readonly
*/
public ?string $filter = null;
public ?string $filter;

/** @readonly */
public ?int $source = null;
public ?int $source;

/** @var int[] @readonly */
public array $extraIds = [];
/**
* @var int[]
*
* @readonly
*/
public array $extraIds;

/**
* Creates new ItemOptions object ensuring the values are proper types.
*
* @param array<string, mixed> $data
*
* @return static
*/
public static function fromUser(array $data): self {
$options = new static();

public function __construct(array $data) {
if (isset($data['offset']) && is_numeric($data['offset'])) {
$options->offset = (int) $data['offset'];
$this->offset = (int) $data['offset'];
} else {
$this->offset = 0;
}

if (isset($data['search']) && is_string($data['search']) && strlen($search = trim($data['search'])) > 0) {
$options->search = $search;
$this->search = $search;
} else {
$this->search = null;
}

if (isset($data['items']) && is_numeric($data['items'])) {
$options->pageSize = (int) $data['items'];
$this->pageSize = (int) $data['items'];
} else {
$this->pageSize = null;
}

if (isset($data['fromDatetime']) && is_string($data['fromDatetime']) && strlen($data['fromDatetime']) > 0) {
$options->fromDatetime = new DateTime($data['fromDatetime']);
$this->fromDatetime = new DateTime($data['fromDatetime']);
} else {
$this->fromDatetime = null;
}

if (isset($data['fromId']) && is_numeric($data['fromId'])) {
$options->fromId = (int) $data['fromId'];
$this->fromId = (int) $data['fromId'];
} else {
$this->fromId = null;
}

if (isset($data['updatedsince']) && is_string($data['updatedsince']) && strlen($data['updatedsince']) > 0) {
$options->updatedSince = new DateTime($data['updatedsince']);
$this->updatedSince = new DateTime($data['updatedsince']);
} else {
$this->updatedSince = null;
}

if (isset($data['tag']) && is_string($data['tag']) && strlen($tag = trim($data['tag'])) > 0) {
$options->tag = $tag;
$this->tag = $tag;
} else {
$this->tag = null;
}

if (isset($data['type']) && is_string($data['type']) && in_array($filter = trim($data['type']), ['starred', 'unread'], true)) {
$options->filter = $filter;
$this->filter = $filter;
} else {
$this->filter = null;
}

if (isset($data['source']) && is_numeric($data['source'])) {
$options->source = (int) $data['source'];
$this->source = (int) $data['source'];
} else {
$this->source = null;
}

if (isset($data['extraIds']) && is_array($data['extraIds'])) {
$options->extraIds = array_map(
$this->extraIds = array_map(
fn($val) => (int) $val,
$data['extraIds']
);
} else {
$this->extraIds = [];
}

return $options;
}
}
1 change: 1 addition & 0 deletions src/daos/Sources.php
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ public function validate(string $title, string $spout, array $params) {
}

$validation = $spout->params[$id]['validation'];
// @phpstan-ignore-next-line function.alreadyNarrowedType (User can create their own spouts so we cannot necessarily trust PHPDoc.)
if (!is_array($validation)) {
$validation = [$validation];
}
Expand Down
Loading