phpstan and phpcs fixes

This commit is contained in:
Dennis Eichhorn 2022-03-29 16:41:17 +02:00
parent e2b842c29d
commit 9ae86275ff
26 changed files with 265 additions and 72 deletions

View File

@ -138,7 +138,7 @@ class PermissionAbstract implements \JsonSerializable
* @param null|string $app App App to check (null if all are acceptable)
* @param null|string $module Module Module to check (null if all are acceptable)
* @param null|string $from Provided by which module
* @param null|int $category Type (e.g. customer) (null if all are acceptable)
* @param null|int $category Category (e.g. customer) (null if all are acceptable)
* @param null|int $element (e.g. customer id) (null if all are acceptable)
* @param null|int $component (e.g. address) (null if all are acceptable)
* @param int $permission Permission to check
@ -159,7 +159,7 @@ class PermissionAbstract implements \JsonSerializable
$this->app = $app;
$this->module = $module;
$this->from = $from;
$this->category = $category;
$this->category = $category;
$this->element = $element;
$this->component = $component;
@ -469,7 +469,7 @@ class PermissionAbstract implements \JsonSerializable
* @param null|int $unit Unit Unit to check (null if all are acceptable)
* @param null|string $app App App to check (null if all are acceptable)
* @param null|string $module Module Module to check (null if all are acceptable)
* @param null|int $category Type (e.g. customer) (null if all are acceptable)
* @param null|int $category Category (e.g. customer) (null if all are acceptable)
* @param null|int $element (e.g. customer id) (null if all are acceptable)
* @param null|int $component (e.g. address) (null if all are acceptable)
*

View File

@ -87,10 +87,15 @@ final class TesseractOcr
*/
public function parseImage(string $image, array $languages = ['eng'], int $psm = 3, int $oem = 3) : string
{
$temp = \tempnam(\sys_get_temp_dir(), 'ocr_');
if ($temp === false) {
return '';
}
SystemUtils::runProc(
self::$bin,
$image . ' '
. ($temp = \tempnam(\sys_get_temp_dir(), 'ocr_'))
. $temp
. ' -c preserve_interword_spaces=1'
. ' --psm ' . $psm
. ' --oem ' . $oem
@ -98,6 +103,9 @@ final class TesseractOcr
);
$parsed = \file_get_contents($temp . '.txt');
if ($parsed === false) {
return '';
}
// @todo: auto flip image if x% of text are garbage words?

View File

@ -41,9 +41,9 @@ abstract class InstallerAbstract
/**
* Install app.
*
* @param ApplicationAbstract $app Application
* @param ApplicationInfo $info App info
* @param SettingsInterface $cfgHandler Settings/Configuration handler
* @param ApplicationAbstract $app Application
* @param ApplicationInfo $info App info
* @param SettingsInterface $cfgHandler Settings/Configuration handler
*
* @return void
*
@ -125,8 +125,8 @@ abstract class InstallerAbstract
/**
* Activate after install.
*
* @param ApplicationAbstract $app Application
* @param ApplicationInfo $info App info
* @param ApplicationAbstract $app Application
* @param ApplicationInfo $info App info
*
* @return void
*

View File

@ -42,8 +42,8 @@ abstract class StatusAbstract
/**
* Deactivate app.
*
* @param ApplicationAbstract $app Application
* @param ApplicationInfo $info Module info
* @param ApplicationAbstract $app Application
* @param ApplicationInfo $info Module info
*
* @return void
*

View File

@ -27,6 +27,23 @@ namespace phpOMS\Contract;
*/
interface SerializableInterface
{
/**
* Serialize object
*
* @return string
*
* @since 1.0.0
*/
public function serialize() : string;
/**
* Fill object with data
*
* @param mixed $data Date to unserialize
*
* @return void
*
* @since 1.0.0
*/
public function unserialize($data) : void;
}

View File

@ -611,7 +611,7 @@ class Grammar extends GrammarAbstract
return '';
}
$cols = '(';
$cols = '(';
for ($i = 0; $i < $count; ++$i) {
$cols .= $this->compileSystem($columns[$i]) . ', ';
}

View File

@ -65,7 +65,7 @@ final class Dispatcher implements DispatcherInterface
public function dispatch(array | string | \Closure $controller, ...$data) : array
{
$views = [];
$data = $data !== null ? \array_values($data) : null;
$data = $data !== null ? \array_values($data) : null;
if (\is_array($controller) && isset($controller['dest'])) {
if (!empty($controller['data'])) {

View File

@ -251,14 +251,14 @@ final class EventManager implements \Countable
foreach ($this->callbacks[$group]['callbacks'] as $func) {
if (\is_array($data)) {
$data[':triggerGroup'] ??= $group;
$data[':triggerId'] = $id;
$data[':triggerId'] = $id;
} else {
$data = [
$data,
];
$data[':triggerGroup'] ??= $group;
$data[':triggerId'] = $id;
$data[':triggerId'] = $id;
}
$this->dispatcher->dispatch($func, ...$data);

View File

@ -86,15 +86,19 @@ final class Kernel
$im = \imagecreatefromgif($inPath);
}
if ($im == false) {
return;
}
if (\count($kernel) === 3) {
\imageconvolution($im, $kernel, 1, 0);
} else {
// @todo: implement @see https://rosettacode.org/wiki/Image_convolution
// @todo: not working yet
$dim = [\imagesx($im), \imagesy($im)];
$dim = [\imagesx($im), \imagesy($im)];
$kDim = [\count($kernel[1]), \count($kernel)]; // @todo: is the order correct? mhh...
$kWidthRadius = NumericUtils::uRightShift($kDim[0], 1);
$kWidthRadius = NumericUtils::uRightShift($kDim[0], 1);
$kHeightRadius = NumericUtils::uRightShift($kDim[1], 1);
for ($i = $dim[0] - 1; $i >= 0; --$i) {

View File

@ -14,8 +14,6 @@ declare(strict_types=1);
namespace phpOMS\Image;
use phpOMS\Utils\ImageUtils;
/**
* Skew image
*
@ -29,10 +27,11 @@ final class Skew
/**
* Automatically rotate image based on projection profile
*
* @param string $inPath Binary input image (black/white)
* @param string $outPath Output image
* @param array $start Start coordinates for analysis (e.g. ignore top/border of image)
* @param array $end End coordinates for analysis (e.g. ignore bottom/border of image)
* @param string $inPath Binary input image (black/white)
* @param string $outPath Output image
* @param int $maxDegree Max degree to consider for rotation
* @param array $start Start coordinates for analysis (e.g. ignore top/border of image)
* @param array $end End coordinates for analysis (e.g. ignore bottom/border of image)
*/
public static function autoRotate(string $inPath, string $outPath, int $maxDegree = 45, array $start = [], array $end = []) : void
{
@ -45,6 +44,10 @@ final class Skew
$im = \imagecreatefromgif($inPath);
}
if ($im == false) {
return;
}
$dim = [\imagesx($im), \imagesy($im)];
$start = [\max(0, $start[0] ?? 0), \max(0, $start[1] ?? 0)];
@ -59,15 +62,15 @@ final class Skew
for ($i = $start[0]; $i < $end[0]; ++$i) {
for ($j = $start[1]; $j < $end[1]; ++$j) {
$imMatrix[$j - $start[1]][$i - $start[0]] = \imagecolorat($im, $i, $j) < 0.5 ? 1 : 0;
$avg += $imMatrix[$j - $start[1]][$i - $start[0]];
$avg += $imMatrix[$j - $start[1]][$i - $start[0]];
}
}
$avg /= $start[1] - $end[1];
$dimImMatrix = [\count($imMatrix), \count($imMatrix[0])];
$bestScore = 0;
$bestDegree = 0;
$bestScore = 0;
$bestDegree = 0;
for ($i = -$maxDegree; $i < $maxDegree; $i += 1) {
if ($i === 0) {
@ -75,7 +78,7 @@ final class Skew
}
$rotated = self::rotatePixelMatrix($imMatrix, $dimImMatrix, $i);
$hist = [];
$hist = [];
for ($j = 0; $j < $dimImMatrix[0]; ++$j) {
$hist[$j] = \array_sum($rotated[$j]);
@ -88,12 +91,15 @@ final class Skew
$score = \array_sum($hist);
if ($bestScore < $score) {
$bestScore = $score;
$bestScore = $score;
$bestDegree = $i;
}
}
$im = \imagerotate($im, $bestDegree, 1);
if ($im == false) {
return;
}
if (\strripos($outPath, 'png') !== false) {
\imagepng($im, $outPath);
@ -106,6 +112,17 @@ final class Skew
\imagedestroy($im);
}
/**
* Rotate the pixel matrix by a certain degree
*
* @param array $pixel Pixel matrix (0 index = y, 1 index = x)
* @param array $dim Matrix dimension (0 index = y, 1 index = x)
* @param int $deg Degree to rotate
*
* @return array
*
* @since 1.0.0
*/
public static function rotatePixelMatrix(array $pixel, array $dim, int $deg) : array
{
$rad = \deg2rad($deg);
@ -131,12 +148,24 @@ final class Skew
return $rotated;
}
/**
* Find the closes pixel based on floating points
*
* @param array $pixel Pixel matrix (0 index = y, 1 index = x)
* @param array $dim Matrix dimension (0 index = y, 1 index = x)
* @param float $x X coordinate
* @param float $y Y coordinate
*
* @return int
*
* @since 1.0.0
*/
private static function getNearestValue(array $pixel, array $dim, float $x, float $y) : int
{
$xLow = \min((int) $x, $dim[1] - 1);
$xLow = \min((int) $x, $dim[1] - 1);
$xHigh = \min((int) \ceil($x), $dim[1] - 1);
$yLow = \min((int) $y, $dim[0] - 1);
$yLow = \min((int) $y, $dim[0] - 1);
$yHigh = \min((int) \ceil($y), $dim[0] - 1);
$points = [

View File

@ -50,8 +50,15 @@ final class Thresholding
$im = \imagecreatefromgif($inPath);
}
if ($im == false) {
return;
}
$dim = [\imagesx($im), \imagesy($im)];
$out = \imagecreate($dim[0], $dim[1]);
if ($out == false) {
return;
}
$intImg = [[]];
for ($i = 0; $i < $dim[0]; ++$i) {
@ -59,6 +66,10 @@ final class Thresholding
for ($j = 0; $j < $dim[1]; ++$j) {
$rgb = \imagecolorat($im, $i, $j);
if ($rgb === false) {
$rgb = 0;
}
$sum += ImageUtils::lightness($rgb);
$intImg[$i][$j] = $i === 0 ? $sum : $intImg[$i - 1][$j] + $sum;
@ -71,6 +82,10 @@ final class Thresholding
$black = \imagecolorallocate($out, 0, 0, 0);
$white = \imagecolorallocate($out, 255, 255, 255);
if ($black === false || $white === false) {
return;
}
for ($i = 0; $i < $dim[0]; ++$i) {
for ($j = 0; $j < $dim[1]; ++$j) {
$x1 = \max(1, (int) ($i - $s / 2.0));
@ -82,7 +97,11 @@ final class Thresholding
$count = ($x2 - $x1) * ($y2 - $y1);
$sum = $intImg[$x2][$y2] - $intImg[$x2][$y1 - 1] - $intImg[$x1 - 1][$y2] + $intImg[$x1 - 1][$y1 - 1];
$rgb = \imagecolorat($im, $i, $j);
$rgb = \imagecolorat($im, $i, $j);
if ($rgb === false) {
$rgb = 0;
}
$brightness = ImageUtils::lightness($rgb);
$color = $brightness * $count <= ($sum * (100.0 - $t) / 100.0) ? $black : $white;

View File

@ -111,6 +111,9 @@ final class ConsoleRequest extends RequestAbstract
}
}
/**
* {@inheritdoc}
*/
public function hasData(string $key) : bool
{
$key = '-' . \mb_strtolower($key);

View File

@ -76,7 +76,7 @@ final class HttpRequest extends RequestAbstract
{
$this->header = new HttpHeader();
$this->header->l11n = $l11n ?? new Localization();
$this->uri = $uri ?? new HttpUri('');
$this->uri = $uri ?? new HttpUri('');
}
/**

View File

@ -267,9 +267,18 @@ abstract class RequestAbstract implements MessageInterface
* Get the origin request source (IPv4/IPv6)
*
* @return string
*
* @since 1.0.0
*/
abstract public function getOrigin() : string;
/**
* Get the route verb
*
* @return int
*
* @since 1.0.0
*/
abstract public function getRouteVerb() : int;
/**
@ -292,6 +301,15 @@ abstract class RequestAbstract implements MessageInterface
return $this->files;
}
/**
* Add file to request
*
* @param array $file File data to add (Array here means one file with multiple information e.g. name, path, size)
*
* @return void
*
* @since 1.0.0
*/
public function addFile(array $file) : void
{
$this->files[] = $file;

View File

@ -42,9 +42,9 @@ abstract class InstallerAbstract
/**
* Install module.
*
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
* @param SettingsInterface $cfgHandler Settings/Configuration handler
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
* @param SettingsInterface $cfgHandler Settings/Configuration handler
*
* @return void
*
@ -87,8 +87,8 @@ abstract class InstallerAbstract
/**
* Activate after install.
*
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
*
* @return void
*

View File

@ -46,8 +46,8 @@ abstract class StatusAbstract
/**
* Deactivate module.
*
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
*
* @return void
*
@ -176,8 +176,8 @@ abstract class StatusAbstract
/**
* Deactivate module.
*
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
*
* @return void
*

View File

@ -40,8 +40,8 @@ abstract class UninstallerAbstract
/**
* Install module.
*
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
*
* @return void
*
@ -57,8 +57,8 @@ abstract class UninstallerAbstract
/**
* Activate after install.
*
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
* @param ApplicationAbstract $app Application
* @param ModuleInfo $info Module info
*
* @return void
*

View File

@ -147,6 +147,13 @@ final class SystemUtils
return 'localhost.localdomain';
}
/**
* Execute a command
*
* @param string $executable Path or name of the executable
* @param string $cmd Command to execute
* @param bool $async Execute async
*/
public static function runProc(string $executable, string $cmd, bool $async = false) : array
{
if (\strtolower((string) \substr(\PHP_OS, 0, 3)) === 'win') {

View File

@ -119,7 +119,7 @@ final class Argument implements UriInterface
/**
* Uri query.
*
* @var array<string, mixed>
* @var array<int, mixed>
* @since 1.0.0
*/
private array $query = [];
@ -172,23 +172,17 @@ final class Argument implements UriInterface
// Handle no path information only data
$uriParts = \stripos($uriParts[0], '-') === 0 ? ['/', $uriParts[0]] : $uriParts;
$this->path = \array_shift($uriParts);
$this->path = \count($uriParts) === 0 ? '' : \array_shift($uriParts);
$this->pathElements = \explode('/', \ltrim($this->path, '/'));
$path = \array_slice($this->pathElements, $this->pathOffset);
$path = \array_slice($this->pathElements, $this->pathOffset);
$this->offsetPath = '/' . \implode('/', $path);
$this->setQuery(\implode(' ', $uriParts));
}
/**
* Set query from uri.
*
* @param string $uri Uri to parse
*
* @return void
*
* @since 1.0.0
* {@inheritdoc}
*/
public function setQuery(string $uri) : void
{
@ -250,7 +244,7 @@ final class Argument implements UriInterface
{
$this->pathOffset = $offset;
$path = \array_slice($this->pathElements, $this->pathOffset);
$path = \array_slice($this->pathElements, $this->pathOffset);
$this->offsetPath = '/' . \implode('/', $path);
}
@ -270,7 +264,7 @@ final class Argument implements UriInterface
$this->path = $path;
$this->pathElements = \explode('/', \ltrim($this->path, '/'));
$path = \array_slice($this->pathElements, $this->pathOffset);
$path = \array_slice($this->pathElements, $this->pathOffset);
$this->offsetPath = '/' . \implode('/', $path);
}

View File

@ -110,6 +110,14 @@ final class HttpUri implements UriInterface
*/
private string $path;
/**
* Uri path with offset.
*
* @var string
* @since 1.0.0
*/
private string $offsetPath = '';
/**
* Uri query.
*
@ -205,10 +213,10 @@ final class HttpUri implements UriInterface
$this->pathElements = \explode('/', \trim($this->path, '/'));
$path = \array_slice($this->pathElements, $this->pathOffset);
$path = \array_slice($this->pathElements, $this->pathOffset);
$this->offsetPath = '/' . \implode('/', $path);
$this->queryString = $url['query'] ?? '';
$this->queryString = $url['query'] ?? '';
if (!empty($this->queryString)) {
\parse_str($this->queryString, $this->query);
@ -283,7 +291,7 @@ final class HttpUri implements UriInterface
{
$this->pathOffset = $offset;
$path = \array_slice($this->pathElements, $this->pathOffset);
$path = \array_slice($this->pathElements, $this->pathOffset);
$this->offsetPath = '/' . \implode('/', $path);
}
@ -322,7 +330,7 @@ final class HttpUri implements UriInterface
$this->path = $path;
$this->pathElements = \explode('/', \ltrim($this->path, '/'));
$path = \array_slice($this->pathElements, $this->pathOffset);
$path = \array_slice($this->pathElements, $this->pathOffset);
$this->offsetPath = '/' . \implode('/', $path);
}
@ -363,6 +371,16 @@ final class HttpUri implements UriInterface
return $this->queryString;
}
/**
* {@inheritdoc}
*/
public function setQuery(string $uri) : void
{
\parse_str($uri, $this->query);
$this->query = \array_change_key_case($this->query, \CASE_LOWER);
}
/**
* {@inheritdoc}
*/

View File

@ -134,6 +134,17 @@ interface UriInterface
*/
public function getPathElements() : array;
/**
* Set query from uri.
*
* @param string $uri Uri to parse
*
* @return void
*
* @since 1.0.0
*/
public function setQuery(string $uri) : void;
/**
* Get query.
*
@ -148,7 +159,7 @@ interface UriInterface
/**
* Get query array.
*
* @return array<string, string>
* @return string[]
*
* @since 1.0.0
*/

View File

@ -53,6 +53,15 @@ final class ImageUtils
return (string) \base64_decode($img);
}
/**
* Calculate the lightness from an RGB value as integer
*
* @param int $rgb RGB value represented as integer
*
* @return float
*
* @since 1.0.0
*/
public static function lightness(int $rgb) : float
{
$sR = ($rgb >> 16) & 0xFF;
@ -62,6 +71,17 @@ final class ImageUtils
return self::lightnessFromRgb($sR, $sG, $sB);
}
/**
* Calculate lightess from rgb values
*
* @param int $r Red
* @param int $g Green
* @param int $b Blue
*
* @return float
*
* @since 1.0.0
*/
public static function lightnessFromRgb(int $r, int $g, int $b) : float
{
$vR = $r / 255.0;

View File

@ -60,10 +60,10 @@ final class NumericUtils
}
if ($a < 0) {
$a = ($a >> 1);
$a = ($a >> 1);
$a &= 0x7fffffff;
$a |= 0x40000000;
$a = ($a >> ($b - 1));
$a = ($a >> ($b - 1));
} else {
$a = ($a >> $b);
}

View File

@ -39,34 +39,47 @@ class PdfParser
*/
public static function pdf2text(string $path) : string
{
$text = '';
$text = '';
$tmpDir = \sys_get_temp_dir();
$out = \tempnam($tmpDir, 'pdf_');
if ($out === false) {
return '';
}
SystemUtils::runProc(
'/usr/bin/pdftotext', '-layout '
. \escapeshellarg($path) . ' '
. \escapeshellarg($out = \tempnam($tmpDir, 'pdf_'))
. \escapeshellarg($out)
);
$text = \file_get_contents($out);
\unlink($out);
if ($text === false) {
$text = '';
}
if (\strlen($text) < 256) {
$out = \tempnam($tmpDir, 'pdf_');
if ($out === false) {
return '';
}
SystemUtils::runProc(
'/usr/bin/pdftoppm',
'-jpeg -r 300 '
. \escapeshellarg($path) . ' '
. \escapeshellarg($out = \tempnam($tmpDir, 'pdf_'))
. \escapeshellarg($out)
);
$files = \glob($out . '*');
if ($files === false) {
return $text;
return $text === false ? '' : $text;
}
foreach ($files as $file) {
if (
!StringUtils::endsWith($file, '.jpg')
if (!StringUtils::endsWith($file, '.jpg')
&& !StringUtils::endsWith($file, '.png')
&& !StringUtils::endsWith($file, '.gif')
) {
@ -84,7 +97,7 @@ class PdfParser
. \escapeshellarg($file)
);
$ocr = new TesseractOcr();
$ocr = new TesseractOcr();
$text = $ocr->parseImage($file);
\unlink($file);

View File

@ -31,6 +31,10 @@ class Cron extends SchedulerAbstract
public function create(TaskAbstract $task) : void
{
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
if ($path === false) {
throw new \Exception();
}
$this->run('-l > ' . $path);
\file_put_contents($path, $task->__toString() . "\n", \FILE_APPEND);
$this->run($path);
@ -43,6 +47,10 @@ class Cron extends SchedulerAbstract
public function update(TaskAbstract $task) : void
{
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
if ($path === false) {
throw new \Exception();
}
$this->run('-l > ' . $path);
$new = '';
@ -82,6 +90,10 @@ class Cron extends SchedulerAbstract
public function deleteByName(string $name) : void
{
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
if ($path === false) {
throw new \Exception();
}
$this->run('-l > ' . $path);
$new = '';
@ -113,6 +125,10 @@ class Cron extends SchedulerAbstract
public function getAll() : array
{
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
if ($path === false) {
throw new \Exception();
}
$this->run('-l > ' . $path);
$jobs = [];
@ -152,6 +168,10 @@ class Cron extends SchedulerAbstract
public function getAllByName(string $name, bool $exact = true) : array
{
$path = \tempnam(\sys_get_temp_dir(), 'cron_');
if ($path === false) {
throw new \Exception();
}
$this->run('-l > ' . $path);
$jobs = [];

View File

@ -356,8 +356,20 @@ class View extends ViewAbstract
return $this->l11nManager->getDateTime($this->l11n, $datetime, $format);
}
/**
* Render user name based on format
*
* @param string $format Format used in printf
* @param array $names Names to render according to the format
*
* @return string
*
* @since 1.0.0
*/
public function renderUserName(string $format, array $names) : string
{
return \trim(\preg_replace('/\s+/', ' ', \sprintf($format, ...$names)));;
$name = \preg_replace('/\s+/', ' ', \sprintf($format, ...$names));
return $name === null ? '' : \trim($name);
}
}