Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions .github/workflows/psalm.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
name: Static analysis

on: pull_request

concurrency:
group: psalm-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

permissions:
contents: read

jobs:
static-analysis:
runs-on: ubuntu-latest
strategy:
matrix:
php:
- "8.1"
- "8.2"
- "8.3"
- "8.4"

name: static-psalm-analysis
steps:
- name: Checkout
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
with:
persist-credentials: false

- name: Set up php${{ matrix.php }}
uses: shivammathur/setup-php@ec406be512d7077f68eed36e63f4d91bc006edc4 # v2.35.4
with:
php-version: ${{ matrix.php }}
coverage: none
ini-file: development
# Temporary workaround for missing pcntl_* in PHP 8.3
ini-values: disable_functions=

- name: Install dependencies
run: composer install

- name: Run coding standards check
run: vendor/bin/psalm --no-cache --threads=$(nproc) --output-format=github
2 changes: 2 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
"@composer bin all install --ansi",
"composer dump-autoload"
],
"psalm": "psalm --no-cache --threads=$(nproc)",
"psalm:update-baseline": "psalm --threads=$(nproc) --update-baseline --set-baseline=tests/psalm-baseline.xml",
"post-update-cmd": [
"composer dump-autoload"
],
Expand Down
25 changes: 25 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?xml version="1.0"?>
<psalm
errorBaseline="tests/psalm-baseline.xml"
errorLevel="5"
findUnusedBaselineEntry="true"
findUnusedCode="false"
resolveFromConfigFile="true"
phpVersion="8.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor-bin/psalm/vendor/vimeo/psalm/config.xsd"
>
<projectFiles>
<directory name="src" />
<ignoreFiles>
<directory name="vendor" />
</ignoreFiles>
</projectFiles>
<issueHandlers>
<LessSpecificReturnStatement errorLevel="error"/>
<LessSpecificReturnType errorLevel="error"/>
<LessSpecificImplementedReturnType errorLevel="error"/>
<MoreSpecificReturnType errorLevel="error"/>
</issueHandlers>
</psalm>
77 changes: 43 additions & 34 deletions src/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace mikehaertl\pdftk;

use mikehaertl\shellcommand\Command as BaseCommand;
use mikehaertl\tmp\File;
use Override;

/**
* Command
Expand All @@ -16,38 +18,35 @@
class Command extends BaseCommand
{
/**
* @var string the pdftk binary
* The pdftk binary
*/
protected $_command = 'pdftk';

/**
* @var array list of input files to process as array('name' => $filename,
* List of input files to process as array('name' => $filename,
* 'password' => $pw) indexed by handle
*/
protected $_files = array();
protected array $_files = array();

/**
* @var array list of command options, either strings or array with
* arguments to addArg()
* List of command options, either strings or array with arguments to addArg()
*/
protected $_options = array();
protected array $_options = array();

/**
* @var string the operation to perform
* The operation to perform
*/
protected $_operation;
protected ?string $_operation = null;

/**
* @var string|array operation arguments, e.g. a list of page ranges or a
* filename or tmp file instance
* Operation arguments, e.g. a list of page ranges or a filename or tmp file instance
*/
protected $_operationArgument = array();
protected string|array|File $_operationArgument = array();

/**
* @var bool whether to force escaping of the operation argument e.g. for
* filenames
* Whether to force escaping of the operation argument e.g. for filenames
*/
protected $_escapeOperationArgument = false;
protected bool $_escapeOperationArgument = false;

/**
* @param string $name the PDF file to add for processing
Expand All @@ -57,7 +56,7 @@ class Command extends BaseCommand
* @return Command the command instance for method chaining
* @throws \Exception
*/
public function addFile($name, $handle, $password = null)
public function addFile($name, $handle, $password = null): self
{
$this->checkExecutionStatus();
$file = array(
Expand All @@ -76,7 +75,7 @@ public function addFile($name, $handle, $password = null)
* use Command default setting.
* @return Command the command instance for method chaining
*/
public function addOption($option, $argument = null, $escape = null)
public function addOption($option, $argument = null, ?bool $escape = null): self
{
$this->_options[] = $argument === null ? $option : array($option, $argument, $escape);
return $this;
Expand All @@ -86,7 +85,7 @@ public function addOption($option, $argument = null, $escape = null)
* @param string $operation the operation to perform
* @return Command the command instance for method chaining
*/
public function setOperation($operation)
public function setOperation($operation): self
{
$this->checkExecutionStatus();
$this->_operation = $operation;
Expand All @@ -102,11 +101,11 @@ public function getOperation()
}

/**
* @param string $value the operation argument
* @param string|array $value the operation argument
* @param bool $escape whether to escape the operation argument
* @return Command the command instance for method chaining
*/
public function setOperationArgument($value, $escape = false)
public function setOperationArgument(string|array|File $value, bool $escape = false): self
{
$this->checkExecutionStatus();
$this->_operationArgument = $value;
Expand All @@ -118,7 +117,7 @@ public function setOperationArgument($value, $escape = false)
* @return string|array|null the current operation argument as string or
* array or null if none set
*/
public function getOperationArgument()
public function getOperationArgument(): string|array|null
{
// Typecast to string in case we have a File instance as argument
return is_array($this->_operationArgument) ? $this->_operationArgument : (string) $this->_operationArgument;
Expand All @@ -127,7 +126,7 @@ public function getOperationArgument()
/**
* @return int the number of files added to the command
*/
public function getFileCount()
public function getFileCount(): int
{
return count($this->_files);
}
Expand All @@ -144,17 +143,20 @@ public function getFileCount()
* only a single file was added.
* @param string|null $qualifier the page number qualifier, either 'even'
* or 'odd' or null for none
* @param string $rotation the rotation to apply to the pages.
* @param string|null $rotation the rotation to apply to the pages.
* @return Command the command instance for method chaining
*/
public function addPageRange($start, $end = null, $handle = null, $qualifier = null, $rotation = null)
{
public function addPageRange(
int|string|array $start,
int|string|null $end = null,
string|null $handle = null,
string|null $qualifier = null,
string|null $rotation = null,
) {
$this->checkExecutionStatus();
if (is_array($start)) {
if ($handle !== null) {
$start = array_map(function ($p) use ($handle) {
return $handle . $p;
}, $start);
$start = array_map(fn ($p) => $handle . $p, $start);
}
$range = implode(' ', $start);
} else {
Expand All @@ -164,6 +166,13 @@ public function addPageRange($start, $end = null, $handle = null, $qualifier = n
}
$range .= $qualifier . $rotation;
}
if (!is_array($this->_operationArgument)) {
if (!empty($this->_operationArgument)) {
$this->_operationArgument = array($this->_operationArgument);
} else {
$this->_operationArgument = array();
}
}
$this->_operationArgument[] = $range;
return $this;
}
Expand All @@ -173,6 +182,7 @@ public function addPageRange($start, $end = null, $handle = null, $qualifier = n
* null if none
* @return bool whether the command was executed successfully
*/
#[Override]
public function execute($filename = null)
{
$this->checkExecutionStatus();
Expand All @@ -185,7 +195,7 @@ public function execute($filename = null)
/**
* Process input PDF files and create respective command arguments
*/
protected function processInputFiles()
protected function processInputFiles(): void
{
$passwords = array();
foreach ($this->_files as $handle => $file) {
Expand All @@ -204,10 +214,11 @@ protected function processInputFiles()

/**
* Process options and create respective command arguments
*
* @param string|null $filename if provided an 'output' option will be
* added
*/
protected function processOptions($filename = null)
protected function processOptions($filename = null): void
{
// output must be first option after operation
if ($filename !== null) {
Expand All @@ -225,23 +236,21 @@ protected function processOptions($filename = null)
/**
* Process opearation and create respective command arguments
*/
protected function processOperation()
protected function processOperation(): void
{
if ($this->_operation !== null) {
$value = $this->_operationArgument ? $this->_operationArgument : null;
if ($value instanceof TmpFile) {
$value = (string) $value;
}
$this->addArg($this->_operation, $value, $this->_escapeOperationArgument);
}
}

/**
* Ensure that the command was not exectued yet. Throws exception
* otherwise.
*
* @throws \Exception
*/
protected function checkExecutionStatus()
protected function checkExecutionStatus(): void
{
if ($this->getExecuted()) {
throw new \Exception('Operation was already executed');
Expand Down
30 changes: 14 additions & 16 deletions src/DataFields.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,12 @@
* @author Ray Holland <raymondaholland+php-pdftk@gmail.com>
* @author Michael Härtl <haertl.mike@gmail.com>
* @license http://www.opensource.org/licenses/MIT
* @extends ArrayObject<string, mixed>
*/
class DataFields extends ArrayObject
{
private $_string;
private $_array;
private string $_string;
private array $_array;

/**
* DataFields constructor.
Expand All @@ -24,26 +25,23 @@ class DataFields extends ArrayObject
* @param int $flags
* @param string $iterator_class
*/
public function __construct($input = null, $flags = 0, $iterator_class = "ArrayIterator")
{
public function __construct(
?string $input = null,
int $flags = 0,
string $iterator_class = "ArrayIterator",
) {
$this->_string = $input ?: '';
$this->_array = self::parse($this->_string);

return parent::__construct($this->_array, $flags, $iterator_class);
parent::__construct($this->_array, $flags, $iterator_class);
}

/**
* @return string
*/
public function __toString()
public function __toString(): string
{
return $this->_string;
}

/**
* @return array
*/
public function __toArray()
public function __toArray(): array
{
return $this->_array;
}
Expand Down Expand Up @@ -78,7 +76,7 @@ public function __toArray()
* @param $input the string to parse
* @return array the parsed result
*/
public static function parse($input)
public static function parse(string $input): array
{
if (strncmp('---', $input, 3) === 0) {
// Split blocks only if '---' is followed by 'FieldType'
Expand All @@ -105,7 +103,7 @@ public static function parse($input)
* @param string $block the block to parse
* @return array the parsed block values indexed by respective names
*/
public static function parseBlock($block)
public static function parseBlock(string $block): array
{
$data = array();
$lines = preg_split("/(\r\n|\n|\r)/", trim($block));
Expand Down Expand Up @@ -156,7 +154,7 @@ public static function parseBlock($block)
* 'FieldValueDefault' can span multiple lines
* @return bool whether the value continues in line n + 1
*/
protected static function lineContinues($lines, $n, $key)
protected static function lineContinues(array $lines, int $n, string $key): bool
{
return
in_array($key, array('FieldValue', 'FieldValueDefault')) &&
Expand Down
9 changes: 7 additions & 2 deletions src/FdfFile.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,13 @@ class FdfFile extends File
* created. Autodetected if not provided.
* @param string|null $encoding of the data. Default is 'UTF-8'.
*/
public function __construct($data, $suffix = null, $prefix = null, $directory = null, $encoding = 'UTF-8')
{
public function __construct(
array $data,
?string $suffix = null,
?string $prefix = null,
?string $directory = null,
?string $encoding = 'UTF-8',
) {
if ($directory === null) {
$directory = self::getTempDir();
}
Expand Down
Loading
Loading