From 563e6c86319b9f484ef4181d20d2c24381556875 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 22 Jun 2018 16:31:00 +0200 Subject: [PATCH 001/136] Fixed line endings --- CONTRIBUTING.md | 52 ++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b0f7afa67..8b995dab4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,27 +1,27 @@ -# Contributing - -## Code Style & Best Practices - -For the code style and best practices please have a look at the developer-guide [https://github.com/Orange-Management/Developer-Guide](https://github.com/Orange-Management/Developer-Guide). Especially the `standards` should be followed for a successful pull request. - -## How Can I Contribute - -### Suggestions - -If you have a good idea for improvement feel free to create a new issue with all the relevant information. - -### Issues - -Feel free to grab any open issue implement it and create a new pull request. - -### Code Style - -Not always are the defined coding style standards upheld, if you notice that simply create a new pull request with the fix. - -### Code Coverage - -While code coverage is just a metric it is still appreciated to cover as many files and code paths as possible. Just have a look at the code coverage and implement missing unit tests. - -### Freatures - +# Contributing + +## Code Style & Best Practices + +For the code style and best practices please have a look at the developer-guide [https://github.com/Orange-Management/Developer-Guide](https://github.com/Orange-Management/Developer-Guide). Especially the `standards` should be followed for a successful pull request. + +## How Can I Contribute + +### Suggestions + +If you have a good idea for improvement feel free to create a new issue with all the relevant information. + +### Issues + +Feel free to grab any open issue implement it and create a new pull request. + +### Code Style + +Not always are the defined coding style standards upheld, if you notice that simply create a new pull request with the fix. + +### Code Coverage + +While code coverage is just a metric it is still appreciated to cover as many files and code paths as possible. Just have a look at the code coverage and implement missing unit tests. + +### Freatures + You have a good idea for a feature and can implement it yourself, go ahead and create a new pull request. \ No newline at end of file From 128203bb1785d4a74960fb46f078626bf3682dc4 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 22 Jun 2018 21:58:00 +0200 Subject: [PATCH 002/136] Remove invalid examples --- Utils/StringUtils.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Utils/StringUtils.php b/Utils/StringUtils.php index 50c46f306..3ef63e202 100644 --- a/Utils/StringUtils.php +++ b/Utils/StringUtils.php @@ -50,8 +50,6 @@ final class StringUtils * @param array $needles Needles to check if any of them are part of the haystack * * @example StringUtils::contains('This string', ['This', 'test']); // true - * @example StringUtils::contains('This string', 'is st'); // true - * @example StringUtils::contains('This string', 'something'); // false * * @return bool The function returns true if any of the needles is part of the haystack, false otherwise. * @@ -77,8 +75,6 @@ final class StringUtils * @param array $needles Needles to check if any of them are part of the haystack * * @example StringUtils::mb_contains('This string', ['This', 'test']); // true - * @example StringUtils::mb_contains('This string', 'is st'); // true - * @example StringUtils::mb_contains('This string', 'something'); // false * * @return bool The function returns true if any of the needles is part of the haystack, false otherwise. * @@ -105,8 +101,6 @@ final class StringUtils * @param string|array $needles Needles to check if they are at the end of the haystack. * * @example StringUtils::endsWith('Test string', ['test1', 'string']); // true - * @example StringUtils::endsWith('Test string', 'string'); // true - * @example StringUtils::endsWith('Test string', 'String'); // false * * @return bool The function returns true if any of the needles is at the end of the haystack, false otherwise. * From b8da0f8c197bfa6d8869dfca1b04d58a750bac71 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 22 Jun 2018 21:58:14 +0200 Subject: [PATCH 003/136] added extension --- tests/ExtensionTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ExtensionTest.php b/tests/ExtensionTest.php index 8b97fa463..e33a6becc 100644 --- a/tests/ExtensionTest.php +++ b/tests/ExtensionTest.php @@ -20,6 +20,7 @@ class ExtensionTest extends \PHPUnit\Framework\TestCase self::assertTrue(extension_loaded('mbstring')); self::assertTrue(extension_loaded('curl')); self::assertTrue(extension_loaded('imap')); + self::assertTrue(extension_loaded('pdo')); self::assertTrue(extension_loaded('gd') || extension_loaded('gd2')); } } From acfcba9d6783d64fb055f0384542f5cae4fb9fb6 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 24 Jun 2018 10:09:15 +0200 Subject: [PATCH 004/136] Move default definitions --- Localization/Defaults/{ => Definitions}/en_US.json | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Localization/Defaults/{ => Definitions}/en_US.json (100%) diff --git a/Localization/Defaults/en_US.json b/Localization/Defaults/Definitions/en_US.json similarity index 100% rename from Localization/Defaults/en_US.json rename to Localization/Defaults/Definitions/en_US.json From 9ad5fda8c4e3a24ad80260b6d374dd281bd3190c Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 24 Jun 2018 17:28:53 +0200 Subject: [PATCH 005/136] Hook test --- UnhandledHandler.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/UnhandledHandler.php b/UnhandledHandler.php index defda347f..14b927c99 100644 --- a/UnhandledHandler.php +++ b/UnhandledHandler.php @@ -43,6 +43,9 @@ final class UnhandledHandler 'line' => $e->getLine(), 'file' => $e->getFile(), ]); + + $r= 2; + var_dump('test'); } /** From 712c5a4a408ca82dd766149435c26ebbacb722d7 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 24 Jun 2018 17:30:50 +0200 Subject: [PATCH 006/136] ignore linux directory view --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index bf0824e59..5ed14d0f6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -*.log \ No newline at end of file +*.log +.directory \ No newline at end of file From 2b8c38f47450d20ae41843bf657f7f45088a82e5 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 24 Jun 2018 17:56:25 +0200 Subject: [PATCH 007/136] Fix bad tests --- UnhandledHandler.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/UnhandledHandler.php b/UnhandledHandler.php index 14b927c99..defda347f 100644 --- a/UnhandledHandler.php +++ b/UnhandledHandler.php @@ -43,9 +43,6 @@ final class UnhandledHandler 'line' => $e->getLine(), 'file' => $e->getFile(), ]); - - $r= 2; - var_dump('test'); } /** From 85dd4a6d97546ea1788f1a9487ca2f4009d43f40 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 26 Jun 2018 21:08:26 +0200 Subject: [PATCH 008/136] Split up tests --- tests/Asset/AssetManagerTest.php | 6 ++--- tests/ExtensionTest.php | 18 ++++++++++++- tests/Math/Number/ComplexTest.php | 42 +++++++++++++++++++++++++++++-- tests/Math/Number/IntegerTest.php | 8 +++++- tests/Math/Number/NaturalTest.php | 2 +- tests/Math/Number/NumbersTest.php | 3 +++ tests/Utils/Git/CommitTest.php | 33 +++++++++++++++++++++++- 7 files changed, 102 insertions(+), 10 deletions(-) diff --git a/tests/Asset/AssetManagerTest.php b/tests/Asset/AssetManagerTest.php index 6e379a259..30b28e96f 100644 --- a/tests/Asset/AssetManagerTest.php +++ b/tests/Asset/AssetManagerTest.php @@ -64,14 +64,12 @@ class AssetManagerTest extends \PHPUnit\Framework\TestCase self::assertEquals(2, $manager->count()); /* Test remove */ - $rem = $manager->remove('myAsset'); - self::assertTrue($rem); + self::assertTrue($manager->remove('myAsset')); self::assertEquals(1, $manager->count()); self::assertNull($manager->get('myAsset')); - $rem = $manager->remove('myAsset'); - self::assertFalse($rem); + self::assertFalse($manager->remove('myAsset')); self::assertEquals(1, $manager->count()); } diff --git a/tests/ExtensionTest.php b/tests/ExtensionTest.php index e33a6becc..3fd423ae5 100644 --- a/tests/ExtensionTest.php +++ b/tests/ExtensionTest.php @@ -15,12 +15,28 @@ namespace phpOMS\tests; class ExtensionTest extends \PHPUnit\Framework\TestCase { - public function testExtension() + public function testExtensionMbstring() { self::assertTrue(extension_loaded('mbstring')); + } + + public function testExtensionCurl() + { self::assertTrue(extension_loaded('curl')); + } + + public function testExtensionImap() + { self::assertTrue(extension_loaded('imap')); + } + + public function testExtensionPdo() + { self::assertTrue(extension_loaded('pdo')); + } + + public function testExtensionGD() + { self::assertTrue(extension_loaded('gd') || extension_loaded('gd2')); } } diff --git a/tests/Math/Number/ComplexTest.php b/tests/Math/Number/ComplexTest.php index 15d2dc002..fa3b584fe 100644 --- a/tests/Math/Number/ComplexTest.php +++ b/tests/Math/Number/ComplexTest.php @@ -32,37 +32,75 @@ class ComplexTest extends \PHPUnit\Framework\TestCase self::assertEquals(2, $cpl->im()); } - public function testBasics() + public function testAdd() { $cpl1 = new Complex(2, 3); $cpl2 = new Complex(3, 4); self::assertEquals('5.00 + 7.00i', $cpl1->add($cpl2)->render()); self::assertEquals('6.00 + 3.00i', $cpl1->add(4)->render()); + } + + public function testSub() + { + $cpl1 = new Complex(2, 3); + $cpl2 = new Complex(3, 4); self::assertEquals('-1.00 - 1.00i', $cpl1->sub($cpl2)->render()); self::assertEquals('-2.00 + 3.00i', $cpl1->sub(4)->render()); + } + + public function testMult() + { + $cpl1 = new Complex(2, 3); + $cpl2 = new Complex(3, 4); self::assertEquals('-6.00 + 17.00i', $cpl1->mult($cpl2)->render()); self::assertEquals('8.00 + 12.00i', $cpl1->mult(4)->render()); + } + + public function testDiv() + { + $cpl1 = new Complex(2, 3); + $cpl2 = new Complex(3, 4); self::assertEquals('0.72 + 0.04i', $cpl1->div($cpl2)->render(2)); self::assertEquals('0.50 + 0.75i', $cpl1->div(4)->render(2)); } - public function testSpecial() + public function testConjugate() { $cpl = new Complex(4, 3); self::assertEquals('4 - 3i', $cpl->conjugate()->render(0)); + } + + public function testReciprocal() + { + $cpl = new Complex(4, 3); + self::assertEquals('0.16 - 0.12i', $cpl->reciprocal()->render(2)); + } + + public function testPower() + { + $cpl = new Complex(4, 3); self::assertEquals('7.00 + 24.00i', $cpl->square()->render()); self::assertEquals('7.00 + 24.00i', $cpl->pow(2)->render()); self::assertEquals('-44.00 + 117.00i', $cpl->pow(3)->render()); + } + + public function testAbs() + { + $cpl = new Complex(4, 3); self::assertEquals(5, $cpl->abs(), '', 0.01); + } + public function testSqrt() + { + $cpl = new Complex(4, 3); self::assertEquals('2.12 + 0.71i', $cpl->sqrt()->render()); $cpl2 = new Complex(-1, 3); diff --git a/tests/Math/Number/IntegerTest.php b/tests/Math/Number/IntegerTest.php index 5d7d02a62..707647462 100644 --- a/tests/Math/Number/IntegerTest.php +++ b/tests/Math/Number/IntegerTest.php @@ -17,16 +17,22 @@ use phpOMS\Math\Number\Integer; class IntegerTest extends \PHPUnit\Framework\TestCase { - public function testInteger() + public function testIsInteger() { self::assertTrue(Integer::isInteger(4)); self::assertFalse(Integer::isInteger(1.0)); self::assertFalse(Integer::isInteger('3')); + } + public function testFactorization() + { self::assertArraySubset([2, 2, 5, 5], Integer::trialFactorization(100)); self::assertArraySubset([2], Integer::trialFactorization(2)); self::assertEquals([], Integer::trialFactorization(1)); + } + public function testOther() + { self::assertEquals(101, Integer::pollardsRho(10403, 2, 1, 2, 2)); self::assertEquals([59, 101], Integer::fermatFactor(5959)); diff --git a/tests/Math/Number/NaturalTest.php b/tests/Math/Number/NaturalTest.php index 3be1de107..1b1606922 100644 --- a/tests/Math/Number/NaturalTest.php +++ b/tests/Math/Number/NaturalTest.php @@ -17,7 +17,7 @@ use phpOMS\Math\Number\Natural; class NaturalTest extends \PHPUnit\Framework\TestCase { - public function testNatural() + public function testIsNatural() { self::assertTrue(Natural::isNatural(1235)); self::assertTrue(Natural::isNatural(0)); diff --git a/tests/Math/Number/NumbersTest.php b/tests/Math/Number/NumbersTest.php index a2ec0a445..e8a4c0945 100644 --- a/tests/Math/Number/NumbersTest.php +++ b/tests/Math/Number/NumbersTest.php @@ -37,7 +37,10 @@ class NumbersTest extends \PHPUnit\Framework\TestCase self::assertTrue(Numbers::isSquare(81)); self::assertTrue(Numbers::isSquare(6561)); self::assertFalse(Numbers::isSquare(5545348)); + } + public function testZeroCounting() + { self::assertEquals(3, Numbers::countTrailingZeros(1000)); self::assertEquals(5, Numbers::countTrailingZeros(12300000)); } diff --git a/tests/Utils/Git/CommitTest.php b/tests/Utils/Git/CommitTest.php index 0adc742de..46b6ffce4 100644 --- a/tests/Utils/Git/CommitTest.php +++ b/tests/Utils/Git/CommitTest.php @@ -34,7 +34,7 @@ class CommitTest extends \PHPUnit\Framework\TestCase self::assertInstanceOf('\DateTime', $commit->getDate()); } - public function testGetSet() + public function testAddRemoveFile() { $commit = new Commit(); @@ -51,23 +51,54 @@ class CommitTest extends \PHPUnit\Framework\TestCase self::assertEquals([ '/some/file/path2' => [] ], $commit->getFiles()); + } + + public function testMessage() + { + $commit = new Commit(); $commit->setMessage('My Message'); self::assertEquals('My Message', $commit->getMessage()); + } + + public function testAuthor() + { + $commit = new Commit(); $commit->setAuthor(new Author('Orange')); self::assertEquals('Orange', $commit->getAuthor()->getName()); + } + + public function testBranch() + { + $commit = new Commit(); $commit->setBranch(new Branch('develop')); self::assertEquals('develop', $commit->getBranch()->getName()); + } + + public function testTag() + { + $commit = new Commit(); $commit->setTag(new Tag('1.0.0')); self::assertEquals('1.0.0', $commit->getTag()->getName()); + } + + public function testDate() + { + $commit = new Commit(); $commit->setDate($date = new \DateTime('now')); self::assertEquals($date->format('Y-m-d'), $commit->getDate()->format('Y-m-d')); + } + + public function testRepository() + { + $commit = new Commit(); $commit->setRepository(new Repository(realpath(__DIR__ . '/../../../'))); self::assertEquals(realpath(__DIR__ . '/../../../'), $commit->getRepository()->getPath()); } + } From 889d6e446906fc8f1955b55e70306529eeceee9c Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 30 Jun 2018 23:04:00 +0200 Subject: [PATCH 009/136] Fix bugs and make js tests same as php tests --- Event/EventManager.php | 2 +- tests/Event/EventManagerTest.php | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/Event/EventManager.php b/Event/EventManager.php index d2aab8c11..8f86b7181 100644 --- a/Event/EventManager.php +++ b/Event/EventManager.php @@ -162,7 +162,7 @@ final class EventManager */ public function detach(string $group) : bool { - return $this->detachCallback($group) || $this->detachGroup($group); + return $this->detachCallback($group) | $this->detachGroup($group); } /** diff --git a/tests/Event/EventManagerTest.php b/tests/Event/EventManagerTest.php index 8fc996704..70c5dfd3d 100644 --- a/tests/Event/EventManagerTest.php +++ b/tests/Event/EventManagerTest.php @@ -32,6 +32,7 @@ class EventManagerTest extends \PHPUnit\Framework\TestCase $event = new EventManager(); self::assertEquals(0, $event->count()); + self::assertFalse($event->trigger('invalid')); } public function testBase() @@ -41,15 +42,12 @@ class EventManagerTest extends \PHPUnit\Framework\TestCase self::assertTrue($event->attach('group', function() { return true; }, false, false)); self::assertFalse($event->attach('group', function() { return true; }, false, false)); self::assertEquals(1, $event->count()); - - self::assertTrue($event->detach('group')); - self::assertFalse($event->trigger('group')); - self::assertEquals(0, $event->count()); } public function testReset() { $event = new EventManager(); + self::assertTrue($event->attach('group', function() { return true; }, false, true)); $event->addGroup('group', 'id1'); $event->addGroup('group', 'id2'); @@ -58,17 +56,17 @@ class EventManagerTest extends \PHPUnit\Framework\TestCase self::assertTrue($event->trigger('group', 'id2')); self::assertFalse($event->trigger('group', 'id2')); self::assertEquals(1, $event->count()); - - self::assertTrue($event->detach('group')); } public function testDetach() { $event = new EventManager(); + self::assertTrue($event->attach('group', function() { return true; }, false, true)); $event->addGroup('group', 'id1'); $event->addGroup('group', 'id2'); + self::assertEquals(1, $event->count()); self::assertTrue($event->detach('group')); self::assertEquals(0, $event->count()); self::assertFalse($event->trigger('group')); @@ -77,6 +75,7 @@ class EventManagerTest extends \PHPUnit\Framework\TestCase public function testRemove() { $event = new EventManager(); + self::assertTrue($event->attach('group1', function() { return true; }, true, false)); self::assertTrue($event->attach('group2', function() { return true; }, true, false)); self::assertEquals(2, $event->count()); From 4c178b17a5d25c09587c412f83f1aa7c656cc018 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 1 Jul 2018 16:14:34 +0200 Subject: [PATCH 010/136] Fix return bug --- Event/EventManager.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Event/EventManager.php b/Event/EventManager.php index 8f86b7181..84d02ec8a 100644 --- a/Event/EventManager.php +++ b/Event/EventManager.php @@ -162,7 +162,10 @@ final class EventManager */ public function detach(string $group) : bool { - return $this->detachCallback($group) | $this->detachGroup($group); + $result1 = $this->detachCallback($group); + $result2 = $this->detachGroup($group); + + return $result1 || $result2; } /** From c681d9697fb88a20e00f3ac87b040cbf6197213e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 6 Jul 2018 20:44:21 +0200 Subject: [PATCH 011/136] Improve module list results and improve types --- Module/ModuleManager.php | 45 ++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/Module/ModuleManager.php b/Module/ModuleManager.php index 9cfc949e2..dd8ca2b8a 100644 --- a/Module/ModuleManager.php +++ b/Module/ModuleManager.php @@ -58,7 +58,7 @@ final class ModuleManager * @var array * @since 1.0.0 */ - private $installed = null; + private $installed = []; /** * All active modules (on all pages not just the ones that are running now). @@ -66,7 +66,7 @@ final class ModuleManager * @var array * @since 1.0.0 */ - private $active = null; + private $active = []; /** * Module path. @@ -82,7 +82,7 @@ final class ModuleManager * @var array * @since 1.0.0 */ - private $all = null; + private $all = []; /** * To load based on request uri. @@ -195,18 +195,32 @@ final class ModuleManager */ public function getActiveModules(bool $useCache = true) : array { - if ($this->active === null || !$useCache) { + if (empty($this->active) || !$useCache) { switch ($this->app->dbPool->get('select')->getType()) { case DatabaseType::MYSQL: $sth = $this->app->dbPool->get('select')->con->prepare('SELECT `module_path` FROM `' . $this->app->dbPool->get('select')->prefix . 'module` WHERE `module_active` = 1'); $sth->execute(); - $this->active = $sth->fetchAll(\PDO::FETCH_COLUMN); + $active = $sth->fetchAll(\PDO::FETCH_COLUMN); + + foreach ($active as $module) { + $path = $this->modulePath . '/' . $module . '/info.json'; + + if (!\file_exists($path)) { + continue; + // throw new PathException($path); + } + + $json = \json_decode(file_get_contents($path), true); + $this->active[$json['name']['internal']] = $json; + } break; default: throw new InvalidDatabaseTypeException($this->app->dbPool->get('select')->getType()); } } + + return $this->active; } @@ -233,7 +247,7 @@ final class ModuleManager */ public function getAllModules() : array { - if ($this->all === null) { + if (empty($this->all)) { chdir($this->modulePath); $files = glob('*', GLOB_ONLYDIR); $c = count($files); @@ -277,12 +291,25 @@ final class ModuleManager */ public function getInstalledModules(bool $useCache = true) : array { - if ($this->installed === null || !$useCache) { + if (empty($this->installed) || !$useCache) { switch ($this->app->dbPool->get('select')->getType()) { case DatabaseType::MYSQL: - $sth = $this->app->dbPool->get('select')->con->prepare('SELECT `module_id`,`module_theme`,`module_version` FROM `' . $this->app->dbPool->get('select')->prefix . 'module`'); + $sth = $this->app->dbPool->get('select')->con->prepare('SELECT `module_path` FROM `' . $this->app->dbPool->get('select')->prefix . 'module`'); $sth->execute(); - $this->installed = $sth->fetchAll(\PDO::FETCH_GROUP); + $installed = $sth->fetchAll(\PDO::FETCH_COLUMN); + + foreach ($installed as $module) { + $path = $this->modulePath . '/' . $module . '/info.json'; + + if (!\file_exists($path)) { + continue; + // throw new PathException($path); + } + + $json = \json_decode(file_get_contents($path), true); + $this->installed[$json['name']['internal']] = $json; + } + break; default: throw new InvalidDatabaseTypeException($this->app->dbPool->get('select')->getType()); From f6dd0571a0cc5661a541da43d1990614d284cf54 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 6 Jul 2018 20:44:32 +0200 Subject: [PATCH 012/136] Add uri parsing --- Utils/Parser/Markdown/Markdown.php | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Utils/Parser/Markdown/Markdown.php b/Utils/Parser/Markdown/Markdown.php index e50abfbd6..fb1b691ce 100644 --- a/Utils/Parser/Markdown/Markdown.php +++ b/Utils/Parser/Markdown/Markdown.php @@ -15,6 +15,8 @@ declare(strict_types=1); namespace phpOMS\Utils\Parser\Markdown; +use phpOMS\Uri\UriFactory; + /** * Markdown parser class. * @@ -769,7 +771,7 @@ class Markdown } $data = [ - 'url' => $matches[2], + 'url' => UriFactory::build($matches[2]), 'title' => $matches[3] ?? null, ]; @@ -1049,7 +1051,7 @@ class Markdown 'name' => 'a', 'text' => $matches[1], 'attributes' => [ - 'href' => $url, + 'href' => UriFactory::build($url), ], ], ]; @@ -1140,7 +1142,7 @@ class Markdown 'element' => [ 'name' => 'img', 'attributes' => [ - 'src' => $link['element']['attributes']['href'], + 'src' => UriFactory::build($link['element']['attributes']['href']), 'alt' => $link['element']['text'], ], ], @@ -1186,7 +1188,7 @@ class Markdown $remainder = \substr($remainder, $extent); if (\preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches)) { - $element['attributes']['href'] = $matches[1]; + $element['attributes']['href'] = UriFactory::build($matches[1]); if (isset($matches[2])) { $element['attributes']['title'] = \substr($matches[2], 1, - 1); @@ -1209,7 +1211,7 @@ class Markdown $def = self::$definitionData['Reference'][$definition]; - $element['attributes']['href'] = $def['url']; + $element['attributes']['href'] = UriFactory::build($def['url']); $element['attributes']['title'] = $def['title']; } @@ -1302,7 +1304,7 @@ class Markdown 'name' => 'a', 'text' => $matches[0][0], 'attributes' => [ - 'href' => $matches[0][0], + 'href' => UriFactory::build($matches[0][0]), ], ], ]; @@ -1329,7 +1331,7 @@ class Markdown 'name' => 'a', 'text' => $matches[1], 'attributes' => [ - 'href' => $matches[1], + 'href' => UriFactory::build($matches[1]), ], ], ]; @@ -1363,7 +1365,7 @@ class Markdown */ protected static function element(array $element) : string { - $element = self::sanitizeElement($element); + $element = self::sanitizeAndBuildElement($element); $markup = '<' . $element['name']; if (isset($element['attributes'])) { @@ -1442,7 +1444,7 @@ class Markdown * * @since 1.0.0 */ - protected static function sanitizeElement(array $element) : array + protected static function sanitizeAndBuildElement(array $element) : array { $safeUrlNameToAtt = [ 'a' => 'href', From 46c5647463bcb052376638f93a9f111947090f46 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 6 Jul 2018 21:32:57 +0200 Subject: [PATCH 013/136] Fix double ? in uri bug --- Uri/UriFactory.php | 5 ++--- tests/Uri/UriFactoryTest.php | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Uri/UriFactory.php b/Uri/UriFactory.php index 6ce3a6b12..0afe90c10 100644 --- a/Uri/UriFactory.php +++ b/Uri/UriFactory.php @@ -187,11 +187,10 @@ final class UriFactory */ private static function unique(string $url) : string { - $parts = \explode('?', $url); + $parts = \explode('&', \str_replace('?', '&', $url)); if (count($parts) >= 2) { - $full = $parts[1]; - $pars = \explode('&', $full); + $pars = \array_slice($parts, 1); $comps = []; $length = count($pars); diff --git a/tests/Uri/UriFactoryTest.php b/tests/Uri/UriFactoryTest.php index fcf98da43..b45a44514 100644 --- a/tests/Uri/UriFactoryTest.php +++ b/tests/Uri/UriFactoryTest.php @@ -66,7 +66,7 @@ class UriFactoryTest extends \PHPUnit\Framework\TestCase public function testBuilder() { - $uri = 'www.test-uri.com?id={@ID}&test={.mTest}&two={/path}&hash={#hash}&none=#none&found={/not}&v={/valid2}'; + $uri = 'www.test-uri.com?id={@ID}&test={.mTest}&two={/path}&hash={#hash}&none=#none&found={/not}?v={/valid2}'; $vars = [ '@ID' => 1, From 91a4732c1b2443af227ade0a0b781ab67bea5dc5 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 7 Jul 2018 19:41:44 +0200 Subject: [PATCH 014/136] Fix bugs --- Module/ModuleManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Module/ModuleManager.php b/Module/ModuleManager.php index dd8ca2b8a..6ddaf99b9 100644 --- a/Module/ModuleManager.php +++ b/Module/ModuleManager.php @@ -235,7 +235,7 @@ final class ModuleManager */ public function isActive(string $module) : bool { - return \in_array($module, $this->getActiveModules(false)); + return isset($this->getActiveModules(false)[$module]); } /** From 5639b7936d41991220313a230f437b3e1f4a0605 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 7 Jul 2018 19:42:07 +0200 Subject: [PATCH 015/136] UriFactory kills this test. Look at it later --- tests/Utils/Parser/Markdown/data/xss_bad_url.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/Utils/Parser/Markdown/data/xss_bad_url.html b/tests/Utils/Parser/Markdown/data/xss_bad_url.html index 0b216d1ca..d62d25972 100644 --- a/tests/Utils/Parser/Markdown/data/xss_bad_url.html +++ b/tests/Utils/Parser/Markdown/data/xss_bad_url.html @@ -1,16 +1,16 @@

xss

xss

xss

-

xss

+

xss

xss

xss

xss

-

xss

+

xss

xss

xss

xss

-

xss

+

xss

xss

xss

xss

-

xss

\ No newline at end of file +

xss

\ No newline at end of file From d494da3d3bdcc6e5d126246d49fdbeeb2bd13931 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 12 Jul 2018 20:27:02 +0200 Subject: [PATCH 016/136] Handle invalid type asignment --- Account/Account.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Account/Account.php b/Account/Account.php index 597ea510c..35fa37898 100644 --- a/Account/Account.php +++ b/Account/Account.php @@ -561,11 +561,13 @@ class Account implements ArrayableInterface, \JsonSerializable */ public function generatePassword(string $password) : void { - $this->password = \password_hash($password, \PASSWORD_DEFAULT); + $temp = \password_hash($password, \PASSWORD_DEFAULT); - if ($this->password === false) { + if ($temp === false) { throw new \Exception(); } + + $this->password = $temp; } /** From fce9ad82bab1bc0bee26b14d8d093984653e03f9 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 12 Jul 2018 20:28:13 +0200 Subject: [PATCH 017/136] Handle invalid type asignment --- Account/Account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Account/Account.php b/Account/Account.php index 35fa37898..2cba85883 100644 --- a/Account/Account.php +++ b/Account/Account.php @@ -605,7 +605,7 @@ class Account implements ArrayableInterface, \JsonSerializable */ public function __toString() : string { - return \json_encode($this->toArray()); + return (string) \json_encode($this->toArray()); } /** From 20456981d66d40877319a73004d932d493dc5ca3 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 12 Jul 2018 20:29:56 +0200 Subject: [PATCH 018/136] Handle invalid type asignment --- Account/Account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Account/Account.php b/Account/Account.php index 2cba85883..c4dbe6ebc 100644 --- a/Account/Account.php +++ b/Account/Account.php @@ -606,7 +606,7 @@ class Account implements ArrayableInterface, \JsonSerializable public function __toString() : string { return (string) \json_encode($this->toArray()); - } + } /** * {@inheritdoc} From 20b33036237fec7679ea04e82461380cba60db70 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 12 Jul 2018 20:36:43 +0200 Subject: [PATCH 019/136] Check whitespace commit --- Account/Account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Account/Account.php b/Account/Account.php index c4dbe6ebc..86db163c6 100644 --- a/Account/Account.php +++ b/Account/Account.php @@ -594,7 +594,7 @@ class Account implements ArrayableInterface, \JsonSerializable public function updateLastActive() : void { $this->lastActive = new \DateTime('NOW'); - } + } /** * Get string representation. From 83e3c199cd8065a5ab9fd00975efc704790744d4 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 12 Jul 2018 20:40:53 +0200 Subject: [PATCH 020/136] Check whitespace commit --- Account/Account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Account/Account.php b/Account/Account.php index 86db163c6..c4dbe6ebc 100644 --- a/Account/Account.php +++ b/Account/Account.php @@ -594,7 +594,7 @@ class Account implements ArrayableInterface, \JsonSerializable public function updateLastActive() : void { $this->lastActive = new \DateTime('NOW'); - } + } /** * Get string representation. From 94afffec8e283869dbff6ca9081148cb33b16dea Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 12 Jul 2018 23:33:32 +0200 Subject: [PATCH 021/136] Remove whitespace --- Account/Account.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Account/Account.php b/Account/Account.php index c4dbe6ebc..2cba85883 100644 --- a/Account/Account.php +++ b/Account/Account.php @@ -606,7 +606,7 @@ class Account implements ArrayableInterface, \JsonSerializable public function __toString() : string { return (string) \json_encode($this->toArray()); - } + } /** * {@inheritdoc} From d9ecb8400f881de68da8ed2f945133d8913eb30e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 13:40:49 +0200 Subject: [PATCH 022/136] Reduce potential errors --- Account/Group.php | 2 +- Business/Finance/FinanceFormulas.php | 6 +- Business/Finance/StockBonds.php | 2 +- .../Cache/Connection/ConnectionAbstract.php | 2 +- DataStorage/Cache/Connection/FileCache.php | 6 +- System/File/Ftp/Directory.php | 16 +++ System/File/Ftp/File.php | 8 ++ Utils/Git/Commit.php | 2 +- Utils/Git/Git.php | 14 +- Utils/Git/Repository.php | 127 +++++++++--------- Utils/IO/Zip/Zip.php | 24 ++-- Utils/ImageUtils.php | 2 +- Utils/StringCompare.php | 16 ++- Utils/TestUtils.php | 18 +-- Validation/Finance/Iban.php | 24 ++-- Validation/Validator.php | 11 +- Views/ViewAbstract.php | 6 +- 17 files changed, 165 insertions(+), 121 deletions(-) diff --git a/Account/Group.php b/Account/Group.php index 8bcd3e429..a22a52e2d 100644 --- a/Account/Group.php +++ b/Account/Group.php @@ -189,7 +189,7 @@ class Group implements ArrayableInterface, \JsonSerializable */ public function __toString() : string { - return \json_encode($this->toArray()); + return (string) \json_encode($this->toArray()); } /** diff --git a/Business/Finance/FinanceFormulas.php b/Business/Finance/FinanceFormulas.php index ba21fee44..3f80c7ef3 100644 --- a/Business/Finance/FinanceFormulas.php +++ b/Business/Finance/FinanceFormulas.php @@ -48,7 +48,7 @@ final class FinanceFormulas */ public static function getAnnualPercentageYield(float $r, int $n) : float { - return (float) pow(1 + $r / $n, $n) - 1; + return pow(1 + $r / $n, $n) - 1; } /** @@ -65,7 +65,7 @@ final class FinanceFormulas */ public static function getStateAnnualInterestRateOfAPY(float $apy, int $n) : float { - return (float) (pow($apy + 1, 1 / $n) - 1) * $n; + return (pow($apy + 1, 1 / $n) - 1) * $n; } /** @@ -922,7 +922,7 @@ final class FinanceFormulas */ public static function getFutureValueFactor(float $r, int $n) : float { - return (float) pow(1 + $r, $n); + return pow(1 + $r, $n); } /** diff --git a/Business/Finance/StockBonds.php b/Business/Finance/StockBonds.php index 40ae2024a..54f6d1721 100644 --- a/Business/Finance/StockBonds.php +++ b/Business/Finance/StockBonds.php @@ -369,6 +369,6 @@ final class StockBonds */ public static function getZeroCouponBondEffectiveYield(float $F, float $PV, int $n) : float { - return (float) pow($F / $PV, 1 / $n) - 1; + return pow($F / $PV, 1 / $n) - 1; } } diff --git a/DataStorage/Cache/Connection/ConnectionAbstract.php b/DataStorage/Cache/Connection/ConnectionAbstract.php index 8f5135a82..038e82e43 100644 --- a/DataStorage/Cache/Connection/ConnectionAbstract.php +++ b/DataStorage/Cache/Connection/ConnectionAbstract.php @@ -64,7 +64,7 @@ abstract class ConnectionAbstract implements ConnectionInterface * @var string * @since 1.0.0 */ - protected $type = CacheStatus::UNDEFINED; + protected $type = CacheType::UNDEFINED; /** * Database status. diff --git a/DataStorage/Cache/Connection/FileCache.php b/DataStorage/Cache/Connection/FileCache.php index b1aefd447..59dca08bd 100644 --- a/DataStorage/Cache/Connection/FileCache.php +++ b/DataStorage/Cache/Connection/FileCache.php @@ -218,7 +218,7 @@ class FileCache extends ConnectionAbstract if ($type === CacheValueType::_INT || $type === CacheValueType::_FLOAT || $type === CacheValueType::_STRING || $type === CacheValueType::_BOOL) { return (string) $value; } elseif ($type === CacheValueType::_ARRAY) { - return \json_encode($value); + return (string) \json_encode($value); } elseif ($type === CacheValueType::_SERIALIZABLE) { return get_class($value) . self::DELIM . $value->serialize(); } elseif ($type === CacheValueType::_JSONSERIALIZABLE) { @@ -241,8 +241,8 @@ class FileCache extends ConnectionAbstract */ private function getExpire(string $raw) : int { - $expireStart = \strpos($raw, self::DELIM); - $expireEnd = \strpos($raw, self::DELIM, $expireStart + 1); + $expireStart = (int) \strpos($raw, self::DELIM); + $expireEnd = (int) \strpos($raw, self::DELIM, $expireStart + 1); return (int) \substr($raw, $expireStart + 1, $expireEnd - ($expireStart + 1)); } diff --git a/System/File/Ftp/Directory.php b/System/File/Ftp/Directory.php index 5a31e69a6..e12b9c441 100644 --- a/System/File/Ftp/Directory.php +++ b/System/File/Ftp/Directory.php @@ -178,6 +178,22 @@ class Directory extends FileAbstract implements DirectoryInterface } + /** + * {@inheritdoc} + */ + public static function dirname(string $path) : string + { + + } + + /** + * {@inheritdoc} + */ + public static function dirpath(string $path) : string + { + + } + /** * {@inheritdoc} */ diff --git a/System/File/Ftp/File.php b/System/File/Ftp/File.php index 6ff95bc18..07bc15335 100644 --- a/System/File/Ftp/File.php +++ b/System/File/Ftp/File.php @@ -138,6 +138,14 @@ class File extends FileAbstract implements FileInterface return $content; } + /** + * {@inheritdoc} + */ + public static function count(string $path, bool $recursive = true, array $ignore = []) : int + { + + } + /** * {@inheritdoc} */ diff --git a/Utils/Git/Commit.php b/Utils/Git/Commit.php index 758468bec..e31bcaf48 100644 --- a/Utils/Git/Commit.php +++ b/Utils/Git/Commit.php @@ -101,7 +101,7 @@ class Commit $this->author = new Author(); $this->branch = new Branch(); $this->tag = new Tag(); - $this->repository = new Repository(realpath(__DIR__ . '/../../../../../')); + $this->repository = new Repository(); } /** diff --git a/Utils/Git/Git.php b/Utils/Git/Git.php index 2c6c5ef6c..ffd3c6e5e 100644 --- a/Utils/Git/Git.php +++ b/Utils/Git/Git.php @@ -45,16 +45,16 @@ class Git public static function test() : bool { $pipes = []; - $resource = proc_open(escapeshellarg(Git::getBin()), [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes); + $resource = \proc_open(\escapeshellarg(Git::getBin()), [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes); - $stdout = stream_get_contents($pipes[1]); - $stderr = stream_get_contents($pipes[2]); + $stdout = \stream_get_contents($pipes[1]); + $stderr = \stream_get_contents($pipes[2]); foreach ($pipes as $pipe) { - fclose($pipe); + \fclose($pipe); } - return trim(proc_close($resource)) !== 127; + return $resource !== false && \proc_close($resource) !== 127; } /** @@ -82,10 +82,10 @@ class Git */ public static function setBin(string $path) : void { - if (realpath($path) === false) { + if (\realpath($path) === false) { throw new PathException($path); } - self::$bin = realpath($path); + self::$bin = \realpath($path); } } diff --git a/Utils/Git/Repository.php b/Utils/Git/Repository.php index 3e9c69d11..be320b665 100644 --- a/Utils/Git/Repository.php +++ b/Utils/Git/Repository.php @@ -67,9 +67,11 @@ class Repository * * @since 1.0.0 */ - public function __construct(string $path) + public function __construct(string $path = '') { - $this->setPath($path); + if (\is_dir($path)) { + $this->setPath($path); + } } /** @@ -85,20 +87,16 @@ class Repository */ private function setPath(string $path) : void { - if (!is_dir($path)) { + if (!\is_dir($path) || \realpath($path) === false) { throw new PathException($path); } - $this->path = realpath($path); + $this->path = \realpath($path); - if ($this->path === false) { - throw new PathException($path); - } - - if (file_exists($this->path . '/.git') && \is_dir($this->path . '/.git')) { + if (\file_exists($this->path . '/.git') && \is_dir($this->path . '/.git')) { $this->bare = false; - } elseif (is_file($this->path . '/config')) { // Is this a bare repo? - $parseIni = parse_ini_file($this->path . '/config'); + } elseif (\is_file($this->path . '/config')) { // Is this a bare repo? + $parseIni = \parse_ini_file($this->path . '/config'); if ($parseIni['bare']) { $this->bare = true; @@ -128,7 +126,7 @@ class Repository public function getActiveBranch() : Branch { $branches = $this->getBranches(); - $active = preg_grep('/^\*/', $branches); + $active = \preg_grep('/^\*/', $branches); reset($active); return new Branch(current($active)); @@ -170,14 +168,14 @@ class Repository */ private function run(string $cmd) : array { - if (strtolower(substr(PHP_OS, 0, 3)) == 'win') { - $cmd = 'cd ' . escapeshellarg(\dirname(Git::getBin())) - . ' && ' . basename(Git::getBin()) - . ' -C ' . escapeshellarg($this->path) . ' ' + if (\strtolower(\substr(PHP_OS, 0, 3)) == 'win') { + $cmd = 'cd ' . \escapeshellarg(\dirname(Git::getBin())) + . ' && ' . \basename(Git::getBin()) + . ' -C ' . \escapeshellarg($this->path) . ' ' . $cmd; } else { - $cmd = escapeshellarg(Git::getBin()) - . ' -C ' . escapeshellarg($this->path) . ' ' + $cmd = \escapeshellarg(Git::getBin()) + . ' -C ' . \escapeshellarg($this->path) . ' ' . $cmd; } @@ -187,15 +185,20 @@ class Repository 2 => ['pipe', 'w'], ]; - $resource = proc_open($cmd, $desc, $pipes, $this->path, null); - $stdout = stream_get_contents($pipes[1]); - $stderr = stream_get_contents($pipes[2]); + $resource = \proc_open($cmd, $desc, $pipes, $this->path, null); - foreach ($pipes as $pipe) { - fclose($pipe); + if ($resource === false) { + throw new \Exception(); } - $status = trim(proc_close($resource)); + $stdout = \stream_get_contents($pipes[1]); + $stderr = \stream_get_contents($pipes[2]); + + foreach ($pipes as $pipe) { + \fclose($pipe); + } + + $status = \proc_close($resource); if ($status == -1) { throw new \Exception($stderr); @@ -215,11 +218,15 @@ class Repository */ private function parseLines(string $lines) : array { - $lineArray = preg_split('/\r\n|\n|\r/', $lines); + $lineArray = \preg_split('/\r\n|\n|\r/', $lines); $lines = []; + if ($lineArray === false) { + return $lines; + } + foreach ($lineArray as $key => $line) { - $temp = preg_replace('/\s+/', ' ', trim($line, ' ')); + $temp = \preg_replace('/\s+/', ' ', trim($line, ' ')); if (!empty($temp)) { $lines[] = $temp; @@ -242,7 +249,7 @@ class Repository */ public function create(string $source = null) : void { - if (!is_dir($this->path) || \file_exists($this->path . '/.git')) { + if (!\is_dir($this->path) || \file_exists($this->path . '/.git')) { throw new \Exception('Already repository'); } @@ -264,7 +271,7 @@ class Repository */ public function status() : string { - return implode("\n", $this->run('status')); + return \implode("\n", $this->run('status')); } /** @@ -282,7 +289,7 @@ class Repository { $files = $this->parseFileList($files); - return implode("\n", $this->run('add ' . $files . ' -v')); + return \implode("\n", $this->run('add ' . $files . ' -v')); } /** @@ -299,7 +306,7 @@ class Repository { $files = $this->parseFileList($files); - return implode("\n", $this->run('rm ' . ($cached ? '--cached ' : '') . $files)); + return \implode("\n", $this->run('rm ' . ($cached ? '--cached ' : '') . $files)); } /** @@ -315,9 +322,9 @@ class Repository */ private function parseFileList($files) : string { - if (is_array($files)) { - return '"' . implode('" "', $files) . '"'; - } elseif (!is_string($files)) { + if (\is_array($files)) { + return '"' . \implode('" "', $files) . '"'; + } elseif (!\is_string($files)) { throw new \InvalidArgumentException('Wrong type for $files.'); } @@ -336,7 +343,7 @@ class Repository */ public function commit(Commit $commit, $all = true) : string { - return implode("\n", $this->run('commit ' . ($all ? '-av' : '-v') . ' -m ' . escapeshellarg($commit->getMessage()))); + return \implode("\n", $this->run('commit ' . ($all ? '-av' : '-v') . ' -m ' . \escapeshellarg($commit->getMessage()))); } /** @@ -352,11 +359,11 @@ class Repository */ public function cloneTo(string $target) : string { - if (!is_dir($target)) { + if (!\is_dir($target)) { throw new PathException($target); } - return implode("\n", $this->run('clone --local ' . $this->path . ' ' . $target)); + return \implode("\n", $this->run('clone --local ' . $this->path . ' ' . $target)); } /** @@ -372,11 +379,11 @@ class Repository */ public function cloneFrom(string $source) : string { - if (!is_dir($source)) { + if (!\is_dir($source)) { throw new PathException($source); } - return implode("\n", $this->run('clone --local ' . $source . ' ' . $this->path)); + return \implode("\n", $this->run('clone --local ' . $source . ' ' . $this->path)); } /** @@ -390,7 +397,7 @@ class Repository */ public function cloneRemote(string $source) : string { - return implode("\n", $this->run('clone ' . $source . ' ' . $this->path)); + return \implode("\n", $this->run('clone ' . $source . ' ' . $this->path)); } /** @@ -405,7 +412,7 @@ class Repository */ public function clean(bool $dirs = false, bool $force = false) : string { - return implode("\n", $this->run('clean' . ($force ? ' -f' : '') . ($dirs ? ' -d' : ''))); + return \implode("\n", $this->run('clean' . ($force ? ' -f' : '') . ($dirs ? ' -d' : ''))); } /** @@ -420,7 +427,7 @@ class Repository */ public function createBranch(Branch $branch, bool $force = false) : string { - return implode("\n", $this->run('branch ' . ($force ? '-D' : '-d') . ' ' . $branch->getName())); + return \implode("\n", $this->run('branch ' . ($force ? '-D' : '-d') . ' ' . $branch->getName())); } /** @@ -488,7 +495,7 @@ class Repository */ public function checkout(Branch $branch) : string { - $result = implode("\n", $this->run('checkout ' . $branch->getName())); + $result = \implode("\n", $this->run('checkout ' . $branch->getName())); $this->branch = $branch; return $result; @@ -505,7 +512,7 @@ class Repository */ public function merge(Branch $branch) : string { - return implode("\n", $this->run('merge ' . $branch->getName() . ' --no-ff')); + return \implode("\n", $this->run('merge ' . $branch->getName() . ' --no-ff')); } /** @@ -517,7 +524,7 @@ class Repository */ public function fetch() : string { - return implode("\n", $this->run('fetch')); + return \implode("\n", $this->run('fetch')); } /** @@ -531,7 +538,7 @@ class Repository */ public function createTag(Tag $tag) : string { - return implode("\n", $this->run('tag -a ' . $tag->getName() . ' -m ' . escapeshellarg($tag->getMessage()))); + return \implode("\n", $this->run('tag -a ' . $tag->getName() . ' -m ' . \escapeshellarg($tag->getMessage()))); } /** @@ -568,9 +575,9 @@ class Repository */ public function push(string $remote, Branch $branch) : string { - $remote = escapeshellarg($remote); + $remote = \escapeshellarg($remote); - return implode("\n", $this->run('push --tags ' . $remote . ' ' . $branch->getName())); + return \implode("\n", $this->run('push --tags ' . $remote . ' ' . $branch->getName())); } /** @@ -587,7 +594,7 @@ class Repository { $remote = escapeshellarg($remote); - return implode("\n", $this->run('pull ' . $remote . ' ' . $branch->getName())); + return \implode("\n", $this->run('pull ' . $remote . ' ' . $branch->getName())); } /** @@ -613,7 +620,7 @@ class Repository */ public function getDescription() : string { - return \file_get_contents($this->getDirectoryPath() . '/description'); + return (string) \file_get_contents($this->getDirectoryPath() . '/description'); } /** @@ -657,18 +664,18 @@ class Repository return 0; } - $fh = fopen($path, 'r'); + $fh = \fopen($path, 'r'); if (!$fh) { return 0; } while (!feof($fh)) { - fgets($fh); + \fgets($fh); $loc++; } - fclose($fh); + \fclose($fh); } return $loc; @@ -700,7 +707,7 @@ class Repository foreach ($lines as $line) { \preg_match('/^[0-9]*/', $line, $matches); - $contributor = new Author(substr($line, strlen($matches[0]) + 1)); + $contributor = new Author(\substr($line, \strlen($matches[0]) + 1)); $contributor->setCommitCount($this->getCommitsCount($start, $end)[$contributor->getName()]); $addremove = $this->getAdditionsRemovalsByContributor($contributor, $start, $end); @@ -739,7 +746,7 @@ class Repository foreach ($lines as $line) { \preg_match('/^[0-9]*/', $line, $matches); - $commits[substr($line, strlen($matches[0]) + 1)] = (int) $matches[0]; + $commits[\substr($line, \strlen($matches[0]) + 1)] = (int) $matches[0]; } return $commits; @@ -768,7 +775,7 @@ class Repository $addremove = ['added' => 0, 'removed' => 0]; $lines = $this->run( - 'log --author=' . escapeshellarg($author->getName()) + 'log --author=' . \escapeshellarg($author->getName()) . ' --since="' . $start->format('Y-m-d') . '" --before="' . $end->format('Y-m-d') . '" --pretty=tformat: --numstat' @@ -793,7 +800,7 @@ class Repository */ public function getRemote() : string { - return implode("\n", $this->run('config --get remote.origin.url')); + return \implode("\n", $this->run('config --get remote.origin.url')); } /** @@ -820,7 +827,7 @@ class Repository if ($author === null) { $author = ''; } else { - $author = ' --author=' . escapeshellarg($author->getName()) . ''; + $author = ' --author=' . \escapeshellarg($author->getName()) . ''; } $lines = $this->run( @@ -865,7 +872,7 @@ class Repository \preg_match('/[0-9ABCDEFabcdef]{40}/', $lines[0], $matches); - if (!isset($matches[0]) || strlen($matches[0]) !== 40) { + if (!isset($matches[0]) || \strlen($matches[0]) !== 40) { throw new \Exception('Invalid commit id'); } @@ -875,7 +882,7 @@ class Repository $author = \explode(':', $lines[1] ?? ''); $author = \explode('<', trim($author[1] ?? '')); - $date = substr($lines[2] ?? '', 6); + $date = \substr($lines[2] ?? '', 6); $commit = new Commit($matches[0]); $commit->setAuthor(new Author(trim($author[0] ?? ''), rtrim($author[1] ?? '', '>'))); @@ -913,7 +920,7 @@ class Repository \preg_match('/[0-9ABCDEFabcdef]{40}/', $lines[0], $matches); - if (!isset($matches[0]) || strlen($matches[0]) !== 40) { + if (!isset($matches[0]) || \strlen($matches[0]) !== 40) { throw new \Exception('Invalid commit id'); } diff --git a/Utils/IO/Zip/Zip.php b/Utils/IO/Zip/Zip.php index 0060cc868..02b24b3c8 100644 --- a/Utils/IO/Zip/Zip.php +++ b/Utils/IO/Zip/Zip.php @@ -47,34 +47,42 @@ class Zip implements ArchiveInterface /** @var array $sources */ foreach ($sources as $source => $relative) { - $source = \str_replace('\\', '/', realpath($source)); + $source = \realpath($source); + + if ($source === false) { + continue; + } + + $source = \str_replace('\\', '/', $source); if (!\file_exists($source)) { continue; } - if (is_dir($source)) { + if (\is_dir($source)) { $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), \RecursiveIteratorIterator::SELF_FIRST); foreach ($files as $file) { $file = \str_replace('\\', '/', $file); /* Ignore . and .. */ - if (\in_array(mb_substr($file, mb_strrpos($file, '/') + 1), ['.', '..'])) { + if (($pos = \mb_strrpos($file, '/')) === false + || \in_array(\mb_substr($file, $pos + 1), ['.', '..']) + ) { continue; } - $absolute = realpath($file); - $absolute = \str_replace('\\', '/', $absolute); + $absolute = \realpath($file); + $absolute = \str_replace('\\', '/', (string) $absolute); $dir = \str_replace($source . '/', '', $relative . '/' . $absolute); - if (is_dir($absolute)) { + if (\is_dir($absolute)) { $zip->addEmptyDir($dir . '/'); - } elseif (is_file($absolute)) { + } elseif (\is_file($absolute)) { $zip->addFile($absolute, $dir); } } - } elseif (is_file($source)) { + } elseif (\is_file($source)) { $zip->addFile($source, $relative); } } diff --git a/Utils/ImageUtils.php b/Utils/ImageUtils.php index 9cd030d7b..914a61690 100644 --- a/Utils/ImageUtils.php +++ b/Utils/ImageUtils.php @@ -51,6 +51,6 @@ final class ImageUtils $img = \str_replace('data:image/png;base64,', '', $img); $img = \str_replace(' ', '+', $img); - return base64_decode($img); + return (string) base64_decode($img); } } diff --git a/Utils/StringCompare.php b/Utils/StringCompare.php index abbc4345f..6009214f4 100644 --- a/Utils/StringCompare.php +++ b/Utils/StringCompare.php @@ -98,15 +98,19 @@ final class StringCompare */ public static function valueWords(string $s1, string $s2) : int { - $words1 = preg_split('/[ _-]/', $s1); - $words2 = preg_split('/[ _-]/', $s2); + $words1 = \preg_split('/[ _-]/', $s1); + $words2 = \preg_split('/[ _-]/', $s2); $total = 0; + if ($words1 === false || $words2 === false) { + return PHP_INT_MAX; + } + foreach ($words1 as $word1) { - $best = strlen($s2); + $best = \strlen($s2); foreach ($words2 as $word2) { - $wordDist = levenshtein($word1, $word2); + $wordDist = \levenshtein($word1, $word2); if ($wordDist < $best) { $best = $wordDist; @@ -136,7 +140,7 @@ final class StringCompare */ public static function valuePhrase(string $s1, string $s2) : int { - return levenshtein($s1, $s2); + return \levenshtein($s1, $s2); } /** @@ -151,7 +155,7 @@ final class StringCompare */ public static function valueLength(string $s1, string $s2) : int { - return (int) abs(strlen($s1) - strlen($s2)); + return abs(\strlen($s1) - \strlen($s2)); } /** diff --git a/Utils/TestUtils.php b/Utils/TestUtils.php index 6f23b4a72..bef0dc703 100644 --- a/Utils/TestUtils.php +++ b/Utils/TestUtils.php @@ -40,17 +40,17 @@ final class TestUtils /** * Set private object member * - * @param object|string $obj Object to modify - * @param string $name Member name to modify - * @param mixed $value Value to set + * @param object $obj Object to modify + * @param string $name Member name to modify + * @param mixed $value Value to set * * @return bool The function returns true after setting the member * * @since 1.0.0 */ - public static function setMember(/* object */ $obj, string $name, $value) : bool + public static function setMember(object $obj, string $name, $value) : bool { - $reflectionClass = new \ReflectionClass(is_string($obj) ? $obj : get_class($obj)); + $reflectionClass = new \ReflectionClass(\get_class($obj)); if (!$reflectionClass->hasProperty($name)) { return false; @@ -74,16 +74,16 @@ final class TestUtils /** * Get private object member * - * @param object|string $obj Object to read - * @param string $name Member name to read + * @param object $obj Object to read + * @param string $name Member name to read * * @return mixed Returns the member variable value * * @since 1.0.0 */ - public static function getMember($obj, string $name) + public static function getMember(object $obj, string $name) { - $reflectionClass = new \ReflectionClass(is_string($obj) ? $obj : get_class($obj)); + $reflectionClass = new \ReflectionClass(\get_class($obj)); if (!$reflectionClass->hasProperty($name)) { return null; diff --git a/Validation/Finance/Iban.php b/Validation/Finance/Iban.php index 00884dda2..af5976040 100644 --- a/Validation/Finance/Iban.php +++ b/Validation/Finance/Iban.php @@ -31,8 +31,8 @@ final class Iban extends ValidatorAbstract */ public static function isValid($value, array $constraints = null) : bool { - $value = \str_replace(' ', '', strtolower($value)); - $enumName = 'C_' . strtoupper(substr($value, 0, 2)); + $value = \str_replace(' ', '', \strtolower($value)); + $enumName = 'C_' . \strtoupper(\substr($value, 0, 2)); if (!IbanEnum::isValidName($enumName)) { self::$error = IbanErrorType::INVALID_COUNTRY; @@ -42,7 +42,7 @@ final class Iban extends ValidatorAbstract $layout = \str_replace(' ', '', IbanEnum::getByName($enumName)); - if (strlen($value) !== strlen($layout)) { + if (\strlen($value) !== \strlen($layout)) { self::$error = IbanErrorType::INVALID_LENGTH; return false; @@ -81,12 +81,12 @@ final class Iban extends ValidatorAbstract */ private static function validateZeros(string $iban, string $layout) : bool { - if (strpos($layout, '0') === false) { + if (\strpos($layout, '0') === false) { return true; } $lastPos = 0; - while (($lastPos = strpos($layout, '0', $lastPos)) !== false) { + while (($lastPos = \strpos($layout, '0', $lastPos)) !== false) { if ($iban[$lastPos] !== '0') { return false; } @@ -109,13 +109,13 @@ final class Iban extends ValidatorAbstract */ private static function validateNumeric(string $iban, string $layout) : bool { - if (strpos($layout, 'n') === false) { + if (\strpos($layout, 'n') === false) { return true; } $lastPos = 0; - while (($lastPos = strpos($layout, 'n', $lastPos)) !== false) { - if (!is_numeric($iban[$lastPos])) { + while (($lastPos = \strpos($layout, 'n', $lastPos)) !== false) { + if (!\is_numeric($iban[$lastPos])) { return false; } @@ -139,18 +139,18 @@ final class Iban extends ValidatorAbstract $chars = ['a' => 10, 'b' => 11, 'c' => 12, 'd' => 13, 'e' => 14, 'f' => 15, 'g' => 16, 'h' => 17, 'i' => 18, 'j' => 19, 'k' => 20, 'l' => 21, 'm' => 22, 'n' => 23, 'o' => 24, 'p' => 25, 'q' => 26, 'r' => 27, 's' => 28, 't' => 29, 'u' => 30, 'v' => 31, 'w' => 32, 'x' => 33, 'y' => 34, 'z' => 35,]; - $moved = substr($iban, 4) . substr($iban, 0, 4); - $movedArray = str_split($moved); + $moved = \substr($iban, 4) . \substr($iban, 0, 4); + $movedArray = (array) \str_split($moved); $new = ''; foreach ($movedArray as $key => $value) { - if (!is_numeric($movedArray[$key])) { + if (!\is_numeric($movedArray[$key])) { $movedArray[$key] = $chars[$movedArray[$key]]; } $new .= $movedArray[$key]; } - return bcmod($new, '97') == 1; + return \bcmod($new, '97') == 1; } } diff --git a/Validation/Validator.php b/Validation/Validator.php index 090156223..9c2c917f8 100644 --- a/Validation/Validator.php +++ b/Validation/Validator.php @@ -34,6 +34,8 @@ final class Validator extends ValidatorAbstract * @param array $constraints Constraints for validation * * @return bool + * + * @throws \Exception * * @since 1.0.0 */ @@ -44,14 +46,13 @@ final class Validator extends ValidatorAbstract } foreach ($constraints as $test => $settings) { - $callback = StringUtils::endsWith($test, 'Not') ? substr($test, 0, -3) : $test; + $callback = StringUtils::endsWith($test, 'Not') ? \substr($test, 0, -3) : (string) $test; - if (!empty($settings)) { - $valid = $callback($var, ...$settings); - } else { - $valid = $callback($var); + if (!\is_callable($callback)) { + throw new \Exception(); } + $valid = !empty($settings) ? $callback($var, ...$settings) : $callback($var); $valid = (StringUtils::endsWith($test, 'Not') ? !$valid : $valid); if (!$valid) { diff --git a/Views/ViewAbstract.php b/Views/ViewAbstract.php index 8861a24ab..53a817794 100644 --- a/Views/ViewAbstract.php +++ b/Views/ViewAbstract.php @@ -203,7 +203,7 @@ abstract class ViewAbstract implements \Serializable public function serialize() : string { if (empty($this->template)) { - return \json_encode($this->toArray()); + return (string) \json_encode($this->toArray()); } return $this->render(); @@ -253,10 +253,10 @@ abstract class ViewAbstract implements \Serializable ob_start(); /** @noinspection PhpIncludeInspection */ $includeData = include $path; - $ob = ob_get_clean(); + $ob = (string) ob_get_clean(); if (is_array($includeData)) { - return \json_encode($includeData); + return (string) \json_encode($includeData); } } catch (\Throwable $e) { $ob = ''; From cb76bea3e7671cbdb5ed0c3101bb0dde2e461661 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 13:45:25 +0200 Subject: [PATCH 023/136] Fix missing use --- DataStorage/Cache/Connection/ConnectionAbstract.php | 1 + 1 file changed, 1 insertion(+) diff --git a/DataStorage/Cache/Connection/ConnectionAbstract.php b/DataStorage/Cache/Connection/ConnectionAbstract.php index 038e82e43..83fa481f0 100644 --- a/DataStorage/Cache/Connection/ConnectionAbstract.php +++ b/DataStorage/Cache/Connection/ConnectionAbstract.php @@ -15,6 +15,7 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Cache\Connection; use phpOMS\DataStorage\Cache\CacheStatus; +use phpOMS\DataStorage\Cache\CacheType; /** * Cache handler. From 7d8a68b589409843e8d384f45319480856aa057f Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 14:09:41 +0200 Subject: [PATCH 024/136] Minor code fixes --- Utils/Git/Repository.php | 4 ++-- Utils/TaskSchedule/TaskScheduler.php | 30 ++++++++++++++++------------ 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/Utils/Git/Repository.php b/Utils/Git/Repository.php index be320b665..e76e76ee4 100644 --- a/Utils/Git/Repository.php +++ b/Utils/Git/Repository.php @@ -191,8 +191,8 @@ class Repository throw new \Exception(); } - $stdout = \stream_get_contents($pipes[1]); - $stderr = \stream_get_contents($pipes[2]); + $stdout = \stream_get_contents($pipes[1]); + $stderr = \stream_get_contents($pipes[2]); foreach ($pipes as $pipe) { \fclose($pipe); diff --git a/Utils/TaskSchedule/TaskScheduler.php b/Utils/TaskSchedule/TaskScheduler.php index 6d76c6ba3..7e7e545ff 100644 --- a/Utils/TaskSchedule/TaskScheduler.php +++ b/Utils/TaskSchedule/TaskScheduler.php @@ -38,7 +38,7 @@ class TaskScheduler extends SchedulerAbstract */ private function run(string $cmd) : string { - $cmd = 'cd ' . escapeshellarg(\dirname(self::$bin)) . ' && ' . basename(self::$bin) . ' ' . $cmd; + $cmd = 'cd ' . \escapeshellarg(\dirname(self::$bin)) . ' && ' . \basename(self::$bin) . ' ' . $cmd; $pipes = []; $desc = [ @@ -46,15 +46,19 @@ class TaskScheduler extends SchedulerAbstract 2 => ['pipe', 'w'], ]; - $resource = proc_open($cmd, $desc, $pipes, __DIR__, null); - $stdout = stream_get_contents($pipes[1]); - $stderr = stream_get_contents($pipes[2]); - - foreach ($pipes as $pipe) { - fclose($pipe); + $resource = \proc_open($cmd, $desc, $pipes, __DIR__, null); + if ($resource === false) { + return ''; } - $status = trim((string) proc_close($resource)); + $stdout = \stream_get_contents($pipes[1]); + $stderr = \stream_get_contents($pipes[2]); + + foreach ($pipes as $pipe) { + \fclose($pipe); + } + + $status = \proc_close($resource); if ($status == -1) { throw new \Exception($stderr); @@ -87,7 +91,7 @@ class TaskScheduler extends SchedulerAbstract $jobs = []; foreach ($lines as $line) { - $jobs[] = Schedule::createWith(str_getcsv($line)); + $jobs[] = Schedule::createWith(\str_getcsv($line)); } return $jobs; @@ -99,12 +103,12 @@ class TaskScheduler extends SchedulerAbstract public function getAllByName(string $name, bool $exact = true) : array { if ($exact) { - $lines = \explode("\n", $this->normalize($this->run('/query /v /fo CSV /tn ' . escapeshellarg($name)))); + $lines = \explode("\n", $this->normalize($this->run('/query /v /fo CSV /tn ' . \escapeshellarg($name)))); unset($lines[0]); $jobs = []; foreach ($lines as $line) { - $jobs[] = Schedule::createWith(str_getcsv($line)); + $jobs[] = Schedule::createWith(\str_getcsv($line)); } } else { $lines = \explode("\n", $this->normalize($this->run('/query /v /fo CSV'))); @@ -112,9 +116,9 @@ class TaskScheduler extends SchedulerAbstract $jobs = []; foreach ($lines as $key => $line) { - $line = str_getcsv($line); + $line = \str_getcsv($line); - if (stripos($line[1], $name) !== false) { + if (\stripos($line[1], $name) !== false) { $jobs[] = Schedule::createWith($line); } } From 39f299e2119fd7ddf9698bdc4f4d4f902590c7b1 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 14:22:25 +0200 Subject: [PATCH 025/136] Fix formatting --- Utils/TaskSchedule/TaskScheduler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Utils/TaskSchedule/TaskScheduler.php b/Utils/TaskSchedule/TaskScheduler.php index 7e7e545ff..f662541c3 100644 --- a/Utils/TaskSchedule/TaskScheduler.php +++ b/Utils/TaskSchedule/TaskScheduler.php @@ -51,8 +51,8 @@ class TaskScheduler extends SchedulerAbstract return ''; } - $stdout = \stream_get_contents($pipes[1]); - $stderr = \stream_get_contents($pipes[2]); + $stdout = \stream_get_contents($pipes[1]); + $stderr = \stream_get_contents($pipes[2]); foreach ($pipes as $pipe) { \fclose($pipe); From 0614c12eef44d796632266a14c6665c41bbcde7d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 14:41:15 +0200 Subject: [PATCH 026/136] Fix more type bugs --- DataStorage/DataStoragePoolInterface.php | 2 +- DataStorage/Database/GrammarAbstract.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/DataStorage/DataStoragePoolInterface.php b/DataStorage/DataStoragePoolInterface.php index bc3bd597f..d55c14d72 100644 --- a/DataStorage/DataStoragePoolInterface.php +++ b/DataStorage/DataStoragePoolInterface.php @@ -44,7 +44,7 @@ interface DataStoragePoolInterface * * @param string $key Connection key * - * @return mixed + * @return DataStorageConnectionInterface * * @since 1.0.0 */ diff --git a/DataStorage/Database/GrammarAbstract.php b/DataStorage/Database/GrammarAbstract.php index ecd7c91c0..c55d09abe 100644 --- a/DataStorage/Database/GrammarAbstract.php +++ b/DataStorage/Database/GrammarAbstract.php @@ -225,20 +225,20 @@ abstract class GrammarAbstract * * A system is a table, a sub query or special keyword. * - * @param array|string $system System - * @param string $prefix Prefix for table + * @param string $system System + * @param string $prefix Prefix for table * * @return string * * @since 1.0.0 */ - protected function compileSystem($system, string $prefix = '') : string + protected function compileSystem(string $system, string $prefix = '') : string { // todo: this is a bad way to handle select count(*) which doesn't need a prefix. Maybe remove prefixes in total? $identifier = $this->systemIdentifier; foreach ($this->specialKeywords as $keyword) { - if (strrpos($system, $keyword, -strlen($system)) !== false) { + if (\strrpos($system, $keyword, -\strlen($system)) !== false) { $prefix = ''; $identifier = ''; } From e76606d0a39614f4d34b631e7f5a15f5bc690592 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 17:23:18 +0200 Subject: [PATCH 027/136] Static test fixes --- DataStorage/Database/BuilderAbstract.php | 4 +- DataStorage/Database/DataMapperAbstract.php | 198 +++++++++----------- Message/Http/Response.php | 2 +- Stdlib/Base/Location.php | 2 +- Stdlib/Queue/PriorityQueue.php | 10 +- Utils/JsonBuilder.php | 2 +- 6 files changed, 100 insertions(+), 118 deletions(-) diff --git a/DataStorage/Database/BuilderAbstract.php b/DataStorage/Database/BuilderAbstract.php index f5f81816b..300227dd4 100644 --- a/DataStorage/Database/BuilderAbstract.php +++ b/DataStorage/Database/BuilderAbstract.php @@ -72,11 +72,11 @@ abstract class BuilderAbstract * * @param string $prefix Prefix * - * @return BuilderAbstract + * @return self * * @since 1.0.0 */ - public function prefix(string $prefix) : BuilderAbstract + public function prefix(string $prefix) : self { $this->prefix = $prefix; diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index 7fdc775b9..f857571d8 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -14,7 +14,7 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Database; -use phpOMS\DataStorage\DataStorageConnectionInterface; +use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; use phpOMS\DataStorage\Database\Query\Builder; use phpOMS\DataStorage\DataMapperInterface; use phpOMS\Message\RequestAbstract; @@ -37,7 +37,7 @@ class DataMapperAbstract implements DataMapperInterface /** * Database connection. * - * @var DataStorageConnectionInterface + * @var ConnectionAbstract * @since 1.0.0 */ protected static $db = null; @@ -149,7 +149,7 @@ class DataMapperAbstract implements DataMapperInterface /** * Highest mapper to know when to clear initialized objects * - * @var string + * @var null|string * @since 1.0.0 */ protected static $parentMapper = null; @@ -195,13 +195,13 @@ class DataMapperAbstract implements DataMapperInterface /** * Set database connection. * - * @param DataStorageConnectionInterface $con Database connection + * @param ConnectionAbstract $con Database connection * * @return void * * @since 1.0.0 */ - public static function setConnection(DataStorageConnectionInterface $con) : void + public static function setConnection(ConnectionAbstract $con) : void { self::$db = $con; } @@ -389,14 +389,14 @@ class DataMapperAbstract implements DataMapperInterface /** * Create base model. * - * @param Object $obj Model to create + * @param object $obj Model to create * @param \ReflectionClass $refClass Reflection class * * @return mixed * * @since 1.0.0 */ - private static function createModel($obj, \ReflectionClass $refClass) + private static function createModel(object $obj, \ReflectionClass $refClass) { $query = new Builder(self::$db); $query->prefix(self::$db->getPrefix())->into(static::$table); @@ -512,14 +512,14 @@ class DataMapperAbstract implements DataMapperInterface /** * Get id of object * - * @param Object $obj Model to create + * @param object $obj Model to create * @param \ReflectionClass $refClass Reflection class * * @return mixed * * @since 1.0.0 */ - private static function getObjectId($obj, \ReflectionClass $refClass = null) + private static function getObjectId(object $obj, \ReflectionClass $refClass = null) { $refClass = $refClass ?? new \ReflectionClass($obj); $refProp = $refClass->getProperty(static::$columns[static::$primaryField]['internal']); @@ -541,14 +541,14 @@ class DataMapperAbstract implements DataMapperInterface * Set id to model * * @param \ReflectionClass $refClass Reflection class - * @param Object $obj Object to create + * @param object $obj Object to create * @param mixed $objId Id to set * * @return void * * @since 1.0.0 */ - private static function setObjectId(\ReflectionClass $refClass, $obj, $objId) : void + private static function setObjectId(\ReflectionClass $refClass, object $obj, $objId) : void { $refProp = $refClass->getProperty(static::$columns[static::$primaryField]['internal']); @@ -568,7 +568,7 @@ class DataMapperAbstract implements DataMapperInterface * Create has many * * @param \ReflectionClass $refClass Reflection class - * @param Object $obj Object to create + * @param object $obj Object to create * @param mixed $objId Id to set * * @return void @@ -577,7 +577,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - private static function createHasMany(\ReflectionClass $refClass, $obj, $objId) : void + private static function createHasMany(\ReflectionClass $refClass, object $obj, $objId) : void { foreach (static::$hasMany as $propertyName => $rel) { $property = $refClass->getProperty($propertyName); @@ -672,7 +672,7 @@ class DataMapperAbstract implements DataMapperInterface $objsIds = []; foreach ($values as $key => &$value) { - if (!is_object($value)) { + if (!is_array($value)) { // Is scalar => already in database $objsIds[$key] = $value; @@ -706,14 +706,14 @@ class DataMapperAbstract implements DataMapperInterface * Create has one * * @param \ReflectionClass $refClass Property name to initialize - * @param Object $obj Object to create + * @param object $obj Object to create * * @return mixed * @todo implement??? * * @since 1.0.0 */ - private static function createHasOne(\ReflectionClass $refClass, $obj) + private static function createHasOne(\ReflectionClass $refClass, object $obj) { throw new \Exception(); } @@ -724,26 +724,22 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param Object $obj Object to create + * @param object $obj Object to create * * @return mixed * * @since 1.0.0 */ - private static function createOwnsOne(string $propertyName, $obj) + private static function createOwnsOne(string $propertyName, object $obj) { - if (is_object($obj)) { - $mapper = static::$ownsOne[$propertyName]['mapper']; - $primaryKey = $mapper::getObjectId($obj); + $mapper = static::$ownsOne[$propertyName]['mapper']; + $primaryKey = $mapper::getObjectId($obj); - if (empty($primaryKey)) { - return $mapper::create($obj); - } - - return $primaryKey; + if (empty($primaryKey)) { + return $mapper::create($obj); } - return $obj; + return $primaryKey; } /** @@ -780,27 +776,23 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param Object $obj Object to create + * @param object $obj Object to create * * @return mixed * * @since 1.0.0 */ - private static function createBelongsTo(string $propertyName, $obj) + private static function createBelongsTo(string $propertyName, object $obj) { - if (is_object($obj)) { - /** @var string $mapper */ - $mapper = static::$belongsTo[$propertyName]['mapper']; - $primaryKey = $mapper::getObjectId($obj); + /** @var string $mapper */ + $mapper = static::$belongsTo[$propertyName]['mapper']; + $primaryKey = $mapper::getObjectId($obj); - if (empty($primaryKey)) { - return $mapper::create($obj); - } - - return $primaryKey; + if (empty($primaryKey)) { + return $mapper::create($obj); } - return $obj; + return $primaryKey; } /** @@ -890,11 +882,11 @@ class DataMapperAbstract implements DataMapperInterface } elseif ($type === 'DateTime') { return $value->format('Y-m-d H:i:s'); } elseif ($type === 'Json' || $type === 'jsonSerializable') { - return \json_encode($value); + return (string) \json_encode($value); } elseif ($type === 'Serializable') { return $value->serialize(); } elseif ($value instanceof \JsonSerializable) { - return \json_encode($value->jsonSerialize()); + return (string) \json_encode($value->jsonSerialize()); } elseif (is_object($value) && method_exists($value, 'getId')) { return $value->getId(); } @@ -906,7 +898,7 @@ class DataMapperAbstract implements DataMapperInterface * Update has many * * @param \ReflectionClass $refClass Reflection class - * @param Object $obj Object to create + * @param object $obj Object to create * @param mixed $objId Id to set * * @return void @@ -915,7 +907,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - private static function updateHasMany(\ReflectionClass $refClass, $obj, $objId) : void + private static function updateHasMany(\ReflectionClass $refClass, object $obj, $objId) : void { $objsIds = []; @@ -1055,24 +1047,20 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param Object $obj Object to update + * @param object $obj Object to update * * @return mixed * * @since 1.0.0 */ - private static function updateOwnsOne(string $propertyName, $obj) + private static function updateOwnsOne(string $propertyName, object $obj) { - if (is_object($obj)) { - /** @var string $mapper */ - $mapper = static::$ownsOne[$propertyName]['mapper']; + /** @var string $mapper */ + $mapper = static::$ownsOne[$propertyName]['mapper']; - // todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one? + // todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one? - return $mapper::update($obj); - } - - return $obj; + return $mapper::update($obj); } /** @@ -1081,28 +1069,24 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param Object $obj Object to update + * @param object $obj Object to update * * @return mixed * * @since 1.0.0 */ - private static function updateBelongsTo(string $propertyName, $obj) + private static function updateBelongsTo(string $propertyName, object $obj) { - if (is_object($obj)) { - /** @var string $mapper */ - $mapper = static::$belongsTo[$propertyName]['mapper']; + /** @var string $mapper */ + $mapper = static::$belongsTo[$propertyName]['mapper']; - return $mapper::update($obj); - } - - return $obj; + return $mapper::update($obj); } /** * Update object in db. * - * @param Object $obj Model to update + * @param object $obj Model to update * @param mixed $objId Model id * @param \ReflectionClass $refClass Reflection class * @@ -1110,7 +1094,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - private static function updateModel($obj, $objId, \ReflectionClass $refClass = null) : void + private static function updateModel(object $obj, $objId, \ReflectionClass $refClass = null) : void { $query = new Builder(self::$db); $query->prefix(self::$db->getPrefix()) @@ -1126,6 +1110,7 @@ class DataMapperAbstract implements DataMapperInterface continue; } + $refClass = $refClass ?? new \ReflectionClass($obj); $property = $refClass->getProperty($propertyName); if (!($isPublic = $property->isPublic())) { @@ -1211,7 +1196,7 @@ class DataMapperAbstract implements DataMapperInterface * Delete has many * * @param \ReflectionClass $refClass Reflection class - * @param Object $obj Object to create + * @param object $obj Object to create * @param mixed $objId Id to set * @param int $relations Delete all relations as well * @@ -1221,7 +1206,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - private static function deleteHasMany(\ReflectionClass $refClass, $obj, $objId, int $relations) : void + private static function deleteHasMany(\ReflectionClass $refClass, object $obj, $objId, int $relations) : void { foreach (static::$hasMany as $propertyName => $rel) { $property = $refClass->getProperty($propertyName); @@ -1284,23 +1269,19 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param Object $obj Object to delete + * @param object $obj Object to delete * * @return mixed * * @since 1.0.0 */ - private static function deleteOwnsOne(string $propertyName, $obj) + private static function deleteOwnsOne(string $propertyName, object $obj) { - if (is_object($obj)) { - /** @var string $mapper */ - $mapper = static::$ownsOne[$propertyName]['mapper']; + /** @var string $mapper */ + $mapper = static::$ownsOne[$propertyName]['mapper']; - // todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one? - return $mapper::delete($obj); - } - - return $obj; + // todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one? + return $mapper::delete($obj); } /** @@ -1309,28 +1290,24 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param Object $obj Object to delete + * @param object $obj Object to delete * * @return mixed * * @since 1.0.0 */ - private static function deleteBelongsTo(string $propertyName, $obj) + private static function deleteBelongsTo(string $propertyName, object $obj) { - if (is_object($obj)) { - /** @var string $mapper */ - $mapper = static::$belongsTo[$propertyName]['mapper']; + /** @var string $mapper */ + $mapper = static::$belongsTo[$propertyName]['mapper']; - return $mapper::delete($obj); - } - - return $obj; + return $mapper::delete($obj); } /** * Delete object in db. * - * @param Object $obj Model to delete + * @param object $obj Model to delete * @param mixed $objId Model id * @param int $relations Delete all relations as well * @param \ReflectionClass $refClass Reflection class @@ -1339,7 +1316,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - private static function deleteModel($obj, $objId, int $relations = RelationType::REFERENCE, \ReflectionClass $refClass = null) : void + private static function deleteModel(object $obj, $objId, int $relations = RelationType::REFERENCE, \ReflectionClass $refClass = null) : void { $query = new Builder(self::$db); $query->prefix(self::$db->getPrefix()) @@ -1347,6 +1324,7 @@ class DataMapperAbstract implements DataMapperInterface ->from(static::$table) ->where(static::$table . '.' . static::$primaryField, '=', $objId); + $refClass = $refClass ?? new \ReflectionClass($obj); $properties = $refClass->getProperties(); if ($relations === RelationType::ALL) { @@ -1775,7 +1753,9 @@ class DataMapperAbstract implements DataMapperInterface continue; } - $hasPath = false; + $hasPath = false; + $aValue = []; + $arrayPath = ''; if (stripos(static::$columns[$column]['internal'], '/') !== false) { $hasPath = true; @@ -1787,8 +1767,8 @@ class DataMapperAbstract implements DataMapperInterface } array_shift($path); - $path = implode('/', $path); - $aValue = $refProp->getValue($obj); + $arrayPath = implode('/', $path); + $aValue = $refProp->getValue($obj); } else { $refProp = $refClass->getProperty(static::$columns[$column]['internal']); @@ -1804,20 +1784,20 @@ class DataMapperAbstract implements DataMapperInterface } if ($hasPath) { - $value = ArrayUtils::setArray($path, $aValue, $value, '/', true); + $value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true); } $refProp->setValue($obj, $value); } elseif (static::$columns[$column]['type'] === 'DateTime') { $value = new \DateTime($value ?? ''); if ($hasPath) { - $value = ArrayUtils::setArray($path, $aValue, $value, '/', true); + $value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true); } $refProp->setValue($obj, $value); } elseif (static::$columns[$column]['type'] === 'Json') { if ($hasPath) { - $value = ArrayUtils::setArray($path, $aValue, $value, '/', true); + $value = ArrayUtils::setArray($arrayPath, $aValue, $value, '/', true); } $refProp->setValue($obj, \json_decode($value, true)); @@ -2104,7 +2084,7 @@ class DataMapperAbstract implements DataMapperInterface public static function getAll(int $relations = RelationType::ALL, int $depth = null, string $lang = '') : array { if (isset($depth) && $depth < 1) { - return null; + return []; } if (!isset(self::$parentMapper)) { @@ -2132,7 +2112,7 @@ class DataMapperAbstract implements DataMapperInterface public static function getAllArray(int $relations = RelationType::ALL, int $depth = null, string $lang = '') : array { if (isset($depth) && $depth < 1) { - return null; + return []; } if (!isset(self::$parentMapper)) { @@ -2174,14 +2154,14 @@ class DataMapperAbstract implements DataMapperInterface * @param int $depth Relation depth * @param string $lang Language * - * @return mixed + * @return array * * @since 1.0.0 */ public static function getNewest(int $limit = 1, Builder $query = null, int $relations = RelationType::ALL, int $depth = null, string $lang = '') : array { if (isset($depth) && $depth < 1) { - return null; + return []; } self::extend(__CLASS__); @@ -2204,7 +2184,7 @@ class DataMapperAbstract implements DataMapperInterface $sth->execute(); $results = $sth->fetchAll(\PDO::FETCH_ASSOC); - $obj = self::populateIterable(is_bool($results) ? [] : $results); + $obj = self::populateIterable($results === false ? [] : $results); self::fillRelations($obj, $relations, isset($depth) ? --$depth : null); self::clear(); @@ -2227,14 +2207,14 @@ class DataMapperAbstract implements DataMapperInterface public static function getAllByQuery(Builder $query, int $relations = RelationType::ALL, int $depth = null) : array { if (isset($depth) && $depth < 1) { - return null; + return []; } $sth = self::$db->con->prepare($query->toSql()); $sth->execute(); $results = $sth->fetchAll(\PDO::FETCH_ASSOC); - $results = is_bool($results) ? [] : $results; + $results = $results === false ? [] : $results; $obj = self::populateIterable($results); self::fillRelations($obj, $relations, isset($depth) ? --$depth : null); @@ -2275,7 +2255,7 @@ class DataMapperAbstract implements DataMapperInterface /** * Fill object with relations * - * @param mixed $obj Objects to fill + * @param array $obj Objects to fill * @param int $relations Relations type * @param int $depth Relation depth * @@ -2325,7 +2305,7 @@ class DataMapperAbstract implements DataMapperInterface /** * Fill object with relations * - * @param mixed $obj Objects to fill + * @param array $obj Objects to fill * @param int $relations Relations type * @param int $depth Relation depth * @@ -2377,7 +2357,7 @@ class DataMapperAbstract implements DataMapperInterface * * @param mixed $primaryKey Key * - * @return mixed + * @return array * * @since 1.0.0 */ @@ -2391,7 +2371,7 @@ class DataMapperAbstract implements DataMapperInterface $results = $sth->fetch(\PDO::FETCH_ASSOC); - return is_bool($results) ? [] : $results; + return $results === false ? [] : $results; } /** @@ -2468,7 +2448,7 @@ class DataMapperAbstract implements DataMapperInterface $results = $sth->fetchAll(\PDO::FETCH_ASSOC); - return is_bool($results) ? [] : $results; + return $results === false ? [] : $results; } /** @@ -2510,7 +2490,7 @@ class DataMapperAbstract implements DataMapperInterface ->leftOuterJoin($value['table']) ->on(new And('1', new And(new Or('d1', 'd2'), 'id'))) ->where($value['table'] . '.' . $value['dst'], '=', 'NULL'); - + }*/ $sth = self::$db->con->prepare($query->toSql()); @@ -2608,7 +2588,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - private static function addInitialized(string $mapper, $id, $obj = null) : void + private static function addInitialized(string $mapper, $id, object $obj = null) : void { if (!isset(self::$initObjects[$mapper])) { self::$initObjects[$mapper] = []; @@ -2720,8 +2700,8 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - private static function isNullObject($obj) : bool + private static function isNullObject(object $obj) : bool { - return is_object($obj) && strpos(get_class($obj), '\Null') !== false; + return strpos(get_class($obj), '\Null') !== false; } } diff --git a/Message/Http/Response.php b/Message/Http/Response.php index 1a8b30f3a..4388aece6 100644 --- a/Message/Http/Response.php +++ b/Message/Http/Response.php @@ -106,7 +106,7 @@ final class Response extends ResponseAbstract implements RenderableInterface foreach ($types as $type) { if (\stripos($type, MimeType::M_JSON) !== false) { - return \json_encode($this->jsonSerialize()); + return (string) \json_encode($this->jsonSerialize()); } } diff --git a/Stdlib/Base/Location.php b/Stdlib/Base/Location.php index f30934767..7f772c1df 100644 --- a/Stdlib/Base/Location.php +++ b/Stdlib/Base/Location.php @@ -297,7 +297,7 @@ class Location implements \JsonSerializable, \Serializable */ public function serialize() : string { - return \json_encode($this->jsonSerialize()); + return (string) \json_encode($this->jsonSerialize()); } /** diff --git a/Stdlib/Queue/PriorityQueue.php b/Stdlib/Queue/PriorityQueue.php index 96029929f..71357896e 100644 --- a/Stdlib/Queue/PriorityQueue.php +++ b/Stdlib/Queue/PriorityQueue.php @@ -53,14 +53,15 @@ class PriorityQueue implements \Countable, \Serializable /** * Insert element into queue. * - * @param mixed $data Queue element - * @param float $priority Priority of this element + * @param mixed $data Queue element + * @param string $job Job cmd + * @param float $priority Priority of this element * * @return int * * @since 1.0.0 */ - public function insert($data, float $priority = 1.0) : int + public function insert($data, string $job, float $priority = 1.0) : int { do { $key = rand(); @@ -78,6 +79,7 @@ class PriorityQueue implements \Countable, \Serializable $pos++; } + $original = []; array_splice($original, $pos, 0, [$key => ['key' => $key, 'job' => $job, 'priority' => $priority]]); } @@ -184,7 +186,7 @@ class PriorityQueue implements \Countable, \Serializable */ public function serialize() : string { - return \json_encode($this->queue); + return (string) \json_encode($this->queue); } /** diff --git a/Utils/JsonBuilder.php b/Utils/JsonBuilder.php index f96d709bf..08a92fa21 100644 --- a/Utils/JsonBuilder.php +++ b/Utils/JsonBuilder.php @@ -80,7 +80,7 @@ final class JsonBuilder implements \Serializable, \JsonSerializable */ public function serialize() : string { - return \json_encode($this->json); + return (string) \json_encode($this->json); } /** From c8d938591a0e2e696c0a7fa2d6607b1e94b1b195 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 18:23:05 +0200 Subject: [PATCH 028/136] Fix too strict type definitions --- DataStorage/Database/DataMapperAbstract.php | 88 +++++++++++++-------- Utils/TestUtils.php | 31 +++++--- 2 files changed, 74 insertions(+), 45 deletions(-) diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index f857571d8..a9d787cc8 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -724,22 +724,26 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param object $obj Object to create + * @param mixed $obj Object to create * * @return mixed * * @since 1.0.0 */ - private static function createOwnsOne(string $propertyName, object $obj) + private static function createOwnsOne(string $propertyName, $obj) { - $mapper = static::$ownsOne[$propertyName]['mapper']; - $primaryKey = $mapper::getObjectId($obj); + if (is_object($obj)) { + $mapper = static::$ownsOne[$propertyName]['mapper']; + $primaryKey = $mapper::getObjectId($obj); - if (empty($primaryKey)) { - return $mapper::create($obj); + if (empty($primaryKey)) { + return $mapper::create($obj); + } + + return $primaryKey; } - return $primaryKey; + return $obj; } /** @@ -776,23 +780,27 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param object $obj Object to create + * @param mixed $obj Object to create * * @return mixed * * @since 1.0.0 */ - private static function createBelongsTo(string $propertyName, object $obj) + private static function createBelongsTo(string $propertyName, $obj) { - /** @var string $mapper */ - $mapper = static::$belongsTo[$propertyName]['mapper']; - $primaryKey = $mapper::getObjectId($obj); + if (is_object($obj)) { + /** @var string $mapper */ + $mapper = static::$belongsTo[$propertyName]['mapper']; + $primaryKey = $mapper::getObjectId($obj); - if (empty($primaryKey)) { - return $mapper::create($obj); + if (empty($primaryKey)) { + return $mapper::create($obj); + } + + return $primaryKey; } - return $primaryKey; + return $obj; } /** @@ -1069,18 +1077,22 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param object $obj Object to update + * @param mixed $obj Object to update * * @return mixed * * @since 1.0.0 */ - private static function updateBelongsTo(string $propertyName, object $obj) + private static function updateBelongsTo(string $propertyName, $obj) { - /** @var string $mapper */ - $mapper = static::$belongsTo[$propertyName]['mapper']; + if (is_object($obj)) { + /** @var string $mapper */ + $mapper = static::$belongsTo[$propertyName]['mapper']; - return $mapper::update($obj); + return $mapper::update($obj); + } + + return $obj; } /** @@ -1269,19 +1281,23 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param object $obj Object to delete + * @param mixed $obj Object to delete * * @return mixed * * @since 1.0.0 */ - private static function deleteOwnsOne(string $propertyName, object $obj) + private static function deleteOwnsOne(string $propertyName, $obj) { - /** @var string $mapper */ - $mapper = static::$ownsOne[$propertyName]['mapper']; + if (is_object($obj)) { + /** @var string $mapper */ + $mapper = static::$ownsOne[$propertyName]['mapper']; - // todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one? - return $mapper::delete($obj); + // todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one? + return $mapper::delete($obj); + } + + return $obj; } /** @@ -1290,18 +1306,22 @@ class DataMapperAbstract implements DataMapperInterface * The reference is stored in the main model * * @param string $propertyName Property name to initialize - * @param object $obj Object to delete + * @param mixed $obj Object to delete * * @return mixed * * @since 1.0.0 */ - private static function deleteBelongsTo(string $propertyName, object $obj) + private static function deleteBelongsTo(string $propertyName, $obj) { - /** @var string $mapper */ - $mapper = static::$belongsTo[$propertyName]['mapper']; + if (is_object($obj)) { + /** @var string $mapper */ + $mapper = static::$belongsTo[$propertyName]['mapper']; - return $mapper::delete($obj); + return $mapper::delete($obj); + } + + return $obj; } /** @@ -2694,14 +2714,14 @@ class DataMapperAbstract implements DataMapperInterface /** * Test if object is null object * - * @param object $obj Object to check + * @param mixed $obj Object to check * * @return bool * * @since 1.0.0 */ - private static function isNullObject(object $obj) : bool + private static function isNullObject($obj) : bool { - return strpos(get_class($obj), '\Null') !== false; + return \is_object($obj) && \strpos(\get_class($obj), '\Null') !== false; } } diff --git a/Utils/TestUtils.php b/Utils/TestUtils.php index bef0dc703..52ad9ff16 100644 --- a/Utils/TestUtils.php +++ b/Utils/TestUtils.php @@ -40,17 +40,17 @@ final class TestUtils /** * Set private object member * - * @param object $obj Object to modify - * @param string $name Member name to modify - * @param mixed $value Value to set + * @param object|string $obj Object to modify + * @param string $name Member name to modify + * @param mixed $value Value to set * * @return bool The function returns true after setting the member * * @since 1.0.0 */ - public static function setMember(object $obj, string $name, $value) : bool + public static function setMember($obj, string $name, $value) : bool { - $reflectionClass = new \ReflectionClass(\get_class($obj)); + $reflectionClass = new \ReflectionClass(\is_string($obj) ? $obj : \get_class($obj)); if (!$reflectionClass->hasProperty($name)) { return false; @@ -62,7 +62,11 @@ final class TestUtils $reflectionProperty->setAccessible(true); } - $reflectionProperty->setValue($obj, $value); + if (\is_string($obj)) { + $reflectionProperty->setValue($value); + } elseif (\is_object($obj)) { + $reflectionProperty->setValue($obj, $value); + } if (!$accessible) { $reflectionProperty->setAccessible(false); @@ -74,16 +78,16 @@ final class TestUtils /** * Get private object member * - * @param object $obj Object to read - * @param string $name Member name to read + * @param object|string $obj Object to read + * @param string $name Member name to read * * @return mixed Returns the member variable value * * @since 1.0.0 */ - public static function getMember(object $obj, string $name) + public static function getMember($obj, string $name) { - $reflectionClass = new \ReflectionClass(\get_class($obj)); + $reflectionClass = new \ReflectionClass(\is_string($obj) ? $obj : \get_class($obj)); if (!$reflectionClass->hasProperty($name)) { return null; @@ -95,7 +99,12 @@ final class TestUtils $reflectionProperty->setAccessible(true); } - $value = $reflectionProperty->getValue($obj); + $value = null; + if (\is_string($obj)) { + $value = $reflectionProperty->getValue(); + } elseif (\is_object($obj)) { + $value = $reflectionProperty->getValue($obj); + } if (!$accessible) { $reflectionProperty->setAccessible(false); From 42877f570d7b1022f0865001876e1fe0ee4f0e29 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 20:11:31 +0200 Subject: [PATCH 029/136] More type checks --- Utils/Converter/Numeric.php | 36 ++++++++++++++++++++---------------- Utils/RnG/ArrayRandomize.php | 6 +++--- 2 files changed, 23 insertions(+), 19 deletions(-) diff --git a/Utils/Converter/Numeric.php b/Utils/Converter/Numeric.php index eb359d177..d56466762 100644 --- a/Utils/Converter/Numeric.php +++ b/Utils/Converter/Numeric.php @@ -64,22 +64,26 @@ class Numeric return $numberInput; } - $fromBase = str_split($fromBaseInput, 1); - $toBase = str_split($toBaseInput, 1); - $number = str_split($numberInput, 1); - $fromLen = strlen($fromBaseInput); - $toLen = strlen($toBaseInput); - $numberLen = strlen($numberInput); + $fromBase = \str_split($fromBaseInput, 1); + $toBase = \str_split($toBaseInput, 1); + $number = \str_split($numberInput, 1); + $fromLen = \strlen($fromBaseInput); + $toLen = \strlen($toBaseInput); + $numberLen = \strlen($numberInput); $newOutput = ''; + if ($fromBase === false || $toBase === false || $number === false) { + throw new \Exception(); + } + if ($toBaseInput === '0123456789') { - $newOutput = 0; + $newOutput = '0'; for ($i = 1; $i <= $numberLen; ++$i) { $newOutput = bcadd( - (string) $newOutput, + $newOutput, bcmul( - (string) array_search($number[$i - 1], $fromBase), + (string) \array_search($number[$i - 1], $fromBase), bcpow((string) $fromLen, (string) ($numberLen - $i)) ) ); @@ -88,15 +92,15 @@ class Numeric return $newOutput; } - $base10 = $fromBaseInput != '0123456789' ? self::convertBase($numberInput, $fromBaseInput, '0123456789') : $numberInput; + $base10 = (int) ($fromBaseInput != '0123456789' ? self::convertBase($numberInput, $fromBaseInput, '0123456789') : $numberInput); - if ($base10 < strlen($toBaseInput)) { + if ($base10 < \strlen($toBaseInput)) { return $toBase[$base10]; } while ($base10 !== '0') { - $newOutput = $toBase[bcmod($base10, (string) $toLen)] . $newOutput; - $base10 = bcdiv($base10, (string) $toLen, 0); + $newOutput = $toBase[(int) bcmod((string) $base10, (string) $toLen)] . $newOutput; + $base10 = bcdiv((string) $base10, (string) $toLen, 0); } return $newOutput; @@ -146,7 +150,7 @@ class Numeric foreach (self::ROMANS as $key => $value) { while (strpos($roman, $key) === 0) { $result += $value; - $roman = substr($roman, strlen($key)); + $roman = substr($roman, \strlen($key)); } } @@ -169,7 +173,7 @@ class Numeric $alpha = ''; for ($i = 1; $number >= 0 && $i < 10; ++$i) { - $alpha = chr(0x41 + ($number % pow(26, $i) / pow(26, $i - 1))) . $alpha; + $alpha = chr(0x41 + (int) ($number % pow(26, $i) / pow(26, $i - 1))) . $alpha; $number -= pow(26, $i); } @@ -188,7 +192,7 @@ class Numeric public static function alphaToNumeric(string $alpha) : int { $numeric = 0; - $length = strlen($alpha); + $length = \strlen($alpha); for ($i = 0; $i < $length; ++$i) { $numeric += pow(26, $i) * (ord($alpha[$length - $i - 1]) - 0x40); diff --git a/Utils/RnG/ArrayRandomize.php b/Utils/RnG/ArrayRandomize.php index 2037e7e9b..d22e7dba0 100644 --- a/Utils/RnG/ArrayRandomize.php +++ b/Utils/RnG/ArrayRandomize.php @@ -27,7 +27,7 @@ class ArrayRandomize /** * Yates array shuffler. * - * @param array $arr Array to randomize + * @param array $arr Array to randomize. Array must NOT be associative * * @return array * @@ -38,8 +38,8 @@ class ArrayRandomize $shuffled = []; while (!empty($arr)) { - $rnd = array_rand($arr); - $shuffled[] = $arr[$rnd]; + $rnd = (int) array_rand($arr); + $shuffled[] = $arr[$rnd] ?? null; array_splice($arr, $rnd, 1); } From d1fafd760b78a584b77fbdfccda849af772dfbeb Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 20:11:34 +0200 Subject: [PATCH 030/136] More type checks --- Utils/Converter/Numeric.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utils/Converter/Numeric.php b/Utils/Converter/Numeric.php index d56466762..27149160e 100644 --- a/Utils/Converter/Numeric.php +++ b/Utils/Converter/Numeric.php @@ -198,6 +198,6 @@ class Numeric $numeric += pow(26, $i) * (ord($alpha[$length - $i - 1]) - 0x40); } - return $numeric - 1; + return (int) $numeric - 1; } } From 0069bdac9a20ec43d218e204901b88d21f527b00 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 22:19:48 +0200 Subject: [PATCH 031/136] Static test fixes --- Log/LoggerInterface.php | 36 ++++++++++----------- Stdlib/Base/SmartDateTime.php | 12 +++++-- System/File/FileUtils.php | 8 ++--- System/SystemUtils.php | 43 ++++++++++++++----------- Utils/ArrayUtils.php | 40 +++++++++++++++++------- Utils/Barcode/C128Abstract.php | 45 +++++++++++++++------------ Utils/Compression/LZW.php | 18 ++++++----- Utils/Converter/Ip.php | 5 ++- Utils/Encoding/Huffman/Huffman.php | 28 +++++++++++++---- tests/Utils/Converter/NumericTest.php | 11 +++++++ 10 files changed, 157 insertions(+), 89 deletions(-) diff --git a/Log/LoggerInterface.php b/Log/LoggerInterface.php index dde03237b..1cb97d030 100644 --- a/Log/LoggerInterface.php +++ b/Log/LoggerInterface.php @@ -28,8 +28,8 @@ interface LoggerInterface /** * System is unusable. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -41,8 +41,8 @@ interface LoggerInterface * Example: Entire website down, database unavailable, etc. This should * trigger the SMS alerts and wake you up. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -53,8 +53,8 @@ interface LoggerInterface * * Example: Application component unavailable, unexpected exception. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -64,8 +64,8 @@ interface LoggerInterface * Runtime errors that do not require immediate action but should typically * be logged and monitored. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -77,8 +77,8 @@ interface LoggerInterface * Example: Use of deprecated APIs, poor use of an API, undesirable things * that are not necessarily wrong. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -87,8 +87,8 @@ interface LoggerInterface /** * Normal but significant events. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -99,8 +99,8 @@ interface LoggerInterface * * Example: User logs in, SQL logs. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -109,8 +109,8 @@ interface LoggerInterface /** * Detailed debug information. * - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ @@ -120,8 +120,8 @@ interface LoggerInterface * Logs with an arbitrary level. * * @param string $level Log level/severeness - * @param string $message Logging message schema - * @param array $context Context to log + * @param string $message Logging message schema + * @param array $context Context to log * * @return void */ diff --git a/Stdlib/Base/SmartDateTime.php b/Stdlib/Base/SmartDateTime.php index cf3e617b0..d0a95f317 100644 --- a/Stdlib/Base/SmartDateTime.php +++ b/Stdlib/Base/SmartDateTime.php @@ -97,8 +97,8 @@ class SmartDateTime extends \DateTime $yearNew = (int) $this->format('Y') + $y + $yearChange; $monthNew = ((int) $this->format('m') + $m) % 12; $monthNew = $monthNew === 0 ? 12 : $monthNew < 0 ? 12 + $monthNew : $monthNew; - $dayMonthOld = cal_days_in_month($calendar, (int) $this->format('m'), (int) $this->format('Y')); - $dayMonthNew = cal_days_in_month($calendar, $monthNew, $yearNew); + $dayMonthOld = \cal_days_in_month($calendar, (int) $this->format('m'), (int) $this->format('Y')); + $dayMonthNew = \cal_days_in_month($calendar, $monthNew, $yearNew); $dayOld = (int) $this->format('d'); if ($dayOld > $dayMonthNew) { @@ -219,7 +219,13 @@ class SmartDateTime extends \DateTime */ public static function getDayOfWeek(int $y, int $m, int $d) : int { - return (int) date('w', strtotime($d . '-' . $m . '-' . $y)); + $time = \strtotime($d . '-' . $m . '-' . $y); + + if ($time === false) { + return -1; + } + + return (int) date('w', $time); } /** diff --git a/System/File/FileUtils.php b/System/File/FileUtils.php index c61690791..9b044fe8b 100644 --- a/System/File/FileUtils.php +++ b/System/File/FileUtils.php @@ -92,7 +92,7 @@ final class FileUtils */ public static function absolute(string $origPath) : string { - if (!\file_exists($origPath)) { + if (!\file_exists($origPath) || \realpath($origPath) === false) { $startsWithSlash = strpos($origPath, '/') === 0 ? '/' : ''; $path = []; @@ -106,15 +106,15 @@ final class FileUtils if ($part !== '..') { $path[] = $part; } elseif (!empty($path)) { - array_pop($path); + \array_pop($path); } else { throw new PathException($origPath); } } - return $startsWithSlash . implode('/', $path); + return $startsWithSlash . \implode('/', $path); } - return realpath($origPath); + return \realpath($origPath); } } diff --git a/System/SystemUtils.php b/System/SystemUtils.php index ce40b5a34..729e9a1d3 100644 --- a/System/SystemUtils.php +++ b/System/SystemUtils.php @@ -46,25 +46,27 @@ final class SystemUtils { $mem = 0; - if (stristr(PHP_OS, 'WIN')) { - $mem = null; - exec('wmic memorychip get capacity', $mem); + if (\stristr(PHP_OS, 'WIN')) { + $memArr = []; + exec('wmic memorychip get capacity', $memArr); - /** @var array $mem */ - $mem = array_sum($mem) / 1024; - } elseif (stristr(PHP_OS, 'LINUX')) { - $fh = fopen('/proc/meminfo', 'r'); - $mem = 0; + $mem = \array_sum($memArr) / 1024; + } elseif (\stristr(PHP_OS, 'LINUX')) { + $fh = \fopen('/proc/meminfo', 'r'); - while ($line = fgets($fh)) { + if ($fh === false) { + return $mem; + } + + while ($line = \fgets($fh)) { $pieces = []; if (\preg_match('/^MemTotal:\s+(\d+)\skB$/', $line, $pieces)) { - $mem = $pieces[1] * 1024; + $mem = (int) ($pieces[1] ?? 0) * 1024; break; } } - fclose($fh); + \fclose($fh); } return (int) $mem; @@ -81,12 +83,17 @@ final class SystemUtils { $memUsage = 0; - if (stristr(PHP_OS, 'LINUX')) { - $free = shell_exec('free'); - $free = (string) trim($free); + if (\stristr(PHP_OS, 'LINUX')) { + $free = \shell_exec('free'); + + if ($free === null) { + return $memUsage; + } + + $free = trim($free); $freeArr = \explode("\n", $free); - $mem = \explode(" ", $freeArr[1]); - $mem = array_values(array_filter($mem)); + $mem = \explode(' ', $freeArr[1]); + $mem = \array_values(\array_filter($mem)); $memUsage = $mem[2] / $mem[1] * 100; } @@ -104,11 +111,11 @@ final class SystemUtils { $cpuUsage = 0; - if (stristr(PHP_OS, 'WIN') !== false) { + if (\stristr(PHP_OS, 'WIN') !== false) { $cpuUsage = null; exec('wmic cpu get LoadPercentage', $cpuUsage); $cpuUsage = $cpuUsage[1]; - } elseif (stristr(PHP_OS, 'LINUX') !== false) { + } elseif (\stristr(PHP_OS, 'LINUX') !== false) { $cpuUsage = \sys_getloadavg()[0] * 100; } diff --git a/Utils/ArrayUtils.php b/Utils/ArrayUtils.php index 02733d7e6..839bb9eae 100644 --- a/Utils/ArrayUtils.php +++ b/Utils/ArrayUtils.php @@ -51,8 +51,11 @@ final class ArrayUtils $nodes = \explode($delim, trim($path, $delim)); $prevEl = null; $el = &$data; + $node = null; - $node = null; + if ($nodes === false) { + throw new \Exception(); + } foreach ($nodes as &$node) { $prevEl = &$el; @@ -89,6 +92,10 @@ final class ArrayUtils $pathParts = \explode($delim, trim($path, $delim)); $current = &$data; + if ($pathParts === false) { + throw new \Exception(); + } + foreach ($pathParts as $key) { $current = &$current[$key]; } @@ -124,6 +131,10 @@ final class ArrayUtils $pathParts = \explode($delim, trim($path, $delim)); $current = $data; + if ($pathParts === false) { + throw new \Exception(); + } + foreach ($pathParts as $key) { if (!isset($current[$key])) { return null; @@ -266,14 +277,19 @@ final class ArrayUtils */ public static function arrayToCsv(array $data, string $delimiter = ';', string $enclosure = '"', string $escape = '\\') : string { - $outstream = fopen('php://memory', 'r+'); - /** @noinspection PhpMethodParametersCountMismatchInspection */ - fputcsv($outstream, $data, $delimiter, $enclosure, $escape); - rewind($outstream); - $csv = fgets($outstream); - fclose($outstream); + $outstream = \fopen('php://memory', 'r+'); - return $csv; + if ($outstream === false) { + throw new \Exception(); + } + + /** @noinspection PhpMethodParametersCountMismatchInspection */ + \fputcsv($outstream, $data, $delimiter, $enclosure, $escape); + rewind($outstream); + $csv = \fgets($outstream); + \fclose($outstream); + + return $csv === false ? '' : $csv; } /** @@ -290,11 +306,11 @@ final class ArrayUtils */ public static function getArg(string $id, array $args) : ?string { - if (($key = array_search($id, $args)) === false || $key === count($args) - 1) { + if (($key = \array_search($id, $args)) === false || $key === count($args) - 1) { return null; } - return trim($args[$key + 1], '" '); + return trim($args[(int) $key + 1], '" '); } /** @@ -309,11 +325,11 @@ final class ArrayUtils */ public static function hasArg(string $id, array $args) : ?int { - if (($key = array_search($id, $args)) === false) { + if (($key = \array_search($id, $args)) === false) { return null; } - return $key; + return (int) $key; } /** diff --git a/Utils/Barcode/C128Abstract.php b/Utils/Barcode/C128Abstract.php index 9c730fd8d..e66572cea 100644 --- a/Utils/Barcode/C128Abstract.php +++ b/Utils/Barcode/C128Abstract.php @@ -147,11 +147,11 @@ abstract class C128Abstract public function setDimension(int $width, int $height) : void { if ($width < 0) { - throw new \OutOfBoundsException($width); + throw new \OutOfBoundsException((string) $width); } if ($height < 0) { - throw new \OutOfBoundsException($height); + throw new \OutOfBoundsException((string) $height); } $this->dimension['width'] = $width; @@ -243,8 +243,8 @@ abstract class C128Abstract { $res = $this->get(); - imagepng($res, $file); - imagedestroy($res); + \imagepng($res, $file); + \imagedestroy($res); } /** @@ -260,8 +260,8 @@ abstract class C128Abstract { $res = $this->get(); - imagejpeg($res, $file); - imagedestroy($res); + \imagejpeg($res, $file); + \imagedestroy($res); } /** @@ -273,14 +273,14 @@ abstract class C128Abstract */ protected function generateCodeString() : string { - $keys = array_keys(static::$CODEARRAY); - $values = array_flip($keys); + $keys = \array_keys(static::$CODEARRAY); + $values = \array_flip($keys); $codeString = ''; - $length = strlen($this->content); + $length = \strlen($this->content); $checksum = static::$CHECKSUM; for ($pos = 1; $pos <= $length; $pos++) { - $activeKey = substr($this->content, ($pos - 1), 1); + $activeKey = \substr($this->content, ($pos - 1), 1); $codeString .= static::$CODEARRAY[$activeKey]; $checksum += $values[$activeKey] * $pos; } @@ -302,18 +302,23 @@ abstract class C128Abstract protected function createImage(string $codeString) { $dimensions = $this->calculateDimensions($codeString); - $image = imagecreate($dimensions['width'], $dimensions['height']); - $black = imagecolorallocate($image, 0, 0, 0); - $white = imagecolorallocate($image, 255, 255, 255); + $image = \imagecreate($dimensions['width'], $dimensions['height']); + + if ($image === false) { + throw new \Exception(); + } + + $black = \imagecolorallocate($image, 0, 0, 0); + $white = \imagecolorallocate($image, 255, 255, 255); $location = 0; - $length = strlen($codeString); - imagefill($image, 0, 0, $white); + $length = \strlen($codeString); + \imagefill($image, 0, 0, $white); for ($position = 1; $position <= $length; $position++) { - $cur_size = $location + (int) (substr($codeString, ($position - 1), 1)); + $cur_size = $location + (int) (\substr($codeString, ($position - 1), 1)); if ($this->orientation === OrientationType::HORIZONTAL) { - imagefilledrectangle( + \imagefilledrectangle( $image, $location + $this->margin, 0 + $this->margin, @@ -322,7 +327,7 @@ abstract class C128Abstract ($position % 2 == 0 ? $white : $black) ); } else { - imagefilledrectangle( + \imagefilledrectangle( $image, 0 + $this->margin, $location + $this->margin, @@ -350,10 +355,10 @@ abstract class C128Abstract private function calculateCodeLength(string $codeString) : int { $codeLength = 0; - $length = strlen($codeString); + $length = \strlen($codeString); for ($i = 1; $i <= $length; ++$i) { - $codeLength = $codeLength + (int) (substr($codeString, ($i - 1), 1)); + $codeLength = $codeLength + (int) (\substr($codeString, ($i - 1), 1)); } return $codeLength; diff --git a/Utils/Compression/LZW.php b/Utils/Compression/LZW.php index 3e8cee371..5757f9fe8 100644 --- a/Utils/Compression/LZW.php +++ b/Utils/Compression/LZW.php @@ -39,17 +39,17 @@ class LZW implements CompressionInterface $dictionary[chr($i)] = $i; } - $length = strlen($source); + $length = \strlen($source); for ($i = 0; $i < $length; ++$i) { $c = $source[$i]; $wc = $w . $c; - if (array_key_exists($w . $c, $dictionary)) { + if (\array_key_exists($w . $c, $dictionary)) { $w = $w . $c; } else { $result[] = $dictionary[$w]; $dictionary[$wc] = $dictSize++; - $w = (string) $c; + $w = $c; } } @@ -57,7 +57,7 @@ class LZW implements CompressionInterface $result[] = $dictionary[$w]; } - return implode(',', $result); + return \implode(',', $result); } /** @@ -70,16 +70,20 @@ class LZW implements CompressionInterface $entry = ''; $dictSize = 256; + if (empty($compressed)) { + return ''; + } + for ($i = 0; $i < 256; ++$i) { $dictionary[$i] = chr($i); } - $w = chr($compressed[0]); - $result = $dictionary[$compressed[0]]; + $w = chr((int) $compressed[0]); + $result = $dictionary[(int) ($compressed[0])] ?? 0; $count = count($compressed); for ($i = 1; $i < $count; ++$i) { - $k = $compressed[$i]; + $k = (int) $compressed[$i]; if ($dictionary[$k]) { $entry = $dictionary[$k]; diff --git a/Utils/Converter/Ip.php b/Utils/Converter/Ip.php index a2e686b8b..21a86dad0 100644 --- a/Utils/Converter/Ip.php +++ b/Utils/Converter/Ip.php @@ -49,6 +49,9 @@ class Ip { $split = \explode('.', $ip); - return $split[0] * (256 ** 3) + $split[1] * (256 ** 2) + $split[2] * (256 ** 1) + $split[3]; + return ((int) $split[0] ?? 0) * (256 ** 3) + + ((int) $split[1] ?? 0) * (256 ** 2) + + ((int) $split[2] ?? 0) * (256 ** 1) + + ((int) $split[3] ?? 0); } } diff --git a/Utils/Encoding/Huffman/Huffman.php b/Utils/Encoding/Huffman/Huffman.php index b79f5d7d3..25542ecd9 100644 --- a/Utils/Encoding/Huffman/Huffman.php +++ b/Utils/Encoding/Huffman/Huffman.php @@ -82,11 +82,15 @@ final class Huffman $binary .= $this->dictionary->get($source[$i]); } - $splittedBinaryString = str_split('1' . $binary . '1', 8); + $splittedBinaryString = \str_split('1' . $binary . '1', 8); $binary = ''; + if ($splittedBinaryString === false) { + return $binary; + } + foreach ($splittedBinaryString as $i => $c) { - while (strlen($c) < 8) { + while (\strlen($c) < 8) { $c .= '0'; } @@ -112,22 +116,34 @@ final class Huffman } $binary = ''; - $rawLenght = strlen($raw); + $rawLenght = \strlen($raw); $source = ''; for ($i = 0; $i < $rawLenght; ++$i) { $decbin = decbin(ord($raw[$i])); - while (strlen($decbin) < 8) { + while (\strlen($decbin) < 8) { $decbin = '0' . $decbin; } if ($i === 0) { - $decbin = substr($decbin, strpos($decbin, '1') + 1); + $pos = \strpos($decbin, '1'); + + if ($pos === false) { + throw new \Exception(); + } + + $decbin = \substr($decbin, $pos + 1); } if ($i + 1 === $rawLenght) { - $decbin = substr($decbin, 0, strrpos($decbin, '1')); + $pos = \strrpos($decbin, '1'); + + if ($pos === false) { + throw new \Exception(); + } + + $decbin = \substr($decbin, 0, $pos); } $binary .= $decbin; diff --git a/tests/Utils/Converter/NumericTest.php b/tests/Utils/Converter/NumericTest.php index ffee92f23..ef30364e2 100644 --- a/tests/Utils/Converter/NumericTest.php +++ b/tests/Utils/Converter/NumericTest.php @@ -28,6 +28,17 @@ class NumericTest extends \PHPUnit\Framework\TestCase self::assertEquals('XI', Numeric::arabicToRoman(11)); } + public function testAlphaNumeric() + { + self::assertEquals(0, Numeric::alphaToNumeric('A')); + self::assertEquals(1, Numeric::alphaToNumeric('B')); + self::assertEquals(53, Numeric::alphaToNumeric('BB')); + + self::assertEquals('A', Numeric::numericToAlpha(0)); + self::assertEquals('B', Numeric::numericToAlpha(1)); + self::assertEquals('BB', Numeric::numericToAlpha(53)); + } + public function testBase() { self::assertEquals('443', Numeric::convertBase('123', '0123456789', '01234')); From 2fdc68e7e628410bced38d78f160fbab35ab8a5c Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 22:36:41 +0200 Subject: [PATCH 032/136] More static test fixes --- System/File/Local/FileAbstract.php | 14 ++++++++++---- System/File/Local/LocalStorage.php | 8 +------- System/File/StorageAbstract.php | 13 ++++++++++++- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/System/File/Local/FileAbstract.php b/System/File/Local/FileAbstract.php index 2176205ea..1e4bbf37c 100644 --- a/System/File/Local/FileAbstract.php +++ b/System/File/Local/FileAbstract.php @@ -185,9 +185,15 @@ abstract class FileAbstract implements ContainerInterface */ public function index() : void { - $this->createdAt->setTimestamp(filemtime($this->path)); - $this->changedAt->setTimestamp(filectime($this->path)); - $this->owner = fileowner($this->path); - $this->permission = (int) substr(sprintf('%o', fileperms($this->path)), -4); + $mtime = \filemtime($this->path); + $ctime = \filectime($this->path); + + $this->createdAt->setTimestamp($mtime === false ? 0 : $mtime); + $this->changedAt->setTimestamp($ctime === false ? 0 : $ctime); + + $owner = \fileowner($this->path); + + $this->owner = $owner === false ? 0 : $owner; + $this->permission = (int) \substr(\sprintf('%o', \fileperms($this->path)), -4); } } diff --git a/System/File/Local/LocalStorage.php b/System/File/Local/LocalStorage.php index fc3860de9..f4e7420bf 100644 --- a/System/File/Local/LocalStorage.php +++ b/System/File/Local/LocalStorage.php @@ -54,13 +54,7 @@ class LocalStorage extends StorageAbstract } /** - * Get the internal class type (directory or file) based on path. - * - * @param string $path Path to the directory or file - * - * @return string Class namespace - * - * @since 1.0.0 + * {@inheritdoc} */ protected static function getClassType(string $path) : string { diff --git a/System/File/StorageAbstract.php b/System/File/StorageAbstract.php index d36e09831..48b1d8d37 100644 --- a/System/File/StorageAbstract.php +++ b/System/File/StorageAbstract.php @@ -43,6 +43,17 @@ abstract class StorageAbstract */ abstract public static function getInstance() : StorageAbstract; + /** + * Get the internal class type (directory or file) based on path. + * + * @param string $path Path to the directory or file + * + * @return string Class namespace + * + * @since 1.0.0 + */ + abstract protected static function getClassType(string $path) : string; + /** * Get storage type. * @@ -265,7 +276,7 @@ abstract class StorageAbstract * @param bool $recursive Consider subdirectories * @param array $ignore Files/paths to ignore (no regex) * - * @return string + * @return int * * @since 1.0.0 */ From 67490f42e6dfc47cf57314b240b8636281d68773 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 22:58:44 +0200 Subject: [PATCH 033/136] More type fixes --- Message/Http/Rest.php | 28 ++++++++++++++++------------ Module/InfoManager.php | 4 +++- Module/ModuleManager.php | 17 ++++++++++------- Module/PackageManager.php | 16 ++++++++++++---- Security/PhpCode.php | 9 +++++++-- 5 files changed, 48 insertions(+), 26 deletions(-) diff --git a/Message/Http/Rest.php b/Message/Http/Rest.php index 3bc67adea..edf7f29a0 100644 --- a/Message/Http/Rest.php +++ b/Message/Http/Rest.php @@ -36,35 +36,39 @@ final class Rest */ public static function request(Request $request) : string { - $curl = curl_init(); + $curl = \curl_init(); + + if ($curl === false) { + throw new \Exception(); + } switch ($request->getMethod()) { case RequestMethod::PUT: - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); + \curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); break; case RequestMethod::DELETE: - curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); + \curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'DELETE'); break; } if ($request->getMethod() !== RequestMethod::GET) { - curl_setopt($curl, CURLOPT_POST, 1); + \curl_setopt($curl, CURLOPT_POST, 1); if ($request->getData() !== null) { - curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getData()); + \curl_setopt($curl, CURLOPT_POSTFIELDS, $request->getData()); } } - curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - curl_setopt($curl, CURLOPT_USERPWD, 'username:password'); + \curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + \curl_setopt($curl, CURLOPT_USERPWD, 'username:password'); - curl_setopt($curl, CURLOPT_URL, $request->__toString()); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + \curl_setopt($curl, CURLOPT_URL, $request->__toString()); + \curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - $result = curl_exec($curl); + $result = \curl_exec($curl); - curl_close($curl); + \curl_close($curl); - return $result; + return $result === false ? '' : $result; } } diff --git a/Module/InfoManager.php b/Module/InfoManager.php index 1518f2cb2..053290d0c 100644 --- a/Module/InfoManager.php +++ b/Module/InfoManager.php @@ -85,7 +85,9 @@ final class InfoManager throw new PathException($this->path); } - $this->info = \json_decode(file_get_contents($this->path), true); + $contents = \file_get_contents($this->path . '/info.json'); + $info = \json_decode($contents === false ? '[]' : $contents, true); + $this->info = $info === false ? [] : $info; } /** diff --git a/Module/ModuleManager.php b/Module/ModuleManager.php index 6ddaf99b9..f3e099b5f 100644 --- a/Module/ModuleManager.php +++ b/Module/ModuleManager.php @@ -210,8 +210,9 @@ final class ModuleManager // throw new PathException($path); } - $json = \json_decode(file_get_contents($path), true); - $this->active[$json['name']['internal']] = $json; + $content = \file_get_contents($path); + $json = \json_decode($content === false ? '[]' : $content, true); + $this->active[$json['name']['internal']] = $json === false ? [] : $json; } break; default: @@ -260,8 +261,9 @@ final class ModuleManager // throw new PathException($path); } - $json = \json_decode(file_get_contents($path), true); - $this->all[$json['name']['internal']] = $json; + $content = \file_get_contents($path); + $json = \json_decode($content === false ? '[]' : $content, true); + $this->all[$json['name']['internal']] = $json === false ? [] : $json; } } @@ -306,8 +308,9 @@ final class ModuleManager // throw new PathException($path); } - $json = \json_decode(file_get_contents($path), true); - $this->installed[$json['name']['internal']] = $json; + $content = \file_get_contents($path); + $json = \json_decode($content === false ? '[]' : $content, true); + $this->installed[$json['name']['internal']] = $json === false ? [] : $json; } break; @@ -330,7 +333,7 @@ final class ModuleManager */ private function loadInfo(string $module) : InfoManager { - $path = realpath($oldPath = $this->modulePath . '/' . $module . '/info.json'); + $path = \realpath($oldPath = $this->modulePath . '/' . $module . '/info.json'); if ($path === false) { throw new PathException($oldPath); diff --git a/Module/PackageManager.php b/Module/PackageManager.php index b336ec7b6..d88d32bdb 100644 --- a/Module/PackageManager.php +++ b/Module/PackageManager.php @@ -109,7 +109,9 @@ final class PackageManager throw new PathException($this->extractPath); } - $this->info = \json_decode(file_get_contents($this->extractPath . '/info.json'), true); + $contents = \file_get_contents($this->extractPath . '/info.json'); + $info = \json_decode($contents === false ? '[]' : $contents, true); + $this->info = $info === false ? [] : $info; } /** @@ -121,7 +123,8 @@ final class PackageManager */ public function isValid() : bool { - return $this->authenticate(file_get_contents($this->extractPath . '/package.cert'), $this->hashFiles()); + $contents = \file_get_contents($this->extractPath . '/package.cert'); + return $this->authenticate($contents === false ? '' : $contents, $this->hashFiles()); } /** @@ -141,10 +144,15 @@ final class PackageManager continue; } - \sodium_crypto_generichash_update($state, \file_get_contents($this->extractPath . '/package/' . $file)); + $contents = \file_get_contents($this->extractPath . '/package/' . $file); + if ($contents === false) { + throw new \Exception(); + } + + \sodium_crypto_generichash_update($state, $contents); } - return \sodium_crypto_generichash_final(); + return \sodium_crypto_generichash_final($state); } /** diff --git a/Security/PhpCode.php b/Security/PhpCode.php index 716246bd9..b3d403141 100644 --- a/Security/PhpCode.php +++ b/Security/PhpCode.php @@ -104,7 +104,12 @@ final class PhpCode */ public static function isDisabled(array $functions) : bool { - $disabled = ini_get('disable_functions'); + $disabled = \ini_get('disable_functions'); + + if ($disabled === false) { + return true; + } + $disabled = \str_replace(' ', '', $disabled); $disabled = \explode(',', $disabled); @@ -149,6 +154,6 @@ final class PhpCode */ public static function validateFileIntegrity(string $source, string $hash) : bool { - return md5_file($source) === $hash; + return \md5_file($source) === $hash; } } From adf83f08676cfff8ce1e4ce4338046206db3f031 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 23:06:58 +0200 Subject: [PATCH 034/136] Fix path --- Module/InfoManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Module/InfoManager.php b/Module/InfoManager.php index 053290d0c..197f0c479 100644 --- a/Module/InfoManager.php +++ b/Module/InfoManager.php @@ -85,7 +85,7 @@ final class InfoManager throw new PathException($this->path); } - $contents = \file_get_contents($this->path . '/info.json'); + $contents = \file_get_contents($this->path); $info = \json_decode($contents === false ? '[]' : $contents, true); $this->info = $info === false ? [] : $info; } From 23eb9ab80a99e8fcd5a92c4fd247ba2d145e766d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 14 Jul 2018 23:41:51 +0200 Subject: [PATCH 035/136] More type fixes --- Localization/Defaults/Iban.php | 2 +- Localization/Money.php | 17 +++-- Log/FileLogger.php | 86 +++++++++++++++--------- Math/Exception/ZeroDevisionException.php | 3 +- Math/Functions/Functions.php | 2 +- Math/Geometry/Shape/D2/Polygon.php | 2 +- Math/Geometry/Shape/D3/Sphere.php | 2 +- Math/Matrix/Matrix.php | 6 +- Math/Number/Integer.php | 6 +- Math/Number/Numbers.php | 8 ++- Math/Statistic/Average.php | 4 +- 11 files changed, 84 insertions(+), 54 deletions(-) diff --git a/Localization/Defaults/Iban.php b/Localization/Defaults/Iban.php index b84c55c07..c008a6535 100644 --- a/Localization/Defaults/Iban.php +++ b/Localization/Defaults/Iban.php @@ -43,7 +43,7 @@ final class Iban /** * Iban chars. * - * @var string + * @var int * @since 1.0.0 */ private $chars = 2; diff --git a/Localization/Money.php b/Localization/Money.php index d3534fc8e..c5085db47 100644 --- a/Localization/Money.php +++ b/Localization/Money.php @@ -107,6 +107,11 @@ final class Money implements \Serializable public static function toInt(string $value, string $thousands = ',', string $decimal = '.') : int { $split = \explode($decimal, $value); + + if ($split === false) { + throw new \Exception(); + } + $left = $split[0]; $left = \str_replace($thousands, '', $left); $right = ''; @@ -115,9 +120,9 @@ final class Money implements \Serializable $right = $split[1]; } - $right = substr($right, 0, self::MAX_DECIMALS); + $right = \substr($right, 0, self::MAX_DECIMALS); - return ((int) $left) * 10 ** self::MAX_DECIMALS + (int) str_pad($right, self::MAX_DECIMALS, '0'); + return ((int) $left) * 10 ** self::MAX_DECIMALS + (int) \str_pad($right, self::MAX_DECIMALS, '0'); } /** @@ -185,10 +190,10 @@ final class Money implements \Serializable { $value = (string) round($this->value, -self::MAX_DECIMALS + $decimals); - $left = substr($value, 0, -self::MAX_DECIMALS); - $right = substr($value, -self::MAX_DECIMALS); + $left = \substr($value, 0, -self::MAX_DECIMALS); + $right = \substr($value, -self::MAX_DECIMALS); - return ($decimals > 0) ? number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . substr($right, 0, $decimals) : (string) $left; + return ($decimals > 0) ? number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals) : $left; } /** @@ -309,7 +314,7 @@ final class Money implements \Serializable public function pow($value) : Money { if (is_float($value) || is_int($value)) { - $this->value = $this->value ** $value; + $this->value = (int) ($this->value ** $value); } return $this; diff --git a/Log/FileLogger.php b/Log/FileLogger.php index c7b37c44d..b8f0ec565 100644 --- a/Log/FileLogger.php +++ b/Log/FileLogger.php @@ -98,10 +98,10 @@ final class FileLogger implements LoggerInterface */ public function __construct(string $lpath, bool $verbose = false) { - $path = realpath($lpath); + $path = \realpath($lpath); $this->verbose = $verbose; - if (is_dir($lpath) || strpos($lpath, '.') === false) { + if (\is_dir($lpath) || \strpos($lpath, '.') === false) { $path = $lpath . '/' . date('Y-m-d') . '.log'; } else { $path = $lpath; @@ -155,7 +155,7 @@ final class FileLogger implements LoggerInterface public function __destruct() { if (is_resource($this->fp)) { - fclose($this->fp); + \fclose($this->fp); } } @@ -187,7 +187,7 @@ final class FileLogger implements LoggerInterface } $mtime = \explode(' ', microtime()); - $mtime = $mtime[1] + $mtime[0]; + $mtime = (int) $mtime[1] + (int) $mtime[0]; self::$timings[$id] = ['start' => $mtime]; @@ -206,7 +206,7 @@ final class FileLogger implements LoggerInterface public static function endTimeLog($id = '') : float { $mtime = \explode(' ', microtime()); - $mtime = $mtime[1] + $mtime[0]; + $mtime = (int) $mtime[1] + (int) $mtime[0]; self::$timings[$id]['end'] = $mtime; self::$timings[$id]['time'] = $mtime - self::$timings[$id]['start']; @@ -267,17 +267,17 @@ final class FileLogger implements LoggerInterface private function write(string $message) : void { $this->createFile(); - if (!is_writable($this->path)) { + if (!\is_writable($this->path)) { return; } - $this->fp = fopen($this->path, 'a'); + $this->fp = \fopen($this->path, 'a'); - if (flock($this->fp, LOCK_EX) && $this->fp !== false) { - fwrite($this->fp, $message . "\n"); - fflush($this->fp); - flock($this->fp, LOCK_UN); - fclose($this->fp); + if ($this->fp !== false && \flock($this->fp, LOCK_EX)) { + \fwrite($this->fp, $message . "\n"); + \fflush($this->fp); + \flock($this->fp, LOCK_UN); + \fclose($this->fp); $this->fp = false; } @@ -386,10 +386,15 @@ final class FileLogger implements LoggerInterface return $levels; } - $this->fp = fopen($this->path, 'r'); - fseek($this->fp, 0); + $this->fp = \fopen($this->path, 'r'); - while (($line = fgetcsv($this->fp, 0, ';')) !== false) { + if ($this->fp === false) { + return $levels; + } + + \fseek($this->fp, 0); + + while (($line = \fgetcsv($this->fp, 0, ';')) !== false) { $line[1] = trim($line[1]); if (!isset($levels[$line[1]])) { @@ -399,8 +404,8 @@ final class FileLogger implements LoggerInterface $levels[$line[1]]++; } - fseek($this->fp, 0, SEEK_END); - fclose($this->fp); + \fseek($this->fp, 0, SEEK_END); + \fclose($this->fp); return $levels; } @@ -422,10 +427,15 @@ final class FileLogger implements LoggerInterface return $connection; } - $this->fp = fopen($this->path, 'r'); - fseek($this->fp, 0); + $this->fp = \fopen($this->path, 'r'); - while (($line = fgetcsv($this->fp, 0, ';')) !== false) { + if ($this->fp === false) { + return $connection; + } + + \fseek($this->fp, 0); + + while (($line = \fgetcsv($this->fp, 0, ';')) !== false) { $line[2] = trim($line[2]); if (!isset($connection[$line[2]])) { @@ -435,8 +445,8 @@ final class FileLogger implements LoggerInterface $connection[$line[2]]++; } - fseek($this->fp, 0, SEEK_END); - fclose($this->fp); + \fseek($this->fp, 0, SEEK_END); + \fclose($this->fp); asort($connection); return array_slice($connection, 0, $limit); @@ -461,10 +471,16 @@ final class FileLogger implements LoggerInterface return $logs; } - $this->fp = fopen($this->path, 'r'); - fseek($this->fp, 0); + $this->fp = \fopen($this->path, 'r'); - while (($line = fgetcsv($this->fp, 0, ';')) !== false) { + if ($this->fp === false) { + return $logs; + } + + \fseek($this->fp, 0); + + $line = \fgetcsv($this->fp, 0, ';'); + while ($line !== false && $line !== null) { $id++; if ($offset > 0) { @@ -484,10 +500,11 @@ final class FileLogger implements LoggerInterface $logs[$id] = $line; $limit--; ksort($logs); + $line = \fgetcsv($this->fp, 0, ';'); } - fseek($this->fp, 0, SEEK_END); - fclose($this->fp); + \fseek($this->fp, 0, SEEK_END); + \fclose($this->fp); return $logs; } @@ -510,10 +527,15 @@ final class FileLogger implements LoggerInterface return $log; } - $this->fp = fopen($this->path, 'r'); - fseek($this->fp, 0); + $this->fp = \fopen($this->path, 'r'); - while (($line = fgetcsv($this->fp, 0, ';')) !== false && $current <= $id) { + if ($this->fp === false) { + return $log; + } + + \fseek($this->fp, 0); + + while (($line = \fgetcsv($this->fp, 0, ';')) !== false && $current <= $id) { $current++; if ($current < $id) { @@ -533,8 +555,8 @@ final class FileLogger implements LoggerInterface break; } - fseek($this->fp, 0, SEEK_END); - fclose($this->fp); + \fseek($this->fp, 0, SEEK_END); + \fclose($this->fp); return $log; } diff --git a/Math/Exception/ZeroDevisionException.php b/Math/Exception/ZeroDevisionException.php index ed3ba5417..538d463ea 100644 --- a/Math/Exception/ZeroDevisionException.php +++ b/Math/Exception/ZeroDevisionException.php @@ -27,13 +27,12 @@ final class ZeroDevisionException extends \UnexpectedValueException /** * Constructor. * - * @param string $message Exception message * @param int $code Exception code * @param \Exception $previous Previous exception * * @since 1.0.0 */ - public function __construct(string $message = '', int $code = 0, \Exception $previous = null) + public function __construct(int $code = 0, \Exception $previous = null) { parent::__construct('Devision by zero is not defined.', $code, $previous); } diff --git a/Math/Functions/Functions.php b/Math/Functions/Functions.php index b82794bdc..36d1702b1 100644 --- a/Math/Functions/Functions.php +++ b/Math/Functions/Functions.php @@ -315,6 +315,6 @@ final class Functions */ public static function getRelativeDegree(int $value, int $length, int $start = 0) : int { - return (int) abs(self::mod($value - $start, $length)); + return abs(self::mod($value - $start, $length)); } } diff --git a/Math/Geometry/Shape/D2/Polygon.php b/Math/Geometry/Shape/D2/Polygon.php index ca67290c9..f718507c3 100644 --- a/Math/Geometry/Shape/D2/Polygon.php +++ b/Math/Geometry/Shape/D2/Polygon.php @@ -192,7 +192,7 @@ final class Polygon implements D2ShapeInterface */ public function getSurface() : float { - return (float) abs($this->getSignedSurface()); + return abs($this->getSignedSurface()); } /** diff --git a/Math/Geometry/Shape/D3/Sphere.php b/Math/Geometry/Shape/D3/Sphere.php index e440f3db6..64debdbb1 100644 --- a/Math/Geometry/Shape/D3/Sphere.php +++ b/Math/Geometry/Shape/D3/Sphere.php @@ -116,7 +116,7 @@ final class Sphere implements D3ShapeInterface */ public static function getRadiusByVolume(float $v) : float { - return (float) pow($v * 3 / (4 * pi()), 1 / 3); + return pow($v * 3 / (4 * pi()), 1 / 3); } /** diff --git a/Math/Matrix/Matrix.php b/Math/Matrix/Matrix.php index 2f41933ad..135de8fba 100644 --- a/Math/Matrix/Matrix.php +++ b/Math/Matrix/Matrix.php @@ -402,7 +402,7 @@ class Matrix implements \ArrayAccess, \Iterator { if ($value instanceof Matrix) { return $this->add($value->mult(-1)); - } elseif (is_numeric($value)) { + } elseif (!is_string($value) && is_numeric($value)) { return $this->add(-$value); } @@ -424,7 +424,7 @@ class Matrix implements \ArrayAccess, \Iterator { if ($value instanceof Matrix) { return $this->addMatrix($value); - } elseif (is_numeric($value)) { + } elseif (!is_string($value) && is_numeric($value)) { return $this->addScalar($value); } @@ -529,7 +529,7 @@ class Matrix implements \ArrayAccess, \Iterator { if ($value instanceof Matrix) { return $this->multMatrix($value); - } elseif (is_numeric($value)) { + } elseif (!is_string($value) && is_numeric($value)) { return $this->multScalar($value); } diff --git a/Math/Number/Integer.php b/Math/Number/Integer.php index 0f503e187..91a7f6586 100644 --- a/Math/Number/Integer.php +++ b/Math/Number/Integer.php @@ -138,7 +138,7 @@ final class Integer } } - return (int) $m; + return $m; } /** @@ -160,13 +160,13 @@ final class Integer } $a = (int) ceil(sqrt($value)); - $b2 = (int) ($a * $a - $value); + $b2 = ($a * $a - $value); $i = 1; while (!Numbers::isSquare($b2) && $i < $limit) { $i++; $a += 1; - $b2 = (int) ($a * $a - $value); + $b2 = ($a * $a - $value); } return [(int) round($a - sqrt($b2)), (int) round($a + sqrt($b2))]; diff --git a/Math/Number/Numbers.php b/Math/Number/Numbers.php index 454634d1b..0eb76b044 100644 --- a/Math/Number/Numbers.php +++ b/Math/Number/Numbers.php @@ -69,10 +69,14 @@ final class Numbers public static function isSelfdescribing(int $n) : bool { $n = (string) $n; - $split = str_split($n); + $split = \str_split($n); + + if ($split === false) { + return false; + } foreach ($split as $place => $value) { - if (substr_count($n, (string) $place) != $value) { + if (\substr_count($n, (string) $place) != $value) { return false; } } diff --git a/Math/Statistic/Average.php b/Math/Statistic/Average.php index 48d7ed4fc..8f52a7233 100644 --- a/Math/Statistic/Average.php +++ b/Math/Statistic/Average.php @@ -168,7 +168,7 @@ final class Average * * @return float * - * @throws phpOMS\Math\Exception\ZeroDevisionException + * @throws ZeroDevisionException * * @since 1.0.0 */ @@ -252,7 +252,7 @@ final class Average throw new ZeroDevisionException(); } - return (float) pow(array_product($values), 1 / $count); + return pow(\array_product($values), 1 / $count); } /** From da9b2d3406ee0e5452631e0a42f74ae8a9c4ee84 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 15 Jul 2018 00:04:08 +0200 Subject: [PATCH 036/136] Fix mini bugs --- Log/FileLogger.php | 12 ++++++------ tests/Log/FileLoggerTest.php | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Log/FileLogger.php b/Log/FileLogger.php index b8f0ec565..ce84e89c4 100644 --- a/Log/FileLogger.php +++ b/Log/FileLogger.php @@ -186,8 +186,8 @@ final class FileLogger implements LoggerInterface return false; } - $mtime = \explode(' ', microtime()); - $mtime = (int) $mtime[1] + (int) $mtime[0]; + $temp = \explode(' ', \microtime()); + $mtime = ((float) $temp[1]) + ((float) $temp[0]); self::$timings[$id] = ['start' => $mtime]; @@ -205,8 +205,8 @@ final class FileLogger implements LoggerInterface */ public static function endTimeLog($id = '') : float { - $mtime = \explode(' ', microtime()); - $mtime = (int) $mtime[1] + (int) $mtime[0]; + $temp = \explode(' ', \microtime()); + $mtime = ((float) $temp[1]) + ((float) $temp[0]); self::$timings[$id]['end'] = $mtime; self::$timings[$id]['time'] = $mtime - self::$timings[$id]['start']; @@ -532,7 +532,7 @@ final class FileLogger implements LoggerInterface if ($this->fp === false) { return $log; } - + \fseek($this->fp, 0); while (($line = \fgetcsv($this->fp, 0, ';')) !== false && $current <= $id) { @@ -579,7 +579,7 @@ final class FileLogger implements LoggerInterface } if ($verbose) { - echo $message; + echo $this->interpolate($message, $context); } else { $this->info($message, $context); } diff --git a/tests/Log/FileLoggerTest.php b/tests/Log/FileLoggerTest.php index 8ee028563..a9e07e858 100644 --- a/tests/Log/FileLoggerTest.php +++ b/tests/Log/FileLoggerTest.php @@ -55,7 +55,7 @@ class FileLoggerTest extends \PHPUnit\Framework\TestCase unlink(__DIR__ . '/test.log'); } - $log = new FileLogger(__DIR__ . '/test.log', true); + $log = new FileLogger(__DIR__ . '/test.log', false); $log->emergency(FileLogger::MSG_FULL, [ 'message' => 'msg', @@ -121,17 +121,17 @@ class FileLoggerTest extends \PHPUnit\Framework\TestCase self::assertEquals(2, $log->countLogs()['debug'] ?? 0); self::assertEquals(['0.0.0.0' => 9], $log->getHighestPerpetrator()); - self::assertEquals([5, 6, 7, 8, 9], array_keys($log->get(5, 1))); + self::assertEquals([6, 7, 8, 9, 10], array_keys($log->get(5, 1))); self::assertEquals('alert', $log->getByLine(2)['level']); ob_start(); - $log->console(FileLogger::MSG_FULL, false, [ + $log->console(FileLogger::MSG_FULL, true, [ 'message' => 'msg', 'line' => 11, 'file' => FileLoggerTest::class, ]); $ob = ob_get_clean(); - self::assertEquals(2, $log->countLogs()['info'] ?? 0); + self::assertEquals(1, $log->countLogs()['info'] ?? 0); self::assertTrue(stripos($ob, 'msg;') !== false); ob_start(); @@ -165,7 +165,7 @@ class FileLoggerTest extends \PHPUnit\Framework\TestCase { self::assertTrue(FileLogger::startTimeLog('test')); self::assertFalse(FileLogger::startTimeLog('test')); - self::assertGreaterThan(0, FileLogger::endTimeLog('test')); + self::assertGreaterThan(0.0, FileLogger::endTimeLog('test')); } public static function tearDownAfterClass() From 6843ac554849d392ae44efb275559bb3f55277b8 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 15 Jul 2018 10:46:34 +0200 Subject: [PATCH 037/136] Type check fixes --- .../Cache/Connection/ConnectionAbstract.php | 2 +- .../Database/Connection/MysqlConnection.php | 2 +- .../Connection/PostgresConnection.php | 2 +- .../Database/Connection/SQLiteConnection.php | 11 ++++--- DataStorage/Database/DatabaseType.php | 2 +- .../Database/Query/Grammar/SQLiteGrammar.php | 2 +- .../Database/Schema/Grammar/MysqlGrammar.php | 2 +- .../Schema/Grammar/PostgresGrammar.php | 2 +- .../Database/Schema/Grammar/SQLiteGrammar.php | 2 +- DataStorage/Session/HttpSession.php | 4 +-- DataStorage/Session/SessionInterface.php | 4 +-- .../Distribution/BinomialDistribution.php | 2 +- .../Distribution/ChiSquaredDistribution.php | 9 ++--- .../Distribution/ExponentialDistribution.php | 2 +- .../Distribution/GeometricDistribution.php | 2 +- .../Distribution/PoissonDistribution.php | 6 ++-- Message/Http/Request.php | 16 +++++---- Message/Mail/Mail.php | 2 +- Module/InstallerAbstract.php | 2 +- System/File/ContainerInterface.php | 2 +- Utils/IO/Zip/Gz.php | 33 ++++++++++--------- Utils/TaskSchedule/Cron.php | 28 +++++++++------- 22 files changed, 76 insertions(+), 63 deletions(-) diff --git a/DataStorage/Cache/Connection/ConnectionAbstract.php b/DataStorage/Cache/Connection/ConnectionAbstract.php index 83fa481f0..8baac3b3b 100644 --- a/DataStorage/Cache/Connection/ConnectionAbstract.php +++ b/DataStorage/Cache/Connection/ConnectionAbstract.php @@ -39,7 +39,7 @@ abstract class ConnectionAbstract implements ConnectionInterface * @var mixed * @since 1.0.0 */ - private $con = null; + protected $con = null; /** * Database prefix. diff --git a/DataStorage/Database/Connection/MysqlConnection.php b/DataStorage/Database/Connection/MysqlConnection.php index a05fc19b3..92676ab56 100644 --- a/DataStorage/Database/Connection/MysqlConnection.php +++ b/DataStorage/Database/Connection/MysqlConnection.php @@ -59,7 +59,7 @@ final class MysqlConnection extends ConnectionAbstract $this->dbdata = isset($dbdata) ? $dbdata : $this->dbdata; if (!isset($this->dbdata['db'], $this->dbdata['host'], $this->dbdata['port'], $this->dbdata['database'], $this->dbdata['login'], $this->dbdata['password'])) { - throw new InvalidConnectionConfigException(\json_encode($this->dbdata)); + throw new InvalidConnectionConfigException((string) \json_encode($this->dbdata)); } $this->close(); diff --git a/DataStorage/Database/Connection/PostgresConnection.php b/DataStorage/Database/Connection/PostgresConnection.php index 33fa94d48..ae61b9338 100644 --- a/DataStorage/Database/Connection/PostgresConnection.php +++ b/DataStorage/Database/Connection/PostgresConnection.php @@ -58,7 +58,7 @@ final class PostgresConnection extends ConnectionAbstract $this->dbdata = isset($dbdata) ? $dbdata : $this->dbdata; if (!isset($this->dbdata['db'], $this->dbdata['host'], $this->dbdata['port'], $this->dbdata['database'], $this->dbdata['login'], $this->dbdata['password'])) { - throw new InvalidConnectionConfigException(\json_encode($this->dbdata)); + throw new InvalidConnectionConfigException((string) \json_encode($this->dbdata)); } $this->close(); diff --git a/DataStorage/Database/Connection/SQLiteConnection.php b/DataStorage/Database/Connection/SQLiteConnection.php index 5e45f345f..23374e332 100644 --- a/DataStorage/Database/Connection/SQLiteConnection.php +++ b/DataStorage/Database/Connection/SQLiteConnection.php @@ -16,7 +16,7 @@ namespace phpOMS\DataStorage\Database\Connection; use phpOMS\DataStorage\Database\DatabaseStatus; use phpOMS\DataStorage\Database\DatabaseType; -use phpOMS\DataStorage\Database\Query\Grammar\SqliteGrammar; +use phpOMS\DataStorage\Database\Query\Grammar\SQLiteGrammar; /** * Database handler. @@ -29,7 +29,7 @@ use phpOMS\DataStorage\Database\Query\Grammar\SqliteGrammar; * @link http://website.orange-management.de * @since 1.0.0 */ -final class SqliteConnection extends ConnectionAbstract +final class SQLiteConnection extends ConnectionAbstract { /** @@ -43,8 +43,8 @@ final class SqliteConnection extends ConnectionAbstract */ public function __construct(array $dbdata) { - $this->type = DatabaseType::MYSQL; - $this->grammar = new SqliteGrammar(); + $this->type = DatabaseType::SQLITE; + $this->grammar = new SQLiteGrammar(); $this->connect($dbdata); } @@ -65,9 +65,10 @@ final class SqliteConnection extends ConnectionAbstract $this->status = DatabaseStatus::OK; } catch (\PDOException $e) { - var_dump($e->getMessage()); $this->status = DatabaseStatus::MISSING_DATABASE; $this->con = null; + } finally { + $this->dbdata['password'] = '****'; } } } diff --git a/DataStorage/Database/DatabaseType.php b/DataStorage/Database/DatabaseType.php index 2999a3ace..8fa1a2491 100644 --- a/DataStorage/Database/DatabaseType.php +++ b/DataStorage/Database/DatabaseType.php @@ -30,7 +30,7 @@ abstract class DatabaseType extends Enum { public const MYSQL = 'mysql'; /* MySQL */ public const SQLITE = 'sqlite'; /* SQLITE */ - public const PGSQL = 2; /* PostgreSQL */ + public const PGSQL = 'postgresql'; /* PostgreSQL */ public const ORACLE = 3; /* Oracle */ public const SQLSRV = 'mssql'; /* Microsoft SQL Server */ } diff --git a/DataStorage/Database/Query/Grammar/SQLiteGrammar.php b/DataStorage/Database/Query/Grammar/SQLiteGrammar.php index d77483f85..056a8d6c5 100644 --- a/DataStorage/Database/Query/Grammar/SQLiteGrammar.php +++ b/DataStorage/Database/Query/Grammar/SQLiteGrammar.php @@ -24,7 +24,7 @@ use phpOMS\DataStorage\Database\Query\Builder; * @link http://website.orange-management.de * @since 1.0.0 */ -class SqliteGrammar extends Grammar +class SQLiteGrammar extends Grammar { /** diff --git a/DataStorage/Database/Schema/Grammar/MysqlGrammar.php b/DataStorage/Database/Schema/Grammar/MysqlGrammar.php index ea86d288e..43e2e9270 100644 --- a/DataStorage/Database/Schema/Grammar/MysqlGrammar.php +++ b/DataStorage/Database/Schema/Grammar/MysqlGrammar.php @@ -67,7 +67,7 @@ class MysqlGrammar extends Grammar */ protected function compileFrom(Builder $query, array $table) : string { - $expression = $this->expressionizeTableColumn('information_schema.tables'); + $expression = $this->expressionizeTableColumn(['information_schema.tables']); return 'FROM ' . $expression; } diff --git a/DataStorage/Database/Schema/Grammar/PostgresGrammar.php b/DataStorage/Database/Schema/Grammar/PostgresGrammar.php index 51ae131e8..6dfe5424f 100644 --- a/DataStorage/Database/Schema/Grammar/PostgresGrammar.php +++ b/DataStorage/Database/Schema/Grammar/PostgresGrammar.php @@ -14,7 +14,7 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Database\Schema\Grammar; -class PostgresGrammar +class PostgresGrammar extends Grammar { } diff --git a/DataStorage/Database/Schema/Grammar/SQLiteGrammar.php b/DataStorage/Database/Schema/Grammar/SQLiteGrammar.php index da4a7dd52..448fe9a91 100644 --- a/DataStorage/Database/Schema/Grammar/SQLiteGrammar.php +++ b/DataStorage/Database/Schema/Grammar/SQLiteGrammar.php @@ -14,7 +14,7 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Database\Schema\Grammar; -class SQLiteGrammar +class SQLiteGrammar extends Grammar { } diff --git a/DataStorage/Session/HttpSession.php b/DataStorage/Session/HttpSession.php index 2d66dc3a2..443fb5e38 100644 --- a/DataStorage/Session/HttpSession.php +++ b/DataStorage/Session/HttpSession.php @@ -50,7 +50,7 @@ class HttpSession implements SessionInterface /** * Session ID. * - * @var string|int + * @var string|int|null * @since 1.0.0 */ private $sid = null; @@ -85,7 +85,7 @@ class HttpSession implements SessionInterface } if (!\is_bool($sid)) { - \session_id($sid); + \session_id((string) $sid); } $this->inactivityInterval = $inactivityInterval; diff --git a/DataStorage/Session/SessionInterface.php b/DataStorage/Session/SessionInterface.php index 98d3b68a5..2e8e6eb77 100644 --- a/DataStorage/Session/SessionInterface.php +++ b/DataStorage/Session/SessionInterface.php @@ -74,14 +74,14 @@ interface SessionInterface public function save() : void; /** - * @return int|string + * @return int|string|null * * @since 1.0.0 */ public function getSID(); /** - * @param int|string $sid Session id + * @param int|string|null $sid Session id * * @return void * diff --git a/Math/Stochastic/Distribution/BinomialDistribution.php b/Math/Stochastic/Distribution/BinomialDistribution.php index ef62eb044..82a49127c 100644 --- a/Math/Stochastic/Distribution/BinomialDistribution.php +++ b/Math/Stochastic/Distribution/BinomialDistribution.php @@ -57,7 +57,7 @@ class BinomialDistribution */ public static function getMgf(int $n, float $t, float $p) : float { - return (float) pow(1 - $p + $p * exp($t), $n); + return pow(1 - $p + $p * exp($t), $n); } /** diff --git a/Math/Stochastic/Distribution/ChiSquaredDistribution.php b/Math/Stochastic/Distribution/ChiSquaredDistribution.php index 80d472bcc..18547f119 100644 --- a/Math/Stochastic/Distribution/ChiSquaredDistribution.php +++ b/Math/Stochastic/Distribution/ChiSquaredDistribution.php @@ -31,7 +31,7 @@ class ChiSquaredDistribution /** * Chi square table. * - * @var array + * @var array> * @since 1.0.0 */ public const TABLE = [ @@ -106,7 +106,7 @@ class ChiSquaredDistribution $df = self::getDegreesOfFreedom($dataset); } - if (!defined(self::TABLE[$df])) { + if (!defined('self::TABLE') || !array_key_exists($df, self::TABLE)) { throw new \Exception('Degrees of freedom not supported'); } @@ -117,7 +117,8 @@ class ChiSquaredDistribution } } - $p = 1 - ($p ?? key(end(self::TABLE[$df]))); + $key = key(end(self::TABLE[$df])); + $p = 1 - ($p ?? ($key === false ? 1 : (float) $key)); return ['P' => $p, 'H0' => ($p > $significance), 'df' => $df]; } @@ -235,7 +236,7 @@ class ChiSquaredDistribution throw new \Exception('Out of bounds'); } - return (float) pow(1 - 2 * $t, -$df / 2); + return pow(1 - 2 * $t, -$df / 2); } /** diff --git a/Math/Stochastic/Distribution/ExponentialDistribution.php b/Math/Stochastic/Distribution/ExponentialDistribution.php index d53ed6303..43be19014 100644 --- a/Math/Stochastic/Distribution/ExponentialDistribution.php +++ b/Math/Stochastic/Distribution/ExponentialDistribution.php @@ -105,7 +105,7 @@ class ExponentialDistribution */ public static function getVariance(float $lambda) : float { - return (float) pow($lambda, -2); + return pow($lambda, -2); } /** diff --git a/Math/Stochastic/Distribution/GeometricDistribution.php b/Math/Stochastic/Distribution/GeometricDistribution.php index 84ec3bf70..fdbca94ad 100644 --- a/Math/Stochastic/Distribution/GeometricDistribution.php +++ b/Math/Stochastic/Distribution/GeometricDistribution.php @@ -36,7 +36,7 @@ class GeometricDistribution */ public static function getPmf(float $p, int $k) : float { - return (float) pow(1 - $p, $k - 1) * $p; + return pow(1 - $p, $k - 1) * $p; } /** diff --git a/Math/Stochastic/Distribution/PoissonDistribution.php b/Math/Stochastic/Distribution/PoissonDistribution.php index 438982080..94d6d9088 100644 --- a/Math/Stochastic/Distribution/PoissonDistribution.php +++ b/Math/Stochastic/Distribution/PoissonDistribution.php @@ -147,7 +147,7 @@ class PoissonDistribution */ public static function getSkewness(float $lambda) : float { - return (float) pow($lambda, -1 / 2); + return pow($lambda, -1 / 2); } /** @@ -161,7 +161,7 @@ class PoissonDistribution */ public static function getFisherInformation(float $lambda) : float { - return (float) pow($lambda, -1); + return pow($lambda, -1); } /** @@ -175,7 +175,7 @@ class PoissonDistribution */ public static function getExKurtosis(float $lambda) : float { - return (float) pow($lambda, -1); + return pow($lambda, -1); } public static function getRandom() diff --git a/Message/Http/Request.php b/Message/Http/Request.php index 834db20b8..8101a5efb 100644 --- a/Message/Http/Request.php +++ b/Message/Http/Request.php @@ -140,13 +140,16 @@ final class Request extends RequestAbstract { if (isset($_SERVER['CONTENT_TYPE'])) { if (\stripos($_SERVER['CONTENT_TYPE'], 'application/json') !== false) { - if (($json = \json_decode(($input = \file_get_contents('php://input')), true)) === false || $json === null) { + $input = \file_get_contents('php://input'); + $json = \json_decode($input === false ? '' : $input, true); + if ($input === false || $json === false || $json === null) { throw new \Exception('Is not valid json ' . $input); } $this->data += $json; } elseif (\stripos($_SERVER['CONTENT_TYPE'], 'application/x-www-form-urlencoded') !== false) { - parse_str(file_get_contents('php://input'), $temp); + $content = \file_get_contents('php://input'); + \parse_str($content === false ? '' : $content, $temp); $this->data += $temp; } } @@ -292,7 +295,7 @@ final class Request extends RequestAbstract { if ($this->browser === null) { $arr = BrowserType::getConstants(); - $httpUserAgent = strtolower($_SERVER['HTTP_USER_AGENT']); + $httpUserAgent = \strtolower($_SERVER['HTTP_USER_AGENT']); foreach ($arr as $key => $val) { if (stripos($httpUserAgent, $val)) { @@ -333,10 +336,10 @@ final class Request extends RequestAbstract { if ($this->os === null) { $arr = OSType::getConstants(); - $httpUserAgent = strtolower($_SERVER['HTTP_USER_AGENT']); + $httpUserAgent = \strtolower($_SERVER['HTTP_USER_AGENT']); foreach ($arr as $key => $val) { - if (stripos($httpUserAgent, $val)) { + if (\stripos($httpUserAgent, $val)) { $this->os = $val; return $this->os; @@ -397,7 +400,8 @@ final class Request extends RequestAbstract */ public function getBody() : string { - return \file_get_contents('php://input'); + $body = \file_get_contents('php://input'); + return $body === false ? '' : $body; } /** diff --git a/Message/Mail/Mail.php b/Message/Mail/Mail.php index c9618ba4f..513ea0bab 100644 --- a/Message/Mail/Mail.php +++ b/Message/Mail/Mail.php @@ -123,7 +123,7 @@ class Mail /** * Word wrap. * - * @var string + * @var int * @since 1.0.0 */ protected $wordWrap = 78; diff --git a/Module/InstallerAbstract.php b/Module/InstallerAbstract.php index 4a347780e..6d77f0701 100644 --- a/Module/InstallerAbstract.php +++ b/Module/InstallerAbstract.php @@ -115,7 +115,7 @@ class InstallerAbstract */ private static function activate(DatabasePool $dbPool, InfoManager $info) : void { - /** @var ActivateAbstract $class */ + /** @var StatusAbstract $class */ $class = '\Modules\\' . $info->getDirectory() . '\Admin\Status'; $class::activate($dbPool, $info); } diff --git a/System/File/ContainerInterface.php b/System/File/ContainerInterface.php index 8084f7a70..fc999e9b3 100644 --- a/System/File/ContainerInterface.php +++ b/System/File/ContainerInterface.php @@ -205,7 +205,7 @@ interface ContainerInterface * @param bool $recursive Consider subdirectories * @param array $ignore Files/paths to ignore (no regex) * - * @return string + * @return int * * @since 1.0.0 */ diff --git a/Utils/IO/Zip/Gz.php b/Utils/IO/Zip/Gz.php index 47e3ea97f..922a2ea6e 100644 --- a/Utils/IO/Zip/Gz.php +++ b/Utils/IO/Zip/Gz.php @@ -31,23 +31,25 @@ class Gz implements ArchiveInterface */ public static function pack($source, string $destination, bool $overwrite = true) : bool { - $destination = \str_replace('\\', '/', realpath($destination)); + $destination = \str_replace('\\', '/', $destination); if (!$overwrite && \file_exists($destination)) { return false; } - if (($gz = gzopen($destination, 'w')) === false) { + $gz = \gzopen($destination, 'w'); + $src = \fopen($source, 'r'); + if ($gz === false || $src === false) { return false; } - $src = fopen($source, 'r'); - while (!feof($src)) { - gzwrite($gz, fread($src, 4096)); + while (!\feof($src)) { + $read = \fread($src, 4096); + \gzwrite($gz, $read === false ? '' : $read); } - fclose($src); + \fclose($src); - return gzclose($gz); + return \gzclose($gz); } /** @@ -55,22 +57,23 @@ class Gz implements ArchiveInterface */ public static function unpack(string $source, string $destination) : bool { - $destination = \str_replace('\\', '/', realpath($destination)); - if (file_exists($destination)) { + $destination = \str_replace('\\', '/', $destination); + if (\file_exists($destination)) { return false; } - if (($gz = gzopen($source, 'w')) === false) { + $gz = \gzopen($source, 'w'); + $dest = \fopen($destination, 'w'); + if ($gz === false || $dest === false) { return false; } - $dest = fopen($destination, 'w'); - while (!gzeof($gz)) { - fwrite($dest, gzread($gz, 4096)); + while (!\gzeof($gz)) { + \fwrite($dest, \gzread($gz, 4096)); } - fclose($dest); + \fclose($dest); - return gzclose($gz); + return \gzclose($gz); } } diff --git a/Utils/TaskSchedule/Cron.php b/Utils/TaskSchedule/Cron.php index 37171fee6..8279c7f63 100644 --- a/Utils/TaskSchedule/Cron.php +++ b/Utils/TaskSchedule/Cron.php @@ -39,7 +39,7 @@ class Cron extends SchedulerAbstract */ private function run(string $cmd) : string { - $cmd = 'cd ' . escapeshellarg(\dirname(self::$bin)) . ' && ' . basename(self::$bin) . ' ' . $cmd; + $cmd = 'cd ' . \escapeshellarg(\dirname(self::$bin)) . ' && ' . \basename(self::$bin) . ' ' . $cmd; $pipes = []; $desc = [ @@ -47,15 +47,19 @@ class Cron extends SchedulerAbstract 2 => ['pipe', 'w'], ]; - $resource = proc_open($cmd, $desc, $pipes, __DIR__, null); - $stdout = stream_get_contents($pipes[1]); - $stderr = stream_get_contents($pipes[2]); + $resource = \proc_open($cmd, $desc, $pipes, __DIR__, null); + $stdout = \stream_get_contents($pipes[1]); + $stderr = \stream_get_contents($pipes[2]); foreach ($pipes as $pipe) { - fclose($pipe); + \fclose($pipe); } - $status = trim((string) proc_close($resource)); + if ($resource === false) { + throw new \Exception(); + } + + $status = \proc_close($resource); if ($status == -1) { throw new \Exception($stderr); @@ -88,8 +92,8 @@ class Cron extends SchedulerAbstract $jobs = []; foreach ($lines as $line) { - if ($line !== '' && strrpos($line, '#', -strlen($line)) === false) { - $jobs[] = CronJob::createWith(str_getcsv($line, ' ')); + if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false) { + $jobs[] = CronJob::createWith(\str_getcsv($line, ' ')); } } @@ -107,18 +111,18 @@ class Cron extends SchedulerAbstract if ($exact) { $jobs = []; foreach ($lines as $line) { - $csv = str_getcsv($line, ' '); + $csv = \str_getcsv($line, ' '); - if ($line !== '' && strrpos($line, '#', -strlen($line)) === false && $csv[5] === $name) { + if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false && $csv[5] === $name) { $jobs[] = CronJob::createWith($csv); } } } else { $jobs = []; foreach ($lines as $line) { - $csv = str_getcsv($line, ' '); + $csv = \str_getcsv($line, ' '); - if ($line !== '' && strrpos($line, '#', -strlen($line)) === false && \stripos($csv[5], $name) !== false) { + if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false && \stripos($csv[5], $name) !== false) { $jobs[] = CronJob::createWith($csv); } } From 2d20d913e35ddafd0ac6427ec7077f6ab2f25708 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 15 Jul 2018 11:49:09 +0200 Subject: [PATCH 038/136] Fix empty line --- tests/Utils/Git/CommitTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/Utils/Git/CommitTest.php b/tests/Utils/Git/CommitTest.php index 46b6ffce4..689531b6a 100644 --- a/tests/Utils/Git/CommitTest.php +++ b/tests/Utils/Git/CommitTest.php @@ -100,5 +100,4 @@ class CommitTest extends \PHPUnit\Framework\TestCase $commit->setRepository(new Repository(realpath(__DIR__ . '/../../../'))); self::assertEquals(realpath(__DIR__ . '/../../../'), $commit->getRepository()->getPath()); } - } From 1200350c62322fdc06f8f00597b2e8c0f055b226 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 15 Jul 2018 20:10:53 +0200 Subject: [PATCH 039/136] Minor type fixes --- DataStorage/Database/BuilderAbstract.php | 2 +- DataStorage/Database/DataMapperAbstract.php | 2 +- DataStorage/Database/Query/QueryType.php | 2 +- tests/DataStorage/Database/Query/QueryTypeTest.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/DataStorage/Database/BuilderAbstract.php b/DataStorage/Database/BuilderAbstract.php index 300227dd4..8b0346692 100644 --- a/DataStorage/Database/BuilderAbstract.php +++ b/DataStorage/Database/BuilderAbstract.php @@ -49,7 +49,7 @@ abstract class BuilderAbstract * @var int * @since 1.0.0 */ - protected $type = QueryType::EMPTY; + protected $type = QueryType::NONE; /** * Prefix. diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index a9d787cc8..aa6fe6436 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -444,7 +444,7 @@ class DataMapperAbstract implements DataMapperInterface } // if a table only has a single column = primary key column. This must be done otherwise the query is empty - if ($query->getType() === QueryType::EMPTY) { + if ($query->getType() === QueryType::NONE) { $query->insert(static::$primaryField)->value(0, static::$columns[static::$primaryField]['type']); } diff --git a/DataStorage/Database/Query/QueryType.php b/DataStorage/Database/Query/QueryType.php index ff3a77dfd..3d1727cb5 100644 --- a/DataStorage/Database/Query/QueryType.php +++ b/DataStorage/Database/Query/QueryType.php @@ -32,5 +32,5 @@ abstract class QueryType extends Enum public const DELETE = 3; public const RANDOM = 4; public const RAW = 5; - public const EMPTY = 6; + public const NONE = 6; } diff --git a/tests/DataStorage/Database/Query/QueryTypeTest.php b/tests/DataStorage/Database/Query/QueryTypeTest.php index a9c8c8469..5d67acef2 100644 --- a/tests/DataStorage/Database/Query/QueryTypeTest.php +++ b/tests/DataStorage/Database/Query/QueryTypeTest.php @@ -28,6 +28,6 @@ class QueryTypeTest extends \PHPUnit\Framework\TestCase self::assertEquals(3, QueryType::DELETE); self::assertEquals(4, QueryType::RANDOM); self::assertEquals(5, QueryType::RAW); - self::assertEquals(6, QueryType::EMPTY); + self::assertEquals(6, QueryType::NONE); } } From a3fd37fd8498287df9a3969923b7e37aee49c9d6 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 15 Jul 2018 21:22:25 +0200 Subject: [PATCH 040/136] Fix types --- DataStorage/DataStorageConnectionInterface.php | 9 +++++++++ DataStorage/Database/BuilderAbstract.php | 12 +++--------- Dispatcher/Dispatcher.php | 16 +++++++++++++--- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/DataStorage/DataStorageConnectionInterface.php b/DataStorage/DataStorageConnectionInterface.php index 3f79866a3..a69f3421e 100644 --- a/DataStorage/DataStorageConnectionInterface.php +++ b/DataStorage/DataStorageConnectionInterface.php @@ -25,6 +25,15 @@ namespace phpOMS\DataStorage; interface DataStorageConnectionInterface { + /** + * Get prefix. + * + * @return string + * + * @since 1.0.0 + */ + public function getPrefix() : string; + /** * Connect to datastorage. * diff --git a/DataStorage/Database/BuilderAbstract.php b/DataStorage/Database/BuilderAbstract.php index 8b0346692..e391224ab 100644 --- a/DataStorage/Database/BuilderAbstract.php +++ b/DataStorage/Database/BuilderAbstract.php @@ -14,7 +14,7 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Database; -use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; +use phpOMS\DataStorage\DataStorageConnectionInterface; use phpOMS\DataStorage\Database\Query\QueryType; /** @@ -38,7 +38,7 @@ abstract class BuilderAbstract /** * Database connection. * - * @var ConnectionAbstract + * @var DataStorageConnectionInterface * @since 1.0.0 */ protected $connection = null; @@ -68,13 +68,7 @@ abstract class BuilderAbstract public $raw = ''; /** - * Set prefix. - * - * @param string $prefix Prefix - * - * @return self - * - * @since 1.0.0 + * {@inheritdoc} */ public function prefix(string $prefix) : self { diff --git a/Dispatcher/Dispatcher.php b/Dispatcher/Dispatcher.php index b8ffed67c..04d5285b4 100644 --- a/Dispatcher/Dispatcher.php +++ b/Dispatcher/Dispatcher.php @@ -63,7 +63,7 @@ final class Dispatcher * Dispatch controller. * * @param string|array|\Closure $controller Controller string - * @param array|null ...$data Data + * @param array|null|mixed ...$data Data * * @return array * @@ -111,7 +111,12 @@ final class Dispatcher if (($c = count($dispatch)) === 3) { /* Handling static functions */ - $function = $dispatch[0] . '::' . $dispatch[2]; + $function = $dispatch[0] . '::' . $dispatch[2]; + + if (!\is_callable($function)) { + throw new \Exception(); + } + $views[$controller] = $function(...$data); } elseif ($c === 2) { $this->getController($dispatch[0]); @@ -135,9 +140,14 @@ final class Dispatcher */ private function dispatchArray(array $controller, array $data = null) : array { + $views = []; foreach ($controller as $controllerSingle) { - $views += $this->dispatch($controllerSingle, ...$data); + if ($data === null) { + $views += $this->dispatch($controllerSingle); + } else { + $views += $this->dispatch($controllerSingle, ...$data); + } } return $views; From b6782198c097ff05ef93215bdc86ffd858afc9ca Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 15 Jul 2018 21:41:30 +0200 Subject: [PATCH 041/136] Fix types --- ApplicationAbstract.php | 8 ++++++++ DataStorage/Database/DataMapperAbstract.php | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/ApplicationAbstract.php b/ApplicationAbstract.php index 5bddb2f24..9bbc6d540 100644 --- a/ApplicationAbstract.php +++ b/ApplicationAbstract.php @@ -50,6 +50,14 @@ class ApplicationAbstract */ protected $appName = ''; + /** + * Organization id. + * + * @var int + * @since 1.0.0 + */ + protected $orgId = 1; + /** * Database object. * diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index aa6fe6436..95559b68f 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -14,7 +14,7 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Database; -use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; +use phpOMS\DataStorage\DataStorageConnectionInterface; use phpOMS\DataStorage\Database\Query\Builder; use phpOMS\DataStorage\DataMapperInterface; use phpOMS\Message\RequestAbstract; @@ -37,7 +37,7 @@ class DataMapperAbstract implements DataMapperInterface /** * Database connection. * - * @var ConnectionAbstract + * @var DataStorageConnectionInterface * @since 1.0.0 */ protected static $db = null; @@ -195,13 +195,13 @@ class DataMapperAbstract implements DataMapperInterface /** * Set database connection. * - * @param ConnectionAbstract $con Database connection + * @param DataStorageConnectionInterface $con Database connection * * @return void * * @since 1.0.0 */ - public static function setConnection(ConnectionAbstract $con) : void + public static function setConnection(DataStorageConnectionInterface $con) : void { self::$db = $con; } From dbd216aa3b6886219bdcdda22cc22702c2dec9f5 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 15 Jul 2018 21:48:56 +0200 Subject: [PATCH 042/136] Better type juggling --- DataStorage/Database/DataMapperAbstract.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index 95559b68f..aa6fe6436 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -14,7 +14,7 @@ declare(strict_types=1); namespace phpOMS\DataStorage\Database; -use phpOMS\DataStorage\DataStorageConnectionInterface; +use phpOMS\DataStorage\Database\Connection\ConnectionAbstract; use phpOMS\DataStorage\Database\Query\Builder; use phpOMS\DataStorage\DataMapperInterface; use phpOMS\Message\RequestAbstract; @@ -37,7 +37,7 @@ class DataMapperAbstract implements DataMapperInterface /** * Database connection. * - * @var DataStorageConnectionInterface + * @var ConnectionAbstract * @since 1.0.0 */ protected static $db = null; @@ -195,13 +195,13 @@ class DataMapperAbstract implements DataMapperInterface /** * Set database connection. * - * @param DataStorageConnectionInterface $con Database connection + * @param ConnectionAbstract $con Database connection * * @return void * * @since 1.0.0 */ - public static function setConnection(DataStorageConnectionInterface $con) : void + public static function setConnection(ConnectionAbstract $con) : void { self::$db = $con; } From c688f12c0665a15e83b9867fc3b1656835a55853 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 15 Jul 2018 21:50:10 +0200 Subject: [PATCH 043/136] Better type juggling --- Message/Http/Rest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Message/Http/Rest.php b/Message/Http/Rest.php index edf7f29a0..3245246c6 100644 --- a/Message/Http/Rest.php +++ b/Message/Http/Rest.php @@ -69,6 +69,6 @@ final class Rest \curl_close($curl); - return $result === false ? '' : $result; + return \is_bool($result) ? '' : $result; } } From d633d964623957338ffe697615b7e9b0f66cc21d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 17 Jul 2018 18:49:46 +0200 Subject: [PATCH 044/136] Type fixes --- Math/Number/Complex.php | 4 ++-- Stdlib/Base/EnumArray.php | 7 +++++++ System/File/Local/Directory.php | 30 +++++++++++++++++++++++------- System/File/Local/File.php | 32 ++++++++++++++++++++------------ 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/Math/Number/Complex.php b/Math/Number/Complex.php index 139646ba9..c4a8c74c5 100644 --- a/Math/Number/Complex.php +++ b/Math/Number/Complex.php @@ -159,7 +159,7 @@ final class Complex throw new \InvalidArgumentException(); } - public function powComplex() : Complex + public function powComplex(Complex $value) : Complex { } @@ -184,7 +184,7 @@ final class Complex return $this->multComplex($this->powInteger(--$value)); } - public function powScalar() : Complex + public function powScalar($value) : Complex { } diff --git a/Stdlib/Base/EnumArray.php b/Stdlib/Base/EnumArray.php index 30f7c04af..d33a314fe 100644 --- a/Stdlib/Base/EnumArray.php +++ b/Stdlib/Base/EnumArray.php @@ -26,6 +26,13 @@ namespace phpOMS\Stdlib\Base; */ abstract class EnumArray { + /** + * Constants. + * + * @var array + * @since 1.0.0 + */ + protected static $constants = []; /** * Checking enum name. diff --git a/System/File/Local/Directory.php b/System/File/Local/Directory.php index d5e51fe64..f07bcd5e3 100644 --- a/System/File/Local/Directory.php +++ b/System/File/Local/Directory.php @@ -71,7 +71,7 @@ final class Directory extends FileAbstract implements DirectoryInterface * @param string $path Path * @param string $filter Filter * - * @return string[] + * @return array * * @since 1.0.0 */ @@ -105,7 +105,7 @@ final class Directory extends FileAbstract implements DirectoryInterface * @param string $extension Extension * @param string $exclude Pattern to exclude * - * @return string[] + * @return array * * @since 1.0.0 */ @@ -168,6 +168,10 @@ final class Directory extends FileAbstract implements DirectoryInterface $countSize = 0; $directories = \scandir($dir); + if ($directories === false) { + return $countSize; + } + foreach ($directories as $key => $filename) { if ($filename === ".." || $filename === ".") { continue; @@ -181,7 +185,7 @@ final class Directory extends FileAbstract implements DirectoryInterface } } - return (int) $countSize; + return $countSize; } /** @@ -198,6 +202,10 @@ final class Directory extends FileAbstract implements DirectoryInterface $ignore[] = '.'; $ignore[] = '..'; + if ($files === false) { + return $size; + } + foreach ($files as $t) { if (\in_array($t, $ignore)) { continue; @@ -221,6 +229,10 @@ final class Directory extends FileAbstract implements DirectoryInterface { $files = \scandir($path); + if ($files === false) { + return false; + } + /* Removing . and .. */ unset($files[1]); unset($files[0]); @@ -260,7 +272,9 @@ final class Directory extends FileAbstract implements DirectoryInterface } $created = new \DateTime('now'); - $created->setTimestamp(\filemtime($path)); + $time = \filemtime($path); + + $created->setTimestamp($time === false ? 0 : $time); return $created; } @@ -275,7 +289,9 @@ final class Directory extends FileAbstract implements DirectoryInterface } $changed = new \DateTime(); - $changed->setTimestamp(\filectime($path)); + $time = \filectime($path); + + $changed->setTimestamp($time === false ? 0 : $time); return $changed; } @@ -289,7 +305,7 @@ final class Directory extends FileAbstract implements DirectoryInterface throw new PathException($path); } - return \fileowner($path); + return (int) \fileowner($path); } /** @@ -301,7 +317,7 @@ final class Directory extends FileAbstract implements DirectoryInterface throw new PathException($path); } - return \fileperms($path); + return (int) \fileperms($path); } /** diff --git a/System/File/Local/File.php b/System/File/Local/File.php index 2e0c84033..2f52e98f7 100644 --- a/System/File/Local/File.php +++ b/System/File/Local/File.php @@ -56,7 +56,7 @@ final class File extends FileAbstract implements FileInterface { parent::index(); - $this->size = \filesize($this->path); + $this->size = (int) \filesize($this->path); } /** @@ -98,7 +98,9 @@ final class File extends FileAbstract implements FileInterface throw new PathException($path); } - return \file_get_contents($path); + $contents = \file_get_contents($path); + + return $contents === false ? '' : $contents; } /** @@ -166,7 +168,9 @@ final class File extends FileAbstract implements FileInterface throw new PathException($path); } - return self::createFileTime(\filemtime($path)); + $time = \filemtime($path); + + return self::createFileTime($time === false ? 0 : $time); } /** @@ -178,7 +182,9 @@ final class File extends FileAbstract implements FileInterface throw new PathException($path); } - return self::createFileTime(\filemtime($path)); + $time = \filemtime($path); + + return self::createFileTime($time === false ? 0 : $time); } /** @@ -207,7 +213,7 @@ final class File extends FileAbstract implements FileInterface throw new PathException($path); } - return filesize($path); + return (int) \filesize($path); } /** @@ -219,7 +225,7 @@ final class File extends FileAbstract implements FileInterface throw new PathException($path); } - return \fileowner($path); + return (int) \fileowner($path); } /** @@ -231,7 +237,7 @@ final class File extends FileAbstract implements FileInterface throw new PathException($path); } - return \fileperms($path); + return (int) \fileperms($path); } /** @@ -245,7 +251,7 @@ final class File extends FileAbstract implements FileInterface */ public static function dirname(string $path) : string { - return basename(\dirname($path)); + return \basename(\dirname($path)); } /** @@ -259,7 +265,7 @@ final class File extends FileAbstract implements FileInterface */ public static function dirpath(string $path) : string { - return dirname($path); + return \dirname($path); } /** @@ -267,7 +273,7 @@ final class File extends FileAbstract implements FileInterface */ public static function copy(string $from, string $to, bool $overwrite = false) : bool { - if (!is_file($from)) { + if (!\is_file($from)) { throw new PathException($from); } @@ -325,7 +331,7 @@ final class File extends FileAbstract implements FileInterface */ public function getDirName() : string { - return basename(\dirname($this->path)); + return \basename(\dirname($this->path)); } /** @@ -375,7 +381,9 @@ final class File extends FileAbstract implements FileInterface */ public function getContent() : string { - return \file_get_contents($this->path); + $contents = \file_get_contents($this->path); + + return $contents === false ? '' : $contents; } /** From a0b51cef625e878375d25b1a2eb243b5b2e7bd7a Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 17 Jul 2018 21:38:32 +0200 Subject: [PATCH 045/136] Fix types --- DataStorage/Database/Query/Builder.php | 74 +++++++++++--------------- Utils/RnG/Text.php | 24 ++++----- 2 files changed, 43 insertions(+), 55 deletions(-) diff --git a/DataStorage/Database/Query/Builder.php b/DataStorage/Database/Query/Builder.php index ad37a3625..8f293b75e 100644 --- a/DataStorage/Database/Query/Builder.php +++ b/DataStorage/Database/Query/Builder.php @@ -38,7 +38,7 @@ final class Builder extends BuilderAbstract /** * Columns. * - * @var array> + * @var array * @since 1.0.0 */ public $selects = []; @@ -46,7 +46,7 @@ final class Builder extends BuilderAbstract /** * Columns. * - * @var array> + * @var array * @since 1.0.0 */ public $updates = []; @@ -260,7 +260,7 @@ final class Builder extends BuilderAbstract $this->type = QueryType::SELECT; foreach ($columns as $key => $column) { - if (is_string($column) || $column instanceof \Closure) { + if (\is_string($column) || $column instanceof \Closure) { $this->selects[] = $column; } else { throw new \InvalidArgumentException(); @@ -293,7 +293,7 @@ final class Builder extends BuilderAbstract /** * Bind parameter. * - * @param string|array|\Closure $binds Binds + * @param mixed $binds Binds * * @return Builder * @@ -301,9 +301,9 @@ final class Builder extends BuilderAbstract */ public function bind($binds) : Builder { - if (is_array($binds)) { + if (\is_array($binds)) { $this->binds += $binds; - } elseif (is_string($binds) || $binds instanceof \Closure) { + } elseif (\is_string($binds) || $binds instanceof \Closure) { $this->binds[] = $binds; } else { throw new \InvalidArgumentException(); @@ -336,18 +336,6 @@ final class Builder extends BuilderAbstract return $this->grammar->compileQuery($this); } - /** - * Parsing to prepared string. - * - * @return string - * - * @since 1.0.0 - */ - public function toPrepared() : string - { - return $this->grammar->compilePreparedQuery($this); - } - /** * Set raw query. * @@ -387,14 +375,14 @@ final class Builder extends BuilderAbstract return true; } - $test = strtolower($raw); + $test = \strtolower($raw); - if (strpos($test, 'insert') !== false - || strpos($test, 'update') !== false - || strpos($test, 'drop') !== false - || strpos($test, 'delete') !== false - || strpos($test, 'create') !== false - || strpos($test, 'alter') !== false + if (\strpos($test, 'insert') !== false + || \strpos($test, 'update') !== false + || \strpos($test, 'drop') !== false + || \strpos($test, 'delete') !== false + || \strpos($test, 'create') !== false + || \strpos($test, 'alter') !== false ) { return false; } @@ -435,7 +423,7 @@ final class Builder extends BuilderAbstract /** * From. * - * @param string|array ...$tables Tables + * @param array ...$tables Tables * * @return Builder * @@ -444,7 +432,7 @@ final class Builder extends BuilderAbstract public function from(...$tables) : Builder { foreach ($tables as $key => $table) { - if (is_string($table) || $table instanceof \Closure) { + if (\is_string($table) || $table instanceof \Closure) { $this->from[] = $table; } else { throw new \InvalidArgumentException(); @@ -486,11 +474,11 @@ final class Builder extends BuilderAbstract */ public function where($columns, $operator = null, $values = null, $boolean = 'and') : Builder { - if ($operator !== null && !is_array($operator) && !\in_array(strtolower($operator), self::OPERATORS)) { + if ($operator !== null && !\is_array($operator) && !\in_array(\strtolower($operator), self::OPERATORS)) { throw new \InvalidArgumentException('Unknown operator.'); } - if (!is_array($columns)) { + if (!\is_array($columns)) { $columns = [$columns]; $operator = [$operator]; $values = [$values]; @@ -499,7 +487,7 @@ final class Builder extends BuilderAbstract $i = 0; foreach ($columns as $key => $column) { - if (isset($operator[$i]) && !\in_array(strtolower($operator[$i]), self::OPERATORS)) { + if (isset($operator[$i]) && !\in_array(\strtolower($operator[$i]), self::OPERATORS)) { throw new \InvalidArgumentException('Unknown operator.'); } @@ -545,11 +533,11 @@ final class Builder extends BuilderAbstract */ public function getTableOfSystem($expression, string $systemIdentifier) : ?string { - if (($pos = strpos($expression, $systemIdentifier . '.' . $systemIdentifier)) === false) { + if (($pos = \strpos($expression, $systemIdentifier . '.' . $systemIdentifier)) === false) { return null; } - return explode('.', $expression)[0]; + return \explode('.', $expression)[0]; } /** @@ -648,7 +636,7 @@ final class Builder extends BuilderAbstract public function groupBy(...$columns) : Builder { foreach ($columns as $key => $column) { - if (is_string($column) || $column instanceof \Closure) { + if (\is_string($column) || $column instanceof \Closure) { $this->groups[] = $column; } else { throw new \InvalidArgumentException(); @@ -702,8 +690,8 @@ final class Builder extends BuilderAbstract */ public function orderBy($columns, $order = 'DESC') : Builder { - if (is_string($columns) || $columns instanceof \Closure) { - if (!is_string($order)) { + if (\is_string($columns) || $columns instanceof \Closure) { + if (!\is_string($order)) { throw new \InvalidArgumentException(); } @@ -712,9 +700,9 @@ final class Builder extends BuilderAbstract } $this->orders[$order][] = $columns; - } elseif (is_array($columns)) { + } elseif (\is_array($columns)) { foreach ($columns as $key => $column) { - $this->orders[is_string($order) ? $order : $order[$key]][] = $column; + $this->orders[\is_string($order) ? $order : $order[$key]][] = $column; } } else { throw new \InvalidArgumentException(); @@ -766,7 +754,7 @@ final class Builder extends BuilderAbstract */ public function union($query) : Builder { - if (!is_array($query)) { + if (!\is_array($query)) { $this->unions[] = $query; } else { $this->unions += $query; @@ -1022,7 +1010,7 @@ final class Builder extends BuilderAbstract $this->type = QueryType::UPDATE; foreach ($tables as $key => $table) { - if (is_string($table) || $table instanceof \Closure) { + if (\is_string($table) || $table instanceof \Closure) { $this->updates[] = $table; } else { throw new \InvalidArgumentException(); @@ -1214,9 +1202,9 @@ final class Builder extends BuilderAbstract */ public static function getBindParamType($value) { - if (is_int($value)) { + if (\is_int($value)) { return \PDO::PARAM_INT; - } elseif (is_string($value) || is_float($value)) { + } elseif (\is_string($value) || \is_float($value)) { return \PDO::PARAM_STR; } @@ -1236,10 +1224,10 @@ final class Builder extends BuilderAbstract */ public static function getPublicColumnName($column) : string { - if (is_string($column)) { + if (\is_string($column)) { return $column; } elseif ($column instanceof Column) { - return $column->getPublicName(); + return $column->getColumn(); } elseif ($column instanceof \Closure) { return $column(); } elseif ($column instanceof \Serializable) { diff --git a/Utils/RnG/Text.php b/Utils/RnG/Text.php index 706ea8667..cf7cec1eb 100644 --- a/Utils/RnG/Text.php +++ b/Utils/RnG/Text.php @@ -117,14 +117,14 @@ class Text /** * Get a random string. * - * @param int $length Text length - * @param int $words Vocabulary + * @param int $length Text length + * @param array $words Vocabulary * * @return string * * @since 1.0.0 */ - public function generateText(int $length, $words = null) : string + public function generateText(int $length, array $words = null) : string { if ($length === 0) { return ''; @@ -135,8 +135,8 @@ class Text } $punctuation = $this->generatePunctuation($length); - $punctuationCount = array_count_values( - array_map( + $punctuationCount = \array_count_values( + \array_map( function ($item) { return $item[1]; }, @@ -163,20 +163,20 @@ class Text for ($i = 0; $i < $length + 1; ++$i) { $newSentence = false; - $lastChar = substr($text, -1); + $lastChar = \substr($text, -1); if ($lastChar === '.' || $lastChar === '!' || $lastChar === '?' || !$lastChar) { $newSentence = true; } - $word = $words[rand(0, $wordCount - 1)]; + $word = $words[rand(0, $wordCount - 1)] ?? ''; if ($newSentence) { - $word = ucfirst($word); + $word = \ucfirst($word); $sentenceCount++; /** @noinspection PhpUndefinedVariableInspection */ - if ($this->hasParagraphs && $sentenceCount === $paragraph[$paid]) { + if ($this->hasParagraphs) { $paid++; $text .= '

'; @@ -184,7 +184,7 @@ class Text } /** @noinspection PhpUndefinedVariableInspection */ - if ($this->hasFormatting && array_key_exists($i, $formatting)) { + if ($this->hasFormatting && isset($formatting[$i])) { $word = '<' . $formatting[$i] . '>' . $word . ''; } @@ -276,11 +276,11 @@ class Text * * @param int $length Amount of sentences * - * @return string + * @return array * * @since 1.0.0 */ - private function generateParagraph(int $length) : string + private function generateParagraph(int $length) : array { $minSentence = 3; $maxSentence = 10; From 72d2e3ad77d7f7f96cd2adff40b41b8c1962febb Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 17 Jul 2018 22:26:25 +0200 Subject: [PATCH 046/136] Fix types --- Utils/IO/Csv/CsvDatabaseMapper.php | 90 -------------------- Utils/IO/Csv/CsvSettings.php | 23 +++-- Utils/IO/Zip/Tar.php | 55 ++++++++---- Utils/IO/Zip/Zip.php | 2 +- tests/Utils/IO/Csv/CsvDatabaseMapperTest.php | 24 ------ 5 files changed, 55 insertions(+), 139 deletions(-) delete mode 100644 Utils/IO/Csv/CsvDatabaseMapper.php delete mode 100644 tests/Utils/IO/Csv/CsvDatabaseMapperTest.php diff --git a/Utils/IO/Csv/CsvDatabaseMapper.php b/Utils/IO/Csv/CsvDatabaseMapper.php deleted file mode 100644 index 26489fe94..000000000 --- a/Utils/IO/Csv/CsvDatabaseMapper.php +++ /dev/null @@ -1,90 +0,0 @@ -db = $db; - } - - public function addSource(string $source) - { - $this->sources[] = $source; - - $this->sources = array_unique($this->sources); - } - - public function setSources(array $sources) : void - { - $this->sources = $sources; - } - - public function autoIdentifyCsvSettings(bool $identify) - { - $this->autoIdentifyCsvSettings = $identify; - } - - public function setLineBuffer(int $buffer) : void - { - $this->lineBuffer = $buffer; - } - - public function insert() - { - foreach ($this->sources as $source) { - $file = fopen($source, 'r'); - $header = []; - $delimiter = $this->autoIdentifyCsvSettings ? $this->getFileDelimiter($file, 100) : $this->delimiter; - - if (feof($file) && ($line = fgetcsv($file, 0, $delimiter)) !== false) { - $header = $line; - } - - $query = new Builder($this->db); - $query->insert(...$header)->into(\str_replace(' ', '', explode($source, '.'))); - - while (feof($file)) { - $c = 0; - - while (($line = fgetcsv($file)) !== false && $c < $this->lineBuffer && feof($file)) { - $query->values($line); - $c++; - } - - $this->db->con->prepare($query->toSql())->execute(); - } - - fclose($file); - } - } -} diff --git a/Utils/IO/Csv/CsvSettings.php b/Utils/IO/Csv/CsvSettings.php index 0523273e4..f001235a9 100644 --- a/Utils/IO/Csv/CsvSettings.php +++ b/Utils/IO/Csv/CsvSettings.php @@ -25,9 +25,9 @@ class CsvSettings /** * Get csv file delimiter. * - * @param mixed $file File resource - * @param int $checkLines Lines to check for evaluation - * @param array $delimiters Potential delimiters + * @param mixed $file File resource + * @param int $checkLines Lines to check for evaluation + * @param string[] $delimiters Potential delimiters * * @return string * @@ -36,14 +36,23 @@ class CsvSettings public static function getFileDelimiter($file, int $checkLines = 2, array $delimiters = [',', '\t', ';', '|', ':']) : string { $results = []; + $i = 0; + $line = \fgets($file); - $i = 0; - while (($line = fgets($file)) !== false && $i < $checkLines) { + if ($line === false) { + return ';'; + } + + while ($line !== false && $i < $checkLines) { $i++; foreach ($delimiters as $delimiter) { $regExp = '/[' . $delimiter . ']/'; - $fields = preg_split($regExp, $line); + $fields = \preg_split($regExp, $line); + + if ($fields === false) { + return ';'; + } if (count($fields) > 1) { if (!empty($results[$delimiter])) { @@ -55,7 +64,7 @@ class CsvSettings } } - $results = array_keys($results, max($results)); + $results = \array_keys($results, max($results)); return $results[0]; } diff --git a/Utils/IO/Zip/Tar.php b/Utils/IO/Zip/Tar.php index 498494215..71695911e 100644 --- a/Utils/IO/Zip/Tar.php +++ b/Utils/IO/Zip/Tar.php @@ -14,6 +14,8 @@ declare(strict_types=1); namespace phpOMS\Utils\IO\Zip; +use phpOMS\System\File\FileUtils; + /** * Zip class for handling zip files. * @@ -31,48 +33,57 @@ class Tar implements ArchiveInterface */ public static function pack($sources, string $destination, bool $overwrite = true) : bool { - $destination = \str_replace('\\', '/', realpath($destination)); + $destination = FileUtils::absolute(\str_replace('\\', '/', $destination)); if (!$overwrite && \file_exists($destination)) { return false; } + $tar = new \PharData($destination); + /** @var array $sources */ - foreach ($sources as $source) { - $source = \str_replace('\\', '/', realpath($source)); + foreach ($sources as $source => $relative) { + $source = \realpath($source); + + if ($source === false) { + continue; + } + + $source = \str_replace('\\', '/', $source); if (!\file_exists($source)) { continue; } - if (is_dir($source)) { - $files = new \RecursiveIteratorIterator( - new \RecursiveDirectoryIterator($source), - \RecursiveIteratorIterator::SELF_FIRST - ); + if (\is_dir($source)) { + $files = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source), \RecursiveIteratorIterator::SELF_FIRST); foreach ($files as $file) { $file = \str_replace('\\', '/', $file); /* Ignore . and .. */ - if (\in_array(mb_substr($file, mb_strrpos($file, '/') + 1), ['.', '..'])) { + if (($pos = \mb_strrpos($file, '/')) === false + || \in_array(\mb_substr($file, $pos + 1), ['.', '..']) + ) { continue; } - $file = realpath($file); + $absolute = \realpath($file); + $absolute = \str_replace('\\', '/', (string) $absolute); + $dir = \str_replace($source . '/', '', $relative . '/' . $absolute); - if (is_dir($file)) { - // todo: do work here - } elseif (is_file($file)) { - // todo: do work here + if (\is_dir($absolute)) { + $tar->addEmptyDir($dir . '/'); + } elseif (\is_file($absolute)) { + $tar->addFile($absolute, $dir); } } - } elseif (is_file($source)) { - // todo: do work here + } elseif (\is_file($source)) { + $tar->addFile($source, $relative); } } - fwrite($tar, pack('a1024', '')); + return true; } /** @@ -80,6 +91,16 @@ class Tar implements ArchiveInterface */ public static function unpack(string $source, string $destination) : bool { + if (!\file_exists($source)) { + return false; + } + $destination = \str_replace('\\', '/', $destination); + $destination = \rtrim($destination, '/'); + $tar = new \PharData($destination); + + $tar->extractTo($destination . '/'); + + return true; } } diff --git a/Utils/IO/Zip/Zip.php b/Utils/IO/Zip/Zip.php index 02b24b3c8..a330e48cb 100644 --- a/Utils/IO/Zip/Zip.php +++ b/Utils/IO/Zip/Zip.php @@ -100,7 +100,7 @@ class Zip implements ArchiveInterface } $destination = \str_replace('\\', '/', $destination); - $destination = rtrim($destination, '/'); + $destination = \rtrim($destination, '/'); $zip = new \ZipArchive(); if (!$zip->open($source)) { diff --git a/tests/Utils/IO/Csv/CsvDatabaseMapperTest.php b/tests/Utils/IO/Csv/CsvDatabaseMapperTest.php deleted file mode 100644 index 48a9fedab..000000000 --- a/tests/Utils/IO/Csv/CsvDatabaseMapperTest.php +++ /dev/null @@ -1,24 +0,0 @@ - Date: Wed, 18 Jul 2018 00:05:00 +0200 Subject: [PATCH 047/136] Fix types --- Config/SettingsAbstract.php | 5 ++ DataStorage/Cache/Connection/FileCache.php | 59 ++++++++++++++----- DataStorage/Database/DataMapperAbstract.php | 26 +++++--- .../Schema/Exception/TableException.php | 8 ++- Localization/Money.php | 6 ++ Message/Http/Header.php | 5 +- Stdlib/Base/Iban.php | 15 +++-- Uri/Http.php | 16 +++-- Utils/Converter/Numeric.php | 8 ++- Utils/Encoding/Huffman/Huffman.php | 6 ++ Utils/Git/Repository.php | 17 ++++-- Utils/Parser/Markdown/Markdown.php | 16 ++--- Validation/Finance/Iban.php | 10 +++- Views/View.php | 24 +++++--- 14 files changed, 159 insertions(+), 62 deletions(-) diff --git a/Config/SettingsAbstract.php b/Config/SettingsAbstract.php index 042805f76..f23ecd39a 100644 --- a/Config/SettingsAbstract.php +++ b/Config/SettingsAbstract.php @@ -105,6 +105,11 @@ abstract class SettingsAbstract implements OptionsInterface $sth->execute(); $options = $sth->fetchAll(\PDO::FETCH_KEY_PAIR); + + if ($options === false) { + return []; + } + $this->setOptions($options); break; } diff --git a/DataStorage/Cache/Connection/FileCache.php b/DataStorage/Cache/Connection/FileCache.php index 59dca08bd..3c4a9edfc 100644 --- a/DataStorage/Cache/Connection/FileCache.php +++ b/DataStorage/Cache/Connection/FileCache.php @@ -257,7 +257,6 @@ class FileCache extends ConnectionAbstract } $path = $this->getPath($key); - if (!File::exists($path)) { return null; } @@ -269,12 +268,21 @@ class FileCache extends ConnectionAbstract return null; } - $raw = File::get($path); - $type = (int) $raw[0]; + $raw = \file_get_contents($path); + if ($raw === false) { + return null; + } + + $type = (int) $raw[0]; + $expireStart = (int) \strpos($raw, self::DELIM); + $expireEnd = (int) \strpos($raw, self::DELIM, $expireStart + 1); + + if ($expireStart < 0 || $expireEnd < 0) { + return null; + } - $expireStart = \strpos($raw, self::DELIM); - $expireEnd = \strpos($raw, self::DELIM, $expireStart + 1); $cacheExpire = \substr($raw, $expireStart + 1, $expireEnd - ($expireStart + 1)); + $cacheExpire = ($cacheExpire === false) ? $created : (int) $cacheExpire; if ($cacheExpire >= 0 && $created + $cacheExpire < $now) { $this->delete($key); @@ -314,18 +322,23 @@ class FileCache extends ConnectionAbstract $value = \substr($raw, $expireEnd + 1); break; case CacheValueType::_ARRAY: - $value = \json_decode(substr($raw, $expireEnd + 1)); + $array = \substr($raw, $expireEnd + 1); + $value = \json_decode($array === false ? '[]' : $array, true); break; case CacheValueType::_NULL: $value = null; break; case CacheValueType::_SERIALIZABLE: case CacheValueType::_JSONSERIALIZABLE: - $namespaceStart = \strpos($raw, self::DELIM, $expireEnd); - $namespaceEnd = \strpos($raw, self::DELIM, $namespaceStart + 1); + $namespaceStart = (int) \strpos($raw, self::DELIM, $expireEnd); + $namespaceEnd = (int) \strpos($raw, self::DELIM, $namespaceStart + 1); $namespace = \substr($raw, $namespaceStart, $namespaceEnd); - $value = $namespace::unserialize(substr($raw, $namespaceEnd + 1)); + if ($namespace === false) { + return null; + } + + $value = $namespace::unserialize(\substr($raw, $namespaceEnd + 1)); break; } @@ -342,7 +355,6 @@ class FileCache extends ConnectionAbstract } $path = $this->getPath($key); - if ($expire < 0 && File::exists($path)) { File::delete($path); @@ -350,12 +362,29 @@ class FileCache extends ConnectionAbstract } if ($expire >= 0) { - $created = Directory::created(Directory::sanitize($key, self::SANITIZE))->getTimestamp(); - $now = \time(); - $raw = \file_get_contents($path); - $expireStart = \strpos($raw, self::DELIM); - $expireEnd = \strpos($raw, self::DELIM, $expireStart + 1); + $created = Directory::created(Directory::sanitize($key, self::SANITIZE))->getTimestamp(); + $now = \time(); + $raw = \file_get_contents($path); + + if ($raw === false) { + return false; + } + + $expireStart = (int) \strpos($raw, self::DELIM); + $expireEnd = (int) \strpos($raw, self::DELIM, $expireStart + 1); + + if ($expireStart < 0 || $expireEnd < 0) { + return false; + } + $cacheExpire = \substr($raw, $expireStart + 1, $expireEnd - ($expireStart + 1)); + $cacheExpire = ($cacheExpire === false) ? $created : (int) $cacheExpire; + + if ($cacheExpire >= 0 && $created + $cacheExpire < $now) { + $this->delete($key); + + return false; + } if ($cacheExpire >= 0 && $created + $cacheExpire > $now) { File::delete($path); diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index aa6fe6436..edeaebac3 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -2160,7 +2160,13 @@ class DataMapperAbstract implements DataMapperInterface $sth = self::$db->con->prepare($query->toSql()); $sth->execute(); - return self::populateIterable($sth->fetchAll(\PDO::FETCH_ASSOC)); + $result = $sth->fetchAll(\PDO::FETCH_ASSOC); + + if ($result === false) { + return []; + } + + return self::populateIterable($result); } /** @@ -2415,9 +2421,12 @@ class DataMapperAbstract implements DataMapperInterface $sth = self::$db->con->prepare($query->toSql()); $sth->execute(); - $results = array_column($sth->fetchAll(\PDO::FETCH_NUM) ?? [], 0); + $result = $sth->fetchAll(\PDO::FETCH_NUM); + if ($result === false) { + return []; + } - return $results; + return \array_column($result, 0); } /** @@ -2441,9 +2450,12 @@ class DataMapperAbstract implements DataMapperInterface $sth = self::$db->con->prepare($query->toSql()); $sth->execute(); - $results = array_column($sth->fetchAll(\PDO::FETCH_NUM) ?? [], 0); - - return $results; + $result = $sth->fetchAll(\PDO::FETCH_NUM); + if ($result === false) { + return []; + } + + return \array_column($result, 0); } /** @@ -2686,7 +2698,7 @@ class DataMapperAbstract implements DataMapperInterface $results = $sth->fetchAll(\PDO::FETCH_ASSOC); - return count($results) === 0; + return $results && count($results) === 0; } /** diff --git a/DataStorage/Database/Schema/Exception/TableException.php b/DataStorage/Database/Schema/Exception/TableException.php index ecd54500e..7fa34c155 100644 --- a/DataStorage/Database/Schema/Exception/TableException.php +++ b/DataStorage/Database/Schema/Exception/TableException.php @@ -49,18 +49,20 @@ class TableException extends \PDOException */ public static function findTable(string $message) : string { - $pos1 = strpos($message, '\''); + $pos1 = \strpos($message, '\''); if ($pos1 === false) { return $message; } - $pos2 = strpos($message, '\'', $pos1 + 1); + $pos2 = \strpos($message, '\'', $pos1 + 1); if ($pos2 === false) { return $message; } - return substr($message, $pos1 + 1, $pos2 - $pos1 - 1); + $table = \substr($message, $pos1 + 1, $pos2 - $pos1 - 1); + + return $table === false ? '' : $table; } } diff --git a/Localization/Money.php b/Localization/Money.php index c5085db47..df1410dbd 100644 --- a/Localization/Money.php +++ b/Localization/Money.php @@ -121,6 +121,9 @@ final class Money implements \Serializable } $right = \substr($right, 0, self::MAX_DECIMALS); + if ($right === false) { + return 0; + } return ((int) $left) * 10 ** self::MAX_DECIMALS + (int) \str_pad($right, self::MAX_DECIMALS, '0'); } @@ -192,6 +195,9 @@ final class Money implements \Serializable $left = \substr($value, 0, -self::MAX_DECIMALS); $right = \substr($value, -self::MAX_DECIMALS); + if ($left === false || $right === false) { + return '0'; + } return ($decimals > 0) ? number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals) : $left; } diff --git a/Message/Http/Header.php b/Message/Http/Header.php index 4922931b6..62d4fe803 100644 --- a/Message/Http/Header.php +++ b/Message/Http/Header.php @@ -147,8 +147,9 @@ final class Header extends HeaderAbstract $headers = []; foreach ($_SERVER as $name => $value) { - if (substr($name, 0, 5) == 'HTTP_') { - $headers[\str_replace(' ', '-', ucwords(strtolower(\str_replace('_', ' ', substr($name, 5)))))] = $value; + $part = \substr($name, 5); + if ($part === 'HTTP_') { + $headers[\str_replace(' ', '-', \ucwords(\strtolower(\str_replace('_', ' ', $part))))] = $value; } } diff --git a/Stdlib/Base/Iban.php b/Stdlib/Base/Iban.php index 44d68beb5..6fea5acdf 100644 --- a/Stdlib/Base/Iban.php +++ b/Stdlib/Base/Iban.php @@ -115,15 +115,16 @@ class Iban implements \Serializable { $country = $this->getCountry(); $layout = \str_replace(' ', '', IbanEnum::getByName('C_' . $country)); + $start = \stripos($layout, $sequence); + $end = \strrpos($layout, $sequence); - $start = \stripos($layout, $sequence); - $end = strrpos($layout, $sequence); - - if ($start === false) { + if ($start === false || $end === false) { return ''; } - return substr($this->iban, $start, $end - $start + 1); + $sequence = \substr($this->iban, $start, $end - $start + 1); + + return $sequence === false ? '' : $sequence; } /** @@ -135,7 +136,9 @@ class Iban implements \Serializable */ public function getCountry() : string { - return substr($this->iban, 0, 2); + $country = \substr($this->iban, 0, 2); + + return $country === false ? '?' : $country; } /** diff --git a/Uri/Http.php b/Uri/Http.php index 647cbeb15..25f4afd9a 100644 --- a/Uri/Http.php +++ b/Uri/Http.php @@ -145,7 +145,7 @@ final class Http implements UriInterface public function set(string $uri) : void { $this->uri = $uri; - $url = parse_url($this->uri); + $url = \parse_url($this->uri); $this->scheme = $url['scheme'] ?? ''; $this->host = $url['host'] ?? ''; @@ -155,17 +155,23 @@ final class Http implements UriInterface $this->path = $url['path'] ?? ''; if (StringUtils::endsWith($this->path, '.php')) { - $this->path = substr($this->path, 0, -4); + $path = \substr($this->path, 0, -4); + + if ($path === false) { + return; + } + + $this->path = $path; } - $this->path = strpos($this->path, $this->rootPath) === 0 ? substr($this->path, strlen($this->rootPath), strlen($this->path)) : $this->path; + $this->path = \strpos($this->path, $this->rootPath) === 0 ? \substr($this->path, \strlen($this->rootPath), \strlen($this->path)) : $this->path; $this->queryString = $url['query'] ?? ''; if (!empty($this->queryString)) { - parse_str($this->queryString, $this->query); + \parse_str($this->queryString, $this->query); } - $this->query = array_change_key_case($this->query, CASE_LOWER); + $this->query = \array_change_key_case($this->query, CASE_LOWER); $this->fragment = $url['fragment'] ?? ''; $this->base = $this->scheme . '://' . $this->host . $this->rootPath; diff --git a/Utils/Converter/Numeric.php b/Utils/Converter/Numeric.php index 27149160e..f0d929b5a 100644 --- a/Utils/Converter/Numeric.php +++ b/Utils/Converter/Numeric.php @@ -148,9 +148,13 @@ class Numeric $result = 0; foreach (self::ROMANS as $key => $value) { - while (strpos($roman, $key) === 0) { + while (\strpos($roman, $key) === 0) { $result += $value; - $roman = substr($roman, \strlen($key)); + $temp = \substr($roman, \strlen($key)); + + if ($temp !== false) { + $roman = $temp; + } } } diff --git a/Utils/Encoding/Huffman/Huffman.php b/Utils/Encoding/Huffman/Huffman.php index 25542ecd9..165a1c73e 100644 --- a/Utils/Encoding/Huffman/Huffman.php +++ b/Utils/Encoding/Huffman/Huffman.php @@ -134,6 +134,9 @@ final class Huffman } $decbin = \substr($decbin, $pos + 1); + if ($decbin === false) { + throw new \Exception(); + } } if ($i + 1 === $rawLenght) { @@ -144,6 +147,9 @@ final class Huffman } $decbin = \substr($decbin, 0, $pos); + if ($decbin === false) { + throw new \Exception(); + } } $binary .= $decbin; diff --git a/Utils/Git/Repository.php b/Utils/Git/Repository.php index e76e76ee4..fd84f731c 100644 --- a/Utils/Git/Repository.php +++ b/Utils/Git/Repository.php @@ -168,7 +168,7 @@ class Repository */ private function run(string $cmd) : array { - if (\strtolower(\substr(PHP_OS, 0, 3)) == 'win') { + if (\strtolower((string) \substr(PHP_OS, 0, 3)) == 'win') { $cmd = 'cd ' . \escapeshellarg(\dirname(Git::getBin())) . ' && ' . \basename(Git::getBin()) . ' -C ' . \escapeshellarg($this->path) . ' ' @@ -707,7 +707,8 @@ class Repository foreach ($lines as $line) { \preg_match('/^[0-9]*/', $line, $matches); - $contributor = new Author(\substr($line, \strlen($matches[0]) + 1)); + $author = \substr($line, \strlen($matches[0]) + 1); + $contributor = new Author($author === false ? '' : $author); $contributor->setCommitCount($this->getCommitsCount($start, $end)[$contributor->getName()]); $addremove = $this->getAdditionsRemovalsByContributor($contributor, $start, $end); @@ -881,8 +882,16 @@ class Repository } $author = \explode(':', $lines[1] ?? ''); - $author = \explode('<', trim($author[1] ?? '')); - $date = \substr($lines[2] ?? '', 6); + if (count($author) < 2) { + $author = ['none', 'none']; + } else { + $author = \explode('<', trim($author[1] ?? '')); + } + + $date = \substr($lines[2] ?? '', 6); + if ($date === false) { + $date = 'now'; + } $commit = new Commit($matches[0]); $commit->setAuthor(new Author(trim($author[0] ?? ''), rtrim($author[1] ?? '', '>'))); diff --git a/Utils/Parser/Markdown/Markdown.php b/Utils/Parser/Markdown/Markdown.php index fb1b691ce..f81edd4de 100644 --- a/Utils/Parser/Markdown/Markdown.php +++ b/Utils/Parser/Markdown/Markdown.php @@ -980,17 +980,17 @@ class Markdown $inline['position'] = $markerPosition; } - $unmarkedText = \substr($text, 0, $inline['position']); + $unmarkedText = (string) \substr($text, 0, $inline['position']); $markup .= self::unmarkedText($unmarkedText); $markup .= isset($inline['markup']) ? $inline['markup'] : self::element($inline['element']); - $text = \substr($text, $inline['position'] + $inline['extent']); + $text = (string) \substr($text, $inline['position'] + $inline['extent']); continue 2; } - $unmarkedText = \substr($text, 0, $markerPosition + 1); + $unmarkedText = (string) \substr($text, 0, $markerPosition + 1); $markup .= self::unmarkedText($unmarkedText); - $text = \substr($text, $markerPosition + 1); + $text = (string) \substr($text, $markerPosition + 1); } $markup .= self::unmarkedText($text); @@ -1185,13 +1185,13 @@ class Markdown $element['text'] = $matches[1]; $extent += \strlen($matches[0]); - $remainder = \substr($remainder, $extent); + $remainder = (string) \substr($remainder, $extent); if (\preg_match('/^[(]\s*+((?:[^ ()]++|[(][^ )]+[)])++)(?:[ ]+("[^"]*"|\'[^\']*\'))?\s*[)]/', $remainder, $matches)) { $element['attributes']['href'] = UriFactory::build($matches[1]); if (isset($matches[2])) { - $element['attributes']['title'] = \substr($matches[2], 1, - 1); + $element['attributes']['title'] = (string) \substr($matches[2], 1, - 1); } $extent += \strlen($matches[0]); @@ -1427,7 +1427,7 @@ class Markdown if (!\in_array('', $lines) && \substr($trimmedMarkup, 0, 3) === '

') { $markup = $trimmedMarkup; - $markup = \substr($markup, 3); + $markup = (string) \substr($markup, 3); $position = \strpos($markup, '

'); $markup = \substr_replace($markup, '', $position, 4); } @@ -1524,6 +1524,6 @@ class Markdown return false; } - return \strtolower(\substr($string, 0, $length)) === \strtolower($needle); + return \strtolower((string) \substr($string, 0, $length)) === \strtolower($needle); } } diff --git a/Validation/Finance/Iban.php b/Validation/Finance/Iban.php index af5976040..f18fc508d 100644 --- a/Validation/Finance/Iban.php +++ b/Validation/Finance/Iban.php @@ -31,8 +31,14 @@ final class Iban extends ValidatorAbstract */ public static function isValid($value, array $constraints = null) : bool { - $value = \str_replace(' ', '', \strtolower($value)); - $enumName = 'C_' . \strtoupper(\substr($value, 0, 2)); + $value = \str_replace(' ', '', \strtolower($value)); + + $temp = \substr($value, 0, 2); + if ($temp === false) { + return false; + } + + $enumName = 'C_' . \strtoupper($temp); if (!IbanEnum::isValidName($enumName)) { self::$error = IbanErrorType::INVALID_COUNTRY; diff --git a/Views/View.php b/Views/View.php index 57b663d57..466fcfa06 100644 --- a/Views/View.php +++ b/Views/View.php @@ -177,25 +177,33 @@ class View extends ViewAbstract if ($module === null) { $match = '/Modules/'; - if (($start = strripos($this->template, $match)) === false) { + if (($start = \strripos($this->template, $match)) === false) { throw new InvalidModuleException($module ?? ''); } - $start = $start + strlen($match); - $end = strpos($this->template, '/', $start); - $module = substr($this->template, $start, $end - $start); + $start = $start + \strlen($match); + $end = \strpos($this->template, '/', $start); + $module = \substr($this->template, $start, $end - $start); + } + + if ($module === false) { + $module = '0'; } if ($theme === null) { $match = '/Theme/'; - if (($start = strripos($this->template, $match)) === false) { + if (($start = \strripos($this->template, $match)) === false) { throw new InvalidThemeException($theme ?? ''); } - $start = $start + strlen($match); - $end = strpos($this->template, '/', $start); - $theme = substr($this->template, $start, $end - $start); + $start = $start + \strlen($match); + $end = \strpos($this->template, '/', $start); + $theme = \substr($this->template, $start, $end - $start); + } + + if ($theme === false) { + $theme = '0'; } return $this->app->l11nManager->getText($this->l11n->getLanguage(), $module, $theme, $translation); From b82213d97f135ceea6348dd89d19ca746b417a9a Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Wed, 18 Jul 2018 00:12:53 +0200 Subject: [PATCH 048/136] Turn some returns into exceptions --- DataStorage/Database/GrammarAbstract.php | 12 ++++++------ .../Database/Schema/Exception/TableException.php | 2 +- Localization/Money.php | 4 ++-- Uri/Http.php | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/DataStorage/Database/GrammarAbstract.php b/DataStorage/Database/GrammarAbstract.php index c55d09abe..7b85dfcd9 100644 --- a/DataStorage/Database/GrammarAbstract.php +++ b/DataStorage/Database/GrammarAbstract.php @@ -95,7 +95,7 @@ abstract class GrammarAbstract { return trim( implode(' ', - array_filter( + \array_filter( $this->compileComponents($query), function ($value) { return (string) $value !== ''; @@ -169,13 +169,13 @@ abstract class GrammarAbstract $expression = ''; foreach ($elements as $key => $element) { - if (is_string($element) && $element !== '*') { - if (strpos($element, '.') === false) { + if (\is_string($element) && $element !== '*') { + if (\strpos($element, '.') === false) { $prefix = ''; } $expression .= $this->compileSystem($element, $prefix) . ', '; - } elseif (is_string($element) && $element === '*') { + } elseif (\is_string($element) && $element === '*') { $expression .= '*, '; } elseif ($element instanceof \Closure) { $expression .= $element() . ', '; @@ -204,9 +204,9 @@ abstract class GrammarAbstract $expression = ''; foreach ($elements as $key => $element) { - if (is_string($element) && $element !== '*') { + if (\is_string($element) && $element !== '*') { $expression .= $this->compileSystem($element, $prefix) . ', '; - } elseif (is_string($element) && $element === '*') { + } elseif (\is_string($element) && $element === '*') { $expression .= '*, '; } elseif ($element instanceof \Closure) { $expression .= $element() . ', '; diff --git a/DataStorage/Database/Schema/Exception/TableException.php b/DataStorage/Database/Schema/Exception/TableException.php index 7fa34c155..98f82d800 100644 --- a/DataStorage/Database/Schema/Exception/TableException.php +++ b/DataStorage/Database/Schema/Exception/TableException.php @@ -63,6 +63,6 @@ class TableException extends \PDOException $table = \substr($message, $pos1 + 1, $pos2 - $pos1 - 1); - return $table === false ? '' : $table; + return $table === false ? $message : $table; } } diff --git a/Localization/Money.php b/Localization/Money.php index df1410dbd..16b0639cb 100644 --- a/Localization/Money.php +++ b/Localization/Money.php @@ -122,7 +122,7 @@ final class Money implements \Serializable $right = \substr($right, 0, self::MAX_DECIMALS); if ($right === false) { - return 0; + throw new \Exception(); } return ((int) $left) * 10 ** self::MAX_DECIMALS + (int) \str_pad($right, self::MAX_DECIMALS, '0'); @@ -196,7 +196,7 @@ final class Money implements \Serializable $left = \substr($value, 0, -self::MAX_DECIMALS); $right = \substr($value, -self::MAX_DECIMALS); if ($left === false || $right === false) { - return '0'; + throw new \Exception(); } return ($decimals > 0) ? number_format((float) $left, 0, $this->decimal, $this->thousands) . $this->decimal . \substr($right, 0, $decimals) : $left; diff --git a/Uri/Http.php b/Uri/Http.php index 25f4afd9a..79b47cccd 100644 --- a/Uri/Http.php +++ b/Uri/Http.php @@ -158,7 +158,7 @@ final class Http implements UriInterface $path = \substr($this->path, 0, -4); if ($path === false) { - return; + throw new \Exception(); } $this->path = $path; From eebace5030fb313ff854264fdcefba797e4332c8 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 24 Jul 2018 19:30:15 +0200 Subject: [PATCH 049/136] console app draft --- Log/FileLogger.php | 8 +- Message/Console/Header.php | 270 +++++++++++++++++++++++++++++ Message/Console/Request.php | 10 +- Message/Console/Response.php | 193 +++++++++++++++++++++ Message/Http/Header.php | 10 +- Message/Http/Request.php | 8 +- Uri/Argument.php | 321 +++++++++++++++++++++++++++++++++++ Uri/Http.php | 10 +- 8 files changed, 806 insertions(+), 24 deletions(-) create mode 100644 Uri/Argument.php diff --git a/Log/FileLogger.php b/Log/FileLogger.php index ce84e89c4..d295f7eea 100644 --- a/Log/FileLogger.php +++ b/Log/FileLogger.php @@ -266,6 +266,10 @@ final class FileLogger implements LoggerInterface */ private function write(string $message) : void { + if ($this->verbose) { + echo $message, "\n"; + } + $this->createFile(); if (!\is_writable($this->path)) { return; @@ -280,10 +284,6 @@ final class FileLogger implements LoggerInterface \fclose($this->fp); $this->fp = false; } - - if ($this->verbose) { - echo $message, "\n"; - } } /** diff --git a/Message/Console/Header.php b/Message/Console/Header.php index e69de29bb..7b7d56c01 100644 --- a/Message/Console/Header.php +++ b/Message/Console/Header.php @@ -0,0 +1,270 @@ +set('Content-Type', 'text/html; charset=utf-8'); + parent::__construct(); + } + + /** + * Set header. + * + * @param string $key Header key (case insensitive) + * @param string $header Header value + * @param bool $overwrite Overwrite if already existing + * + * @return bool + * + * @since 1.0.0 + */ + public function set(string $key, string $header, bool $overwrite = false) : bool + { + if (self::$isLocked) { + return false; + } + + if (self::isSecurityHeader($key) && isset($this->header[$key])) { + return false; + } + + $key = strtolower($key); + + if (!$overwrite && isset($this->header[$key])) { + return false; + } + + unset($this->header[$key]); + + if (!isset($this->header[$key])) { + $this->header[$key] = []; + } + + $this->header[$key][] = $header; + + return true; + } + + /** + * Is security header. + * + * @param string $key Header key + * + * @return bool + * + * @since 1.0.0 + */ + public static function isSecurityHeader(string $key) : bool + { + $key = strtolower($key); + + return $key === 'content-security-policy' + || $key === 'x-xss-protection' + || $key === 'x-content-type-options' + || $key === 'x-frame-options'; + } + + /** + * {@inheritdoc} + */ + public function getProtocolVersion() : string + { + return self::VERSION; + } + + /** + * Get status code. + * + * @return int + * + * @since 1.0.0 + */ + public function getStatusCode() : int + { + if ($this->status === 0) { + $this->status = (int) \http_response_code(); + } + + return parent::getStatusCode(); + } + + /** + * Get all headers for apache and nginx + * + * @return array + * + * @since 1.0.0 + */ + public static function getAllHeaders() : array + { + if (function_exists('getallheaders')) { + // @codeCoverageIgnoreStart + return getallheaders(); + // @codeCoverageIgnoreEnd + } + + $headers = []; + foreach ($_SERVER as $name => $value) { + $part = \substr($name, 5); + if ($part === 'HTTP_') { + $headers[\str_replace(' ', '-', \ucwords(\strtolower(\str_replace('_', ' ', $part))))] = $value; + } + } + + return $headers; + } + + /** + * Remove header by ID. + * + * @param mixed $key Header key + * + * @return bool + * + * @since 1.0.0 + */ + public function remove($key) : bool + { + if (self::$isLocked) { + return false; + } + + if (isset($this->header[$key])) { + unset($this->header[$key]); + + return true; + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getReasonPhrase() : string + { + $phrases = $this->get('Status'); + + return empty($phrases) ? '' : $phrases[0]; + } + + /** + * Get header by name. + * + * @param string $key Header key + * + * @return array + * + * @since 1.0.0 + */ + public function get(string $key) : array + { + return $this->header[strtolower($key)] ?? []; + } + + /** + * Check if header is defined. + * + * @param string $key Header key + * + * @return bool + * + * @since 1.0.0 + */ + public function has(string $key) : bool + { + return isset($this->header[$key]); + } + + /** + * Push all headers. + * + * @return void + * + * @since 1.0.0 + * @codeCoverageIgnore + */ + public function push() : void + { + if (self::$isLocked) { + throw new \Exception('Already locked'); + } + + foreach ($this->header as $name => $arr) { + foreach ($arr as $ele => $value) { + header($name . ': ' . $value); + } + } + } + + /** + * {@inheritdoc} + */ + public function generate(int $code) : void + { + switch ($code) { + default: + $this->generate500(); + } + } + + /** + * Generate predefined header. + * + * @return void + * + * @since 1.0.0 + */ + private function generate500() : void + { + } +} diff --git a/Message/Console/Request.php b/Message/Console/Request.php index a2d074f91..13777552b 100644 --- a/Message/Console/Request.php +++ b/Message/Console/Request.php @@ -18,6 +18,7 @@ use phpOMS\Localization\Localization; use phpOMS\Message\RequestAbstract; use phpOMS\Message\RequestSource; use phpOMS\Router\RouteVerb; +use phpOMS\Uri\UriInterface; /** * Request class. @@ -50,12 +51,9 @@ final class Request extends RequestAbstract public function __construct(UriInterface $uri, Localization $l11n = null) { $this->header = new Header(); + $this->header->setL11n($l11n ?? new Localization()); - if ($l11n === null) { - $l11n = $l11n ?? new Localization(); - } - - $this->header->setL11n($l11n); + $this->uri = $uri; } /** @@ -80,7 +78,7 @@ final class Request extends RequestAbstract $paths[] = $pathArray[$i]; } - $this->hash[] = sha1(implode('', $paths)); + $this->hash[] = sha1(\implode('', $paths)); } } diff --git a/Message/Console/Response.php b/Message/Console/Response.php index e69de29bb..94f26195b 100644 --- a/Message/Console/Response.php +++ b/Message/Console/Response.php @@ -0,0 +1,193 @@ +header = new Header(); + $this->header->setL11n($l11n ?? new Localization()); + } + + /** + * Set response. + * + * @param array $response Response to set + * + * @return void + * + * @since 1.0.0 + */ + public function setResponse(array $response) : void + { + $this->response = $response; + } + + /** + * Remove response by ID. + * + * @param mixed $id Response ID + * + * @return bool + * + * @since 1.0.0 + */ + public function remove($id) : bool + { + if (isset($this->response[$id])) { + unset($this->response[$id]); + + return true; + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function getBody() : string + { + return $this->render(); + } + + /** + * Generate response based on header. + * + * @return string + * + * @since 1.0.0 + */ + public function render() : string + { + $types = $this->header->get('Content-Type'); + + foreach ($types as $type) { + if (\stripos($type, MimeType::M_JSON) !== false) { + return (string) \json_encode($this->jsonSerialize()); + } + } + + return $this->getRaw(); + } + + /** + * Generate raw response. + * + * @return string + * + * @throws \Exception + * + * @since 1.0.0 + */ + private function getRaw() : string + { + $render = ''; + + foreach ($this->response as $key => $response) { + if ($response instanceOf \Serializable) { + $render .= $response->serialize(); + } elseif (\is_string($response) || \is_numeric($response)) { + $render .= $response; + } else { + throw new \Exception('Wrong response type'); + } + } + + return $this->removeWhitespaceAndLineBreak($render); + } + + /** + * Remove whitespace and line break from render + * + * @param string $render Rendered string + * + * @return string + * + * @since 1.0.0 + */ + private function removeWhitespaceAndLineBreak(string $render) : string + { + $types = $this->header->get('Content-Type'); + if (\stripos($types[0], MimeType::M_HTML) !== false) { + return \trim(\preg_replace('/(\s{2,}|\n|\t)(?![^<>]*<\/pre>)/', ' ', $render)); + } + + return $render; + } + + /** + * {@inheritdoc} + */ + public function toArray() : array + { + $result = []; + + try { + foreach ($this->response as $key => $response) { + if ($response instanceof View) { + $result += $response->toArray(); + } elseif (\is_array($response)) { + $result += $response; + } elseif (\is_scalar($response)) { + $result[] = $response; + } elseif ($response instanceof \JsonSerializable) { + $result[] = $response->jsonSerialize(); + } elseif ($response === null) { + continue; + } else { + throw new \Exception('Wrong response type'); + } + } + } catch (\Exception $e) { + // todo: handle exception + // need to to try catch for logging. otherwise the json_encode in the logger will have a problem with this + $result = []; + } finally { + return $result; + } + } +} diff --git a/Message/Http/Header.php b/Message/Http/Header.php index 62d4fe803..69ea4ae11 100644 --- a/Message/Http/Header.php +++ b/Message/Http/Header.php @@ -70,7 +70,7 @@ final class Header extends HeaderAbstract return false; } - $key = strtolower($key); + $key = \strtolower($key); if (!$overwrite && isset($this->header[$key])) { return false; @@ -98,7 +98,7 @@ final class Header extends HeaderAbstract */ public static function isSecurityHeader(string $key) : bool { - $key = strtolower($key); + $key = \strtolower($key); return $key === 'content-security-policy' || $key === 'x-xss-protection' @@ -139,9 +139,9 @@ final class Header extends HeaderAbstract */ public static function getAllHeaders() : array { - if (function_exists('getallheaders')) { + if (\function_exists('getallheaders')) { // @codeCoverageIgnoreStart - return getallheaders(); + return \getallheaders(); // @codeCoverageIgnoreEnd } @@ -201,7 +201,7 @@ final class Header extends HeaderAbstract */ public function get(string $key) : array { - return $this->header[strtolower($key)] ?? []; + return $this->header[\strtolower($key)] ?? []; } /** diff --git a/Message/Http/Request.php b/Message/Http/Request.php index 8101a5efb..61114fd37 100644 --- a/Message/Http/Request.php +++ b/Message/Http/Request.php @@ -105,7 +105,7 @@ final class Request extends RequestAbstract $this->setupUriBuilder(); } - $this->data = array_change_key_case($this->data, CASE_LOWER); + $this->data = \array_change_key_case($this->data, CASE_LOWER); } /** @@ -249,7 +249,7 @@ final class Request extends RequestAbstract $paths[] = $pathArray[$i]; } - $this->hash[] = sha1(implode('', $paths)); + $this->hash[] = sha1(\implode('', $paths)); } } @@ -298,7 +298,7 @@ final class Request extends RequestAbstract $httpUserAgent = \strtolower($_SERVER['HTTP_USER_AGENT']); foreach ($arr as $key => $val) { - if (stripos($httpUserAgent, $val)) { + if (\stripos($httpUserAgent, $val)) { $this->browser = $val; return $this->browser; @@ -466,7 +466,7 @@ final class Request extends RequestAbstract { if ($this->getMethod() === RequestMethod::GET && !empty($this->data)) { return $this->uri->__toString() - . (parse_url($this->uri->__toString(), PHP_URL_QUERY) ? '&' : '?') + . (\parse_url($this->uri->__toString(), PHP_URL_QUERY) ? '&' : '?') . http_build_query($this->data); } diff --git a/Uri/Argument.php b/Uri/Argument.php new file mode 100644 index 000000000..bbd50c006 --- /dev/null +++ b/Uri/Argument.php @@ -0,0 +1,321 @@ +set($uri); + } + + /** + * {@inheritdoc} + */ + public function set(string $uri) : void + { + $this->uri = $uri; + } + + /** + * {@inheritdoc} + */ + public static function isValid(string $uri) : bool + { + return true; + } + + /** + * {@inheritdoc} + */ + public function getRootPath() : string + { + return $this->rootPath; + } + + /** + * {@inheritdoc} + */ + public function setRootPath(string $root) : void + { + $this->rootPath = $root; + $this->set($this->uri); + } + + /** + * {@inheritdoc} + */ + public function getScheme() : string + { + return $this->scheme; + } + + /** + * {@inheritdoc} + */ + public function getHost() : string + { + return $this->host; + } + + /** + * {@inheritdoc} + */ + public function getPort() : int + { + return $this->port; + } + + /** + * {@inheritdoc} + */ + public function getPass() : string + { + return $this->pass; + } + + /** + * {@inheritdoc} + */ + public function getPath() : string + { + return $this->path; + } + + /** + * Get path offset. + * + * @return int + * + * @since 1.0.0 + */ + public function getPathOffset() : int + { + return \substr_count($this->rootPath, '/') - 1; + } + + /** + * {@inheritdoc} + */ + public function getRoute() : string + { + $query = $this->getQuery(); + return $this->path . (!empty($query) ? '?' . $this->getQuery() : ''); + } + + /** + * {@inheritdoc} + */ + public function getQuery(string $key = null) : string + { + if ($key !== null) { + $key = \strtolower($key); + + return $this->query[$key] ?? ''; + } + + return $this->queryString; + } + + /** + * {@inheritdoc} + */ + public function getPathElement(int $pos = null) : string + { + return explode('/', $this->path)[$pos] ?? ''; + } + + /** + * {@inheritdoc} + */ + public function getPathElements() : array + { + return explode('/', $this->path); + } + + /** + * {@inheritdoc} + */ + public function getQueryArray() : array + { + return $this->query; + } + + /** + * {@inheritdoc} + */ + public function getFragment() : string + { + return $this->fragment; + } + + /** + * {@inheritdoc} + */ + public function getBase() : string + { + return $this->base; + } + + /** + * {@inheritdoc} + */ + public function __toString() + { + return $this->uri; + } + + /** + * {@inheritdoc} + */ + public function getAuthority() : string + { + return ''; + } + + /** + * {@inheritdoc} + */ + public function getUser() : string + { + return $this->user; + } + + /** + * {@inheritdoc} + */ + public function getUserInfo() : string + { + return ''; + } +} diff --git a/Uri/Http.php b/Uri/Http.php index 79b47cccd..b9803d16f 100644 --- a/Uri/Http.php +++ b/Uri/Http.php @@ -195,7 +195,7 @@ final class Http implements UriInterface */ public static function isValid(string $uri) : bool { - return (bool) filter_var($uri, FILTER_VALIDATE_URL); + return (bool) \filter_var($uri, FILTER_VALIDATE_URL); } /** @@ -264,7 +264,7 @@ final class Http implements UriInterface */ public function getPathOffset() : int { - return substr_count($this->rootPath, '/') - 1; + return \substr_count($this->rootPath, '/') - 1; } /** @@ -282,7 +282,7 @@ final class Http implements UriInterface public function getQuery(string $key = null) : string { if ($key !== null) { - $key = strtolower($key); + $key = \strtolower($key); return $this->query[$key] ?? ''; } @@ -295,7 +295,7 @@ final class Http implements UriInterface */ public function getPathElement(int $pos = null) : string { - return explode('/', $this->path)[$pos] ?? ''; + return \explode('/', $this->path)[$pos] ?? ''; } /** @@ -303,7 +303,7 @@ final class Http implements UriInterface */ public function getPathElements() : array { - return explode('/', $this->path); + return \explode('/', $this->path); } /** From d75e12b67b2cb4100b47233ab6ffc70a41b885ba Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 24 Jul 2018 19:30:21 +0200 Subject: [PATCH 050/136] console app draft --- Message/Console/Request.php | 1 + 1 file changed, 1 insertion(+) diff --git a/Message/Console/Request.php b/Message/Console/Request.php index 13777552b..3f74dbae1 100644 --- a/Message/Console/Request.php +++ b/Message/Console/Request.php @@ -17,6 +17,7 @@ namespace phpOMS\Message\Console; use phpOMS\Localization\Localization; use phpOMS\Message\RequestAbstract; use phpOMS\Message\RequestSource; +use phpOMS\Message\Http\RequestMethod; use phpOMS\Router\RouteVerb; use phpOMS\Uri\UriInterface; From b7d3427e6214a8f6534902db5e3081ff98f2ae97 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 24 Jul 2018 20:18:34 +0200 Subject: [PATCH 051/136] Use global namespace --- UnhandledHandler.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/UnhandledHandler.php b/UnhandledHandler.php index defda347f..2a920073b 100644 --- a/UnhandledHandler.php +++ b/UnhandledHandler.php @@ -61,14 +61,14 @@ final class UnhandledHandler { $logger = FileLogger::getInstance(__DIR__ . '/../Logs'); - if (!(error_reporting() & $errno)) { + if (!(\error_reporting() & $errno)) { $logger->error(FileLogger::MSG_FULL, [ 'message' => 'Undefined error', 'line' => $errline, 'file' => $errfile, ]); - error_clear_last(); + \error_clear_last(); return false; } @@ -80,7 +80,7 @@ final class UnhandledHandler 'file' => $errfile, ]); - error_clear_last(); + \error_clear_last(); return true; } @@ -95,9 +95,9 @@ final class UnhandledHandler */ public static function shutdownHandler() : void { - $e = error_get_last(); + $e = \error_get_last(); - if (isset($e)) { + if ($e !== null) { $logger = FileLogger::getInstance(__DIR__ . '/../Logs'); $logger->warning(FileLogger::MSG_FULL, [ 'message' => $e['message'], From 0877aeb7d5d0082517af33d442c773980480576b Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 27 Jul 2018 19:52:56 +0200 Subject: [PATCH 052/136] Implement console framework features --- Console/CommandManager.php | 129 --------------------------- Message/Console/Request.php | 36 +++++++- Message/Console/Response.php | 19 ---- Module/InstallerAbstract.php | 30 ++++--- Router/Router.php | 13 +-- Uri/Argument.php | 5 ++ tests/Console/CommandManagerTest.php | 26 ------ 7 files changed, 59 insertions(+), 199 deletions(-) delete mode 100644 Console/CommandManager.php delete mode 100644 tests/Console/CommandManagerTest.php diff --git a/Console/CommandManager.php b/Console/CommandManager.php deleted file mode 100644 index a76251c97..000000000 --- a/Console/CommandManager.php +++ /dev/null @@ -1,129 +0,0 @@ -commands[$cmd])) { - $this->commands[$cmd] = [$callback, $source]; - $this->count++; - - return true; - } - - return false; - } - - /** - * Detach existing command. - * - * @param string $cmd Command ID - * @param mixed $source Provider - * - * @return bool - * - * @since 1.0.0 - */ - public function detach(string $cmd, $source) : bool - { - if (array_key_exists($cmd, $this->commands)) { - unset($this->commands[$cmd]); - $this->count--; - - return true; - } - - return false; - } - - /** - * Trigger command. - * - * @param string $cmd Command ID - * @param mixed $para Parameters to pass - * - * @return mixed|bool - * - * @since 1.0.0 - */ - public function trigger(string $cmd, $para) - { - if (array_key_exists($cmd, $this->commands)) { - return $this->commands[$cmd][0]($para); - } - - return false; - } - - /** - * Count commands. - * - * @return int - * - * @since 1.0.0 - */ - public function count() : int - { - return $this->count; - } -} diff --git a/Message/Console/Request.php b/Message/Console/Request.php index 3f74dbae1..3ac251ae6 100644 --- a/Message/Console/Request.php +++ b/Message/Console/Request.php @@ -55,6 +55,36 @@ final class Request extends RequestAbstract $this->header->setL11n($l11n ?? new Localization()); $this->uri = $uri; + $this->init(); + } + + /** + * Init request. + * + * This is used in order to either initialize the current http request or a batch of GET requests + * + * @return void + * + * @since 1.0.0 + */ + private function init() : void + { + $lang = \explode('_', $_SERVER['LANG'] ?? ''); + $this->header->getL11n()->setLanguage($lang[0] ?? 'en'); + + $this->cleanupGlobals(); + } + + /** + * Clean up globals that musn't be used any longer + * + * @return void + * + * @since 1.0.0 + */ + private function cleanupGlobals() : void + { + unset($_SERVER); } /** @@ -114,7 +144,11 @@ final class Request extends RequestAbstract public function getMethod() : string { if ($this->method === null) { - $this->method = RequestMethod::GET; + $temp = $this->uri->__toString(); + $found = \stripos($temp, ':'); + $method = $found !== false && $found > 3 && $found < 8 ? \substr($temp, 0, $found) : RequestMethod::GET; + + $this->method = $method === false ? RequestMethod::GET : $method; } return $this->method; diff --git a/Message/Console/Response.php b/Message/Console/Response.php index 94f26195b..10effadb6 100644 --- a/Message/Console/Response.php +++ b/Message/Console/Response.php @@ -137,25 +137,6 @@ final class Response extends ResponseAbstract implements RenderableInterface } } - return $this->removeWhitespaceAndLineBreak($render); - } - - /** - * Remove whitespace and line break from render - * - * @param string $render Rendered string - * - * @return string - * - * @since 1.0.0 - */ - private function removeWhitespaceAndLineBreak(string $render) : string - { - $types = $this->header->get('Content-Type'); - if (\stripos($types[0], MimeType::M_HTML) !== false) { - return \trim(\preg_replace('/(\s{2,}|\n|\t)(?![^<>]*<\/pre>)/', ' ', $render)); - } - return $render; } diff --git a/Module/InstallerAbstract.php b/Module/InstallerAbstract.php index 6d77f0701..b7a8a2418 100644 --- a/Module/InstallerAbstract.php +++ b/Module/InstallerAbstract.php @@ -18,6 +18,7 @@ use phpOMS\DataStorage\Database\DatabaseType; use phpOMS\DataStorage\Database\Exception\InvalidDatabaseTypeException; use phpOMS\DataStorage\Database\DatabasePool; use phpOMS\System\File\Local\Directory; +use phpOMS\System\File\Local\File; use phpOMS\System\File\PathException; use phpOMS\System\File\PermissionException; use phpOMS\Utils\Parser\Php\ArrayParser; @@ -73,7 +74,6 @@ class InstallerAbstract $sth->bindValue(':from', $val['from'], \PDO::PARAM_STR); $sth->bindValue(':for', $val['for'], \PDO::PARAM_STR); $sth->bindValue(':file', $val['file'], \PDO::PARAM_STR); - $sth->execute(); } } @@ -150,11 +150,13 @@ class InstallerAbstract { $directories = new Directory(\dirname($info->getPath()) . '/Admin/Routes'); - foreach ($directories as $key => $subdir) { - if ($subdir instanceof Directory) { - foreach ($subdir as $key2 => $file) { - self::installRoutes(__DIR__ . '/../../' . $subdir->getName() . '/' . basename($file->getName(), '.php') . '/Routes.php', $file->getPath()); + foreach ($directories as $key => $child) { + if ($child instanceof Directory) { + foreach ($child as $key2 => $file) { + self::installRoutes(__DIR__ . '/../../' . $child->getName() . '/' . \basename($file->getName(), '.php') . '/Routes.php', $file->getPath()); } + } elseif ($child instanceof File) { + self::installRoutes(__DIR__ . '/../../' . $child->getName() . '/Routes.php', $child->getPath()); } } } @@ -185,7 +187,7 @@ class InstallerAbstract throw new PathException($destRoutePath); } - if (!is_writable($destRoutePath)) { + if (!\is_writable($destRoutePath)) { throw new PermissionException($destRoutePath); } @@ -194,7 +196,7 @@ class InstallerAbstract /** @noinspection PhpIncludeInspection */ $moduleRoutes = include $srcRoutePath; - $appRoutes = array_merge_recursive($appRoutes, $moduleRoutes); + $appRoutes = \array_merge_recursive($appRoutes, $moduleRoutes); \file_put_contents($destRoutePath, 'getPath()) . '/Admin/Hooks'); - foreach ($directories as $key => $subdir) { - if ($subdir instanceof Directory) { - foreach ($subdir as $key2 => $file) { - self::installHooks(__DIR__ . '/../../' . $subdir->getName() . '/' . basename($file->getName(), '.php') . '/Hooks.php', $file->getPath()); + foreach ($directories as $key => $child) { + if ($child instanceof Directory) { + foreach ($child as $key2 => $file) { + self::installHooks(__DIR__ . '/../../' . $child->getName() . '/' . \basename($file->getName(), '.php') . '/Hooks.php', $file->getPath()); } + } elseif ($child instanceof File) { + self::installRoutes(__DIR__ . '/../../' . $child->getName() . '/Hooks.php', $child->getPath()); } } } @@ -249,7 +253,7 @@ class InstallerAbstract throw new PathException($destHookPath); } - if (!is_writable($destHookPath)) { + if (!\is_writable($destHookPath)) { throw new PermissionException($destHookPath); } @@ -258,7 +262,7 @@ class InstallerAbstract /** @noinspection PhpIncludeInspection */ $moduleHooks = include $srcHookPath; - $appHooks = array_merge_recursive($appHooks, $moduleHooks); + $appHooks = \array_merge_recursive($appHooks, $moduleHooks); \file_put_contents($destHookPath, 'routes += include $path; @@ -105,7 +96,7 @@ final class Router if ($request instanceof RequestAbstract) { $uri = $request->getUri()->getRoute(); $verb = $request->getRouteVerb(); - } elseif (is_string($request)) { + } elseif (\is_string($request)) { $uri = $request; } else { throw new \InvalidArgumentException(); diff --git a/Uri/Argument.php b/Uri/Argument.php index bbd50c006..1b5196197 100644 --- a/Uri/Argument.php +++ b/Uri/Argument.php @@ -145,6 +145,11 @@ final class Argument implements UriInterface public function set(string $uri) : void { $this->uri = $uri; + + $temp = $this->__toString(); + $found = \stripos($temp, ':'); + $path = $found !== false && $found > 3 && $found < 8 ? \substr($temp, $found) : $temp; + $this->path = $path === false ? '' : $path; } /** diff --git a/tests/Console/CommandManagerTest.php b/tests/Console/CommandManagerTest.php deleted file mode 100644 index 60e60ba76..000000000 --- a/tests/Console/CommandManagerTest.php +++ /dev/null @@ -1,26 +0,0 @@ - Date: Fri, 27 Jul 2018 20:05:18 +0200 Subject: [PATCH 053/136] Fix factory return type --- DataStorage/Database/Connection/ConnectionFactory.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DataStorage/Database/Connection/ConnectionFactory.php b/DataStorage/Database/Connection/ConnectionFactory.php index 06016d28d..3d89957ea 100644 --- a/DataStorage/Database/Connection/ConnectionFactory.php +++ b/DataStorage/Database/Connection/ConnectionFactory.php @@ -44,13 +44,13 @@ final class ConnectionFactory * * @param string[] $dbdata the basic database information for establishing a connection * - * @return ConnectionInterface + * @return ConnectionAbstract * * @throws \InvalidArgumentException Throws this exception if the database is not supported. * * @since 1.0.0 */ - public static function create(array $dbdata) : ConnectionInterface + public static function create(array $dbdata) : ConnectionAbstract { switch ($dbdata['db']) { case DatabaseType::MYSQL: From 416f350fdb8d587372856b8b735df41fe0113557 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 27 Jul 2018 20:11:43 +0200 Subject: [PATCH 054/136] Hint orgId for public reads --- ApplicationAbstract.php | 1 + 1 file changed, 1 insertion(+) diff --git a/ApplicationAbstract.php b/ApplicationAbstract.php index 9bbc6d540..9a134a294 100644 --- a/ApplicationAbstract.php +++ b/ApplicationAbstract.php @@ -22,6 +22,7 @@ namespace phpOMS; * and afterwards read only. * * @property string $appName + * @property int $orgId * @property \phpOMS\DataStorage\Database\DatabasePool $dbPool * @property \phpOMS\Localization\L11nManager $l11nManager * @property \phpOMS\Router\Router $router From 999b60999fedccc4ebf4ccdf2b30d58a7002d050 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 28 Jul 2018 13:39:44 +0200 Subject: [PATCH 055/136] Fix pre minification bug --- Message/Http/Response.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Message/Http/Response.php b/Message/Http/Response.php index 4388aece6..9d04e324c 100644 --- a/Message/Http/Response.php +++ b/Message/Http/Response.php @@ -141,7 +141,7 @@ final class Response extends ResponseAbstract implements RenderableInterface /** * Remove whitespace and line break from render - * + * * @param string $render Rendered string * * @return string @@ -152,7 +152,7 @@ final class Response extends ResponseAbstract implements RenderableInterface { $types = $this->header->get('Content-Type'); if (\stripos($types[0], MimeType::M_HTML) !== false) { - return \trim(\preg_replace('/(\s{2,}|\n|\t)(?![^<>]*<\/pre>)/', ' ', $render)); + return \trim(\preg_replace('/(?s).*?<\/pre>(*SKIP)(*F)|(\s{2,}|\n|\t)/', ' ', $render)); } return $render; From 244e2e8d86427c86a46a80457db9e96751480da9 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 28 Jul 2018 20:45:46 +0200 Subject: [PATCH 056/136] Allow empty email --- Account/Account.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Account/Account.php b/Account/Account.php index 2cba85883..5c53f8cc7 100644 --- a/Account/Account.php +++ b/Account/Account.php @@ -453,11 +453,11 @@ class Account implements ArrayableInterface, \JsonSerializable */ public function setEmail(string $email) : void { - if (!Email::isValid($email)) { + if ($email !== '' && !Email::isValid($email)) { throw new \InvalidArgumentException(); } - $this->email = mb_strtolower($email); + $this->email = \mb_strtolower($email); } /** From ee018f124f32eb4323359e7441caa980ca975e30 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 28 Jul 2018 20:46:28 +0200 Subject: [PATCH 057/136] Prevent exception of arrays --- Message/Http/Response.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Message/Http/Response.php b/Message/Http/Response.php index 9d04e324c..c536881d7 100644 --- a/Message/Http/Response.php +++ b/Message/Http/Response.php @@ -131,6 +131,8 @@ final class Response extends ResponseAbstract implements RenderableInterface $render .= $response->serialize(); } elseif (\is_string($response) || \is_numeric($response)) { $render .= $response; + } elseif (\is_array($response)) { + $render .= \json_encode($response); } else { throw new \Exception('Wrong response type'); } From 9a220a85a7e4e1d94ce08b8d1012eeb3e060887f Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 28 Jul 2018 20:46:39 +0200 Subject: [PATCH 058/136] Use global namespace --- Validation/Network/Email.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Validation/Network/Email.php b/Validation/Network/Email.php index b6cfa2cb1..9cfdf0b8b 100644 --- a/Validation/Network/Email.php +++ b/Validation/Network/Email.php @@ -42,7 +42,7 @@ abstract class Email extends ValidatorAbstract */ public static function isValid($value, array $constraints = null) : bool { - if (filter_var($value, FILTER_VALIDATE_EMAIL) === false) { + if (\filter_var($value, FILTER_VALIDATE_EMAIL) === false) { self::$msg = 'Invalid Email by filter_var standards'; self::$error = 1; From 8a3b9ee2f80d6fee9f6e7e0bf07c15c290792493 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 29 Jul 2018 21:16:13 +0200 Subject: [PATCH 059/136] Use root namespace and impl. guess bin path --- Utils/TaskSchedule/Cron.php | 42 ----------- Utils/TaskSchedule/SchedulerAbstract.php | 95 +++++++++++++++++++++--- Utils/TaskSchedule/TaskScheduler.php | 42 ----------- 3 files changed, 86 insertions(+), 93 deletions(-) diff --git a/Utils/TaskSchedule/Cron.php b/Utils/TaskSchedule/Cron.php index 8279c7f63..c0f333e89 100644 --- a/Utils/TaskSchedule/Cron.php +++ b/Utils/TaskSchedule/Cron.php @@ -26,48 +26,6 @@ namespace phpOMS\Utils\TaskSchedule; class Cron extends SchedulerAbstract { - /** - * Run command - * - * @param string $cmd Command to run - * - * @return string - * - * @throws \Exception - * - * @since 1.0.0 - */ - private function run(string $cmd) : string - { - $cmd = 'cd ' . \escapeshellarg(\dirname(self::$bin)) . ' && ' . \basename(self::$bin) . ' ' . $cmd; - - $pipes = []; - $desc = [ - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - - $resource = \proc_open($cmd, $desc, $pipes, __DIR__, null); - $stdout = \stream_get_contents($pipes[1]); - $stderr = \stream_get_contents($pipes[2]); - - foreach ($pipes as $pipe) { - \fclose($pipe); - } - - if ($resource === false) { - throw new \Exception(); - } - - $status = \proc_close($resource); - - if ($status == -1) { - throw new \Exception($stderr); - } - - return trim($stdout); - } - /** * Normalize run result for easier parsing * diff --git a/Utils/TaskSchedule/SchedulerAbstract.php b/Utils/TaskSchedule/SchedulerAbstract.php index cd7ed7436..19647a3c2 100644 --- a/Utils/TaskSchedule/SchedulerAbstract.php +++ b/Utils/TaskSchedule/SchedulerAbstract.php @@ -61,11 +61,42 @@ abstract class SchedulerAbstract */ public static function setBin(string $path) : void { - if (realpath($path) === false) { + if (\realpath($path) === false) { throw new PathException($path); } - self::$bin = realpath($path); + self::$bin = \realpath($path); + } + + /** + * Gues git binary. + * + * @return bool + * + * @since 1.0.0 + */ + public static function guessBin() : bool + { + $paths = [ + 'c:/WINDOWS/system32/schtasks.exe', + 'd:/WINDOWS/system32/schtasks.exe', + 'e:/WINDOWS/system32/schtasks.exe', + 'f:/WINDOWS/system32/schtasks.exe', + '/usr/bin/crontab', + '/usr/sbin/crontab', + '/bin/crontab', + '/sbin/crontab', + ]; + + foreach ($paths as $path) { + if (\file_exists($path)) { + self::setBin($path); + + return true; + } + } + + return false; } /** @@ -79,16 +110,62 @@ abstract class SchedulerAbstract public static function test() : bool { $pipes = []; - $resource = proc_open(escapeshellarg(self::$bin), [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes); + $resource = \proc_open(\escapeshellarg(self::$bin), [1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes); - $stdout = stream_get_contents($pipes[1]); - $stderr = stream_get_contents($pipes[2]); - - foreach ($pipes as $pipe) { - fclose($pipe); + if ($resource === false) { + return false; } - return trim(proc_close($resource)) !== 127; + $stdout = \stream_get_contents($pipes[1]); + $stderr = \stream_get_contents($pipes[2]); + + foreach ($pipes as $pipe) { + \fclose($pipe); + } + + return \proc_close($resource) !== 127; + } + + /** + * Run command + * + * @param string $cmd Command to run + * + * @return string + * + * @throws \Exception + * + * @since 1.0.0 + */ + protected function run(string $cmd) : string + { + $cmd = 'cd ' . \escapeshellarg(\dirname(self::$bin)) . ' && ' . \basename(self::$bin) . ' ' . $cmd; + + $pipes = []; + $desc = [ + 1 => ['pipe', 'w'], + 2 => ['pipe', 'w'], + ]; + + $resource = \proc_open($cmd, $desc, $pipes, __DIR__, null); + if ($resource === false) { + return ''; + } + + $stdout = \stream_get_contents($pipes[1]); + $stderr = \stream_get_contents($pipes[2]); + + foreach ($pipes as $pipe) { + \fclose($pipe); + } + + $status = \proc_close($resource); + + if ($status === -1) { + throw new \Exception($stderr); + } + + return trim($stdout); } /** diff --git a/Utils/TaskSchedule/TaskScheduler.php b/Utils/TaskSchedule/TaskScheduler.php index f662541c3..bc0544237 100644 --- a/Utils/TaskSchedule/TaskScheduler.php +++ b/Utils/TaskSchedule/TaskScheduler.php @@ -25,48 +25,6 @@ namespace phpOMS\Utils\TaskSchedule; */ class TaskScheduler extends SchedulerAbstract { - /** - * Run command - * - * @param string $cmd Command to run - * - * @return string - * - * @throws \Exception - * - * @since 1.0.0 - */ - private function run(string $cmd) : string - { - $cmd = 'cd ' . \escapeshellarg(\dirname(self::$bin)) . ' && ' . \basename(self::$bin) . ' ' . $cmd; - - $pipes = []; - $desc = [ - 1 => ['pipe', 'w'], - 2 => ['pipe', 'w'], - ]; - - $resource = \proc_open($cmd, $desc, $pipes, __DIR__, null); - if ($resource === false) { - return ''; - } - - $stdout = \stream_get_contents($pipes[1]); - $stderr = \stream_get_contents($pipes[2]); - - foreach ($pipes as $pipe) { - \fclose($pipe); - } - - $status = \proc_close($resource); - - if ($status == -1) { - throw new \Exception($stderr); - } - - return trim($stdout); - } - /** * Normalize run result for easier parsing * From dbdce979042deb34dfd8858501d31a56b5ca39c4 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 29 Jul 2018 21:17:12 +0200 Subject: [PATCH 060/136] Make binary path private --- Utils/TaskSchedule/SchedulerAbstract.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Utils/TaskSchedule/SchedulerAbstract.php b/Utils/TaskSchedule/SchedulerAbstract.php index 19647a3c2..25cdf5a8e 100644 --- a/Utils/TaskSchedule/SchedulerAbstract.php +++ b/Utils/TaskSchedule/SchedulerAbstract.php @@ -34,7 +34,7 @@ abstract class SchedulerAbstract * @var string * @since 1.0.0 */ - protected static $bin = ''; + private static $bin = ''; /** * Get git binary. From 2b81ab274b0c45c596180f0593b367ea7af4dcdc Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 29 Jul 2018 21:30:37 +0200 Subject: [PATCH 061/136] Fix bad log lines --- Log/FileLogger.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Log/FileLogger.php b/Log/FileLogger.php index d295f7eea..56f8694e5 100644 --- a/Log/FileLogger.php +++ b/Log/FileLogger.php @@ -393,8 +393,13 @@ final class FileLogger implements LoggerInterface } \fseek($this->fp, 0); + $line = \fgetcsv($this->fp, 0, ';'); + + while ($line !== false && $line !== null) { + if (count($line) < 2) { + continue; + } - while (($line = \fgetcsv($this->fp, 0, ';')) !== false) { $line[1] = trim($line[1]); if (!isset($levels[$line[1]])) { @@ -402,6 +407,7 @@ final class FileLogger implements LoggerInterface } $levels[$line[1]]++; + $line = \fgetcsv($this->fp, 0, ';'); } \fseek($this->fp, 0, SEEK_END); @@ -434,8 +440,13 @@ final class FileLogger implements LoggerInterface } \fseek($this->fp, 0); + $line = \fgetcsv($this->fp, 0, ';'); + + while ($line !== false && $line !== null) { + if (count($line) < 3) { + continue; + } - while (($line = \fgetcsv($this->fp, 0, ';')) !== false) { $line[2] = trim($line[2]); if (!isset($connection[$line[2]])) { @@ -443,6 +454,7 @@ final class FileLogger implements LoggerInterface } $connection[$line[2]]++; + $line = \fgetcsv($this->fp, 0, ';'); } \fseek($this->fp, 0, SEEK_END); From 8f3c90718f9ecf058b6bc31b572ce11ebae607db Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 29 Jul 2018 21:35:51 +0200 Subject: [PATCH 062/136] Use global namespace --- Log/FileLogger.php | 52 +++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/Log/FileLogger.php b/Log/FileLogger.php index 56f8694e5..33e4fcac4 100644 --- a/Log/FileLogger.php +++ b/Log/FileLogger.php @@ -102,7 +102,7 @@ final class FileLogger implements LoggerInterface $this->verbose = $verbose; if (\is_dir($lpath) || \strpos($lpath, '.') === false) { - $path = $lpath . '/' . date('Y-m-d') . '.log'; + $path = $lpath . '/' . \date('Y-m-d') . '.log'; } else { $path = $lpath; } @@ -154,7 +154,7 @@ final class FileLogger implements LoggerInterface */ public function __destruct() { - if (is_resource($this->fp)) { + if (\is_resource($this->fp)) { \fclose($this->fp); } } @@ -232,7 +232,7 @@ final class FileLogger implements LoggerInterface $replace['{' . $key . '}'] = $val; } - $backtrace = debug_backtrace(); + $backtrace = \debug_backtrace(); // Removing sensitive config data from logging foreach ($backtrace as $key => $value) { @@ -244,15 +244,15 @@ final class FileLogger implements LoggerInterface $backtrace = \json_encode($backtrace); $replace['{backtrace}'] = $backtrace; - $replace['{datetime}'] = sprintf('%--19s', (new \DateTime('NOW'))->format('Y-m-d H:i:s')); - $replace['{level}'] = sprintf('%--12s', $level); + $replace['{datetime}'] = \sprintf('%--19s', (new \DateTime('NOW'))->format('Y-m-d H:i:s')); + $replace['{level}'] = \sprintf('%--12s', $level); $replace['{path}'] = $_SERVER['REQUEST_URI'] ?? 'REQUEST_URI'; - $replace['{ip}'] = sprintf('%--15s', $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'); - $replace['{version}'] = sprintf('%--15s', PHP_VERSION); - $replace['{os}'] = sprintf('%--15s', PHP_OS); - $replace['{line}'] = sprintf('%--15s', $context['line'] ?? '?'); + $replace['{ip}'] = \sprintf('%--15s', $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'); + $replace['{version}'] = \sprintf('%--15s', PHP_VERSION); + $replace['{os}'] = \sprintf('%--15s', PHP_OS); + $replace['{line}'] = \sprintf('%--15s', $context['line'] ?? '?'); - return strtr($message, $replace); + return \strtr($message, $replace); } /** @@ -400,7 +400,7 @@ final class FileLogger implements LoggerInterface continue; } - $line[1] = trim($line[1]); + $line[1] = \trim($line[1]); if (!isset($levels[$line[1]])) { $levels[$line[1]] = 0; @@ -447,7 +447,7 @@ final class FileLogger implements LoggerInterface continue; } - $line[2] = trim($line[2]); + $line[2] = \trim($line[2]); if (!isset($connection[$line[2]])) { $connection[$line[2]] = 0; @@ -459,9 +459,9 @@ final class FileLogger implements LoggerInterface \fseek($this->fp, 0, SEEK_END); \fclose($this->fp); - asort($connection); + \asort($connection); - return array_slice($connection, 0, $limit); + return \array_slice($connection, 0, $limit); } /** @@ -506,7 +506,7 @@ final class FileLogger implements LoggerInterface } foreach ($line as &$value) { - $value = trim($value); + $value = \trim($value); } $logs[$id] = $line; @@ -554,16 +554,16 @@ final class FileLogger implements LoggerInterface continue; } - $log['datetime'] = trim($line[0] ?? ''); - $log['level'] = trim($line[1] ?? ''); - $log['ip'] = trim($line[2] ?? ''); - $log['line'] = trim($line[3] ?? ''); - $log['version'] = trim($line[4] ?? ''); - $log['os'] = trim($line[5] ?? ''); - $log['path'] = trim($line[6] ?? ''); - $log['message'] = trim($line[7] ?? ''); - $log['file'] = trim($line[8] ?? ''); - $log['backtrace'] = trim($line[9] ?? ''); + $log['datetime'] = \trim($line[0] ?? ''); + $log['level'] = \trim($line[1] ?? ''); + $log['ip'] = \trim($line[2] ?? ''); + $log['line'] = \trim($line[3] ?? ''); + $log['version'] = \trim($line[4] ?? ''); + $log['os'] = \trim($line[5] ?? ''); + $log['path'] = \trim($line[6] ?? ''); + $log['message'] = \trim($line[7] ?? ''); + $log['file'] = \trim($line[8] ?? ''); + $log['backtrace'] = \trim($line[9] ?? ''); break; } @@ -587,7 +587,7 @@ final class FileLogger implements LoggerInterface public function console(string $message, bool $verbose = true, array $context = []) : void { if (empty($context)) { - $message = date('[Y-m-d H:i:s] ') . $message . "\r\n"; + $message = \date('[Y-m-d H:i:s] ') . $message . "\r\n"; } if ($verbose) { From 47dfb029f70a8d94e583e8507202ce1fb6ed47bf Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 29 Jul 2018 21:37:09 +0200 Subject: [PATCH 063/136] Fix indention --- Log/LoggerInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Log/LoggerInterface.php b/Log/LoggerInterface.php index 1cb97d030..c16454d3a 100644 --- a/Log/LoggerInterface.php +++ b/Log/LoggerInterface.php @@ -119,7 +119,7 @@ interface LoggerInterface /** * Logs with an arbitrary level. * - * @param string $level Log level/severeness + * @param string $level Log level/severeness * @param string $message Logging message schema * @param array $context Context to log * From 6a14f221ee14f9deab7d6ff1120207926d60dbd9 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 29 Jul 2018 21:53:21 +0200 Subject: [PATCH 064/136] Add abstract function --- Utils/TaskSchedule/SchedulerAbstract.php | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Utils/TaskSchedule/SchedulerAbstract.php b/Utils/TaskSchedule/SchedulerAbstract.php index 25cdf5a8e..489ae85aa 100644 --- a/Utils/TaskSchedule/SchedulerAbstract.php +++ b/Utils/TaskSchedule/SchedulerAbstract.php @@ -181,4 +181,16 @@ abstract class SchedulerAbstract { $this->run($task->getCommand()); } + + /** + * Get all jobs/tasks by name + * + * @param string $name Name of the job + * @param bool $exact Name has to be exact + * + * @return array + * + * @since 1.0.0 + */ + abstract public function getAllByName(string $name, bool $exact = true) : array; } From 57da54ad449269cbcd978662c2d012a393449a77 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 31 Jul 2018 18:24:49 +0200 Subject: [PATCH 065/136] Fix download and code inspection bugs --- Message/Http/Rest.php | 12 ++++++++++-- Security/PhpCode.php | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/Message/Http/Rest.php b/Message/Http/Rest.php index 3245246c6..6cde97c18 100644 --- a/Message/Http/Rest.php +++ b/Message/Http/Rest.php @@ -42,7 +42,13 @@ final class Rest throw new \Exception(); } + curl_setopt($curl, CURLOPT_NOBODY, true); + curl_setopt($curl, CURLOPT_HEADER, false); + switch ($request->getMethod()) { + case RequestMethod::GET: + curl_setopt($curl, CURLOPT_HTTPGET, true); + break; case RequestMethod::PUT: \curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); break; @@ -59,8 +65,10 @@ final class Rest } } - \curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); - \curl_setopt($curl, CURLOPT_USERPWD, 'username:password'); + if ($request->getUri()->getUser() !== '') { + \curl_setopt($curl, CURLOPT_HTTPAUTH, CURLAUTH_BASIC); + \curl_setopt($curl, CURLOPT_USERPWD, $request->getUri()->getUserInfo()); + } \curl_setopt($curl, CURLOPT_URL, $request->__toString()); \curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); diff --git a/Security/PhpCode.php b/Security/PhpCode.php index b3d403141..a6ca86393 100644 --- a/Security/PhpCode.php +++ b/Security/PhpCode.php @@ -156,4 +156,19 @@ final class PhpCode { return \md5_file($source) === $hash; } + + /** + * Validate code integrety + * + * @param string $source Source code + * @param string $remote Remote code + * + * @return bool + * + * @since 1.0.0 + */ + public static function validateStringIntegrity(string $source, string $remote) : bool + { + return $source === $remote; + } } From 1e023a12470cba212a7f698fc190e903d954ed67 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Tue, 31 Jul 2018 20:10:20 +0200 Subject: [PATCH 066/136] Fix depth handling --- DataStorage/Database/DataMapperAbstract.php | 73 ++++++++++----------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index edeaebac3..9c2ab6a95 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -1505,7 +1505,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function populateManyToMany(array $result, &$obj, int $depth = null) : void + public static function populateManyToMany(array $result, &$obj, int $depth = 3) : void { // todo: maybe pass reflectionClass as optional parameter for performance increase $refClass = new \ReflectionClass($obj); @@ -1541,7 +1541,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function populateManyToManyArray(array $result, array &$obj, int $depth = null) : void + public static function populateManyToManyArray(array $result, array &$obj, int $depth = 3) : void { foreach ($result as $member => $values) { if (!empty($values)) { @@ -1566,7 +1566,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function populateHasOne(&$obj, int $depth = null) : void + public static function populateHasOne(&$obj, int $depth = 3) : void { $refClass = new \ReflectionClass($obj); @@ -1611,7 +1611,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function populateHasOneArray(array &$obj, int $depth = null) : void + public static function populateHasOneArray(array &$obj, int $depth = 3) : void { foreach (static::$hasOne as $member => $one) { /** @var string $mapper */ @@ -1632,7 +1632,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function populateOwnsOne(&$obj, int $depth = null) : void + public static function populateOwnsOne(&$obj, int $depth = 3) : void { $refClass = new \ReflectionClass($obj); @@ -1677,7 +1677,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function populateOwnsOneArray(array &$obj, int $depth = null) : void + public static function populateOwnsOneArray(array &$obj, int $depth = 3) : void { foreach (static::$ownsOne as $member => $one) { /** @var string $mapper */ @@ -1698,7 +1698,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function populateBelongsTo(&$obj, int $depth = null) : void + public static function populateBelongsTo(&$obj, int $depth = 3) : void { $refClass = new \ReflectionClass($obj); @@ -1743,7 +1743,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function populateBelongsToArray(array &$obj, int $depth = null) : void + public static function populateBelongsToArray(array &$obj, int $depth = 3) : void { foreach (static::$belongsTo as $member => $one) { /** @var string $mapper */ @@ -1887,9 +1887,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function get($primaryKey, int $relations = RelationType::ALL, $fill = null, int $depth = null) + public static function get($primaryKey, int $relations = RelationType::ALL, $fill = null, int $depth = 3) { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return $primaryKey; } @@ -1925,7 +1925,7 @@ class DataMapperAbstract implements DataMapperInterface self::addInitialized(static::class, $value, $obj[$value]); } - self::fillRelations($obj, $relations, isset($depth) ? --$depth : null); + self::fillRelations($obj, $relations, --$depth); self::clear(); $countResulsts = count($obj); @@ -1969,9 +1969,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function getArray($primaryKey, int $relations = RelationType::ALL, int $depth = null) : array + public static function getArray($primaryKey, int $relations = RelationType::ALL, int $depth = 3) : array { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return $primaryKey; } @@ -1995,7 +1995,7 @@ class DataMapperAbstract implements DataMapperInterface self::addInitialized(static::class, $value, $obj[$value]); } - self::fillRelationsArray($obj, $relations, isset($depth) ? --$depth : null); + self::fillRelationsArray($obj, $relations, --$depth); self::clear(); return count($obj) === 1 ? reset($obj) : $obj; @@ -2014,9 +2014,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function getFor($refKey, string $ref, int $relations = RelationType::ALL, $fill = null, int $depth = null) + public static function getFor($refKey, string $ref, int $relations = RelationType::ALL, $fill = null, int $depth = 3) { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return $refKey; } @@ -2038,7 +2038,7 @@ class DataMapperAbstract implements DataMapperInterface $toLoad = self::getPrimaryKeysBy($value, self::getColumnByMember($ref)); } - $obj[$value] = self::get($toLoad, $relations, $fill, isset($depth) ? --$depth : null); + $obj[$value] = self::get($toLoad, $relations, $fill, --$depth); } $countResulsts = count($obj); @@ -2101,9 +2101,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function getAll(int $relations = RelationType::ALL, int $depth = null, string $lang = '') : array + public static function getAll(int $relations = RelationType::ALL, int $depth = 3, string $lang = '') : array { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return []; } @@ -2112,7 +2112,7 @@ class DataMapperAbstract implements DataMapperInterface } $obj = self::populateIterable(self::getAllRaw($lang)); - self::fillRelations($obj, $relations, isset($depth) ? --$depth : null); + self::fillRelations($obj, $relations, --$depth); self::clear(); return $obj; @@ -2129,9 +2129,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function getAllArray(int $relations = RelationType::ALL, int $depth = null, string $lang = '') : array + public static function getAllArray(int $relations = RelationType::ALL, int $depth = 3, string $lang = '') : array { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return []; } @@ -2140,7 +2140,7 @@ class DataMapperAbstract implements DataMapperInterface } $obj = self::populateIterableArray(self::getAllRaw($lang)); - self::fillRelationsArray($obj, $relations, isset($depth) ? --$depth : null); + self::fillRelationsArray($obj, $relations, --$depth); self::clear(); return $obj; @@ -2184,9 +2184,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function getNewest(int $limit = 1, Builder $query = null, int $relations = RelationType::ALL, int $depth = null, string $lang = '') : array + public static function getNewest(int $limit = 1, Builder $query = null, int $relations = RelationType::ALL, int $depth = 3, string $lang = '') : array { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return []; } @@ -2212,11 +2212,10 @@ class DataMapperAbstract implements DataMapperInterface $results = $sth->fetchAll(\PDO::FETCH_ASSOC); $obj = self::populateIterable($results === false ? [] : $results); - self::fillRelations($obj, $relations, isset($depth) ? --$depth : null); + self::fillRelations($obj, $relations, --$depth); self::clear(); return $obj; - } /** @@ -2230,9 +2229,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function getAllByQuery(Builder $query, int $relations = RelationType::ALL, int $depth = null) : array + public static function getAllByQuery(Builder $query, int $relations = RelationType::ALL, int $depth = 3) : array { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return []; } @@ -2243,7 +2242,7 @@ class DataMapperAbstract implements DataMapperInterface $results = $results === false ? [] : $results; $obj = self::populateIterable($results); - self::fillRelations($obj, $relations, isset($depth) ? --$depth : null); + self::fillRelations($obj, $relations, --$depth); self::clear(); return $obj; @@ -2260,9 +2259,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function getRandom(int $amount = 1, int $relations = RelationType::ALL, int $depth = null) + public static function getRandom(int $amount = 1, int $relations = RelationType::ALL, int $depth = 3) { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return null; } @@ -2289,9 +2288,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function fillRelations(array &$obj, int $relations = RelationType::ALL, int $depth = null) : void + public static function fillRelations(array &$obj, int $relations = RelationType::ALL, int $depth = 3) : void { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return; } @@ -2339,9 +2338,9 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - public static function fillRelationsArray(array &$obj, int $relations = RelationType::ALL, int $depth = null) : void + public static function fillRelationsArray(array &$obj, int $relations = RelationType::ALL, int $depth = 3) : void { - if (isset($depth) && $depth < 1) { + if ($depth < 1) { return; } @@ -2454,7 +2453,7 @@ class DataMapperAbstract implements DataMapperInterface if ($result === false) { return []; } - + return \array_column($result, 0); } From cdfb8894b999fc8aa6bf01e66c45ee0785101b13 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Wed, 1 Aug 2018 19:42:00 +0200 Subject: [PATCH 067/136] Add encoding change function --- System/File/FileUtils.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/System/File/FileUtils.php b/System/File/FileUtils.php index 9b044fe8b..d7b35825d 100644 --- a/System/File/FileUtils.php +++ b/System/File/FileUtils.php @@ -117,4 +117,23 @@ final class FileUtils return \realpath($origPath); } + + /** + * Change encoding of file + * + * @param string $file Path to file which should be re-encoded + * @param string $encoding New file encoding + * + * @return void + * + * @since 1.0.0 + */ + public static function changeFileEncoding(string $file, string $encoding) : void + { + $content = \file_get_contents($file); + + if ($content !== false && preg_match('!!u', $content)) { + \file_put_contents($file, \mb_convert_encoding($content, 'UTF-8', mb_list_encodings())); + } + } } From 6cc520a579799ee3078f2e2f535220e20672cb6c Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Wed, 1 Aug 2018 22:08:20 +0200 Subject: [PATCH 068/136] Fix mapper depth bugs and implement math evaluator --- DataStorage/Database/DataMapperAbstract.php | 108 +++++++++-------- Localization/L11nManager.php | 4 +- Math/Parser/Evaluator.php | 125 +++++++++++++++++--- Module/ModuleAbstract.php | 2 +- tests/Math/Parser/EvaluatorTest.php | 7 +- 5 files changed, 179 insertions(+), 67 deletions(-) diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index 9c2ab6a95..578362bc1 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -402,7 +402,7 @@ class DataMapperAbstract implements DataMapperInterface $query->prefix(self::$db->getPrefix())->into(static::$table); foreach (static::$columns as $key => $column) { - $propertyName = \stripos($column['internal'], '/') !== false ? explode('/', $column['internal'])[0] : $column['internal']; + $propertyName = \stripos($column['internal'], '/') !== false ? \explode('/', $column['internal'])[0] : $column['internal']; if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName])) { continue; } @@ -425,11 +425,11 @@ class DataMapperAbstract implements DataMapperInterface $query->insert($column['name'])->value($value, $column['type']); } elseif ($column['name'] !== static::$primaryField) { $tValue = $property->getValue($obj); - if (stripos($column['internal'], '/') !== false) { + if (\stripos($column['internal'], '/') !== false) { $path = \explode('/', $column['internal']); - array_shift($path); - $path = implode('/', $path); + \array_shift($path); + $path = \implode('/', $path); $tValue = ArrayUtils::getArray($path, $tValue, '/'); } @@ -475,11 +475,11 @@ class DataMapperAbstract implements DataMapperInterface } $path = $column['internal']; - if (stripos($column['internal'], '/') !== false) { + if (\stripos($column['internal'], '/') !== false) { $path = \explode('/', $column['internal']); - array_shift($path); - $path = implode('/', $path); + \array_shift($path); + $path = \implode('/', $path); } $property = ArrayUtils::getArray($path, $obj, '/'); @@ -602,7 +602,7 @@ class DataMapperAbstract implements DataMapperInterface $relReflectionClass = null; foreach ($values as $key => &$value) { - if (!is_object($value)) { + if (!\is_object($value)) { // Is scalar => already in database $objsIds[$key] = $value; @@ -732,7 +732,7 @@ class DataMapperAbstract implements DataMapperInterface */ private static function createOwnsOne(string $propertyName, $obj) { - if (is_object($obj)) { + if (\is_object($obj)) { $mapper = static::$ownsOne[$propertyName]['mapper']; $primaryKey = $mapper::getObjectId($obj); @@ -788,7 +788,7 @@ class DataMapperAbstract implements DataMapperInterface */ private static function createBelongsTo(string $propertyName, $obj) { - if (is_object($obj)) { + if (\is_object($obj)) { /** @var string $mapper */ $mapper = static::$belongsTo[$propertyName]['mapper']; $primaryKey = $mapper::getObjectId($obj); @@ -895,7 +895,7 @@ class DataMapperAbstract implements DataMapperInterface return $value->serialize(); } elseif ($value instanceof \JsonSerializable) { return (string) \json_encode($value->jsonSerialize()); - } elseif (is_object($value) && method_exists($value, 'getId')) { + } elseif (\is_object($value) && method_exists($value, 'getId')) { return $value->getId(); } @@ -905,9 +905,11 @@ class DataMapperAbstract implements DataMapperInterface /** * Update has many * - * @param \ReflectionClass $refClass Reflection class - * @param object $obj Object to create - * @param mixed $objId Id to set + * @param \ReflectionClass $refClass Reflection class + * @param object $obj Object to create + * @param mixed $objId Id to set + * @param int $relations Create all relations as well + * @param int $depth Depth of relations to update (default = 1 = none) * * @return void * @@ -915,7 +917,7 @@ class DataMapperAbstract implements DataMapperInterface * * @since 1.0.0 */ - private static function updateHasMany(\ReflectionClass $refClass, object $obj, $objId) : void + private static function updateHasMany(\ReflectionClass $refClass, object $obj, $objId, int $relations = RelationType::ALL, $depth = 1) : void { $objsIds = []; @@ -942,7 +944,7 @@ class DataMapperAbstract implements DataMapperInterface $objsIds[$propertyName] = []; foreach ($values as $key => &$value) { - if (!is_object($value)) { + if (!\is_object($value)) { // Is scalar => already in database $objsIds[$propertyName][$key] = $value; @@ -957,7 +959,7 @@ class DataMapperAbstract implements DataMapperInterface // already in db if (!empty($primaryKey)) { - $mapper::update($value); + $mapper::update($value, $relations, $depth); $objsIds[$propertyName][$key] = $value; @@ -1056,19 +1058,21 @@ class DataMapperAbstract implements DataMapperInterface * * @param string $propertyName Property name to initialize * @param object $obj Object to update + * @param int $relations Create all relations as well + * @param int $depth Depth of relations to update (default = 1 = none) * * @return mixed * * @since 1.0.0 */ - private static function updateOwnsOne(string $propertyName, object $obj) + private static function updateOwnsOne(string $propertyName, object $obj, int $relations = RelationType::ALL, int $depth = 1) { /** @var string $mapper */ $mapper = static::$ownsOne[$propertyName]['mapper']; // todo: delete owned one object is not recommended since it can be owned by by something else? or does owns one mean that nothing else can have a relation to this one? - return $mapper::update($obj); + return $mapper::update($obj, $relations, $depth); } /** @@ -1078,18 +1082,20 @@ class DataMapperAbstract implements DataMapperInterface * * @param string $propertyName Property name to initialize * @param mixed $obj Object to update + * @param int $relations Create all relations as well + * @param int $depth Depth of relations to update (default = 1 = none) * * @return mixed * * @since 1.0.0 */ - private static function updateBelongsTo(string $propertyName, $obj) + private static function updateBelongsTo(string $propertyName, $obj, int $relations = RelationType::ALL, int $depth = 1) { - if (is_object($obj)) { + if (\is_object($obj)) { /** @var string $mapper */ $mapper = static::$belongsTo[$propertyName]['mapper']; - return $mapper::update($obj); + return $mapper::update($obj, $relations, $depth); } return $obj; @@ -1098,15 +1104,17 @@ class DataMapperAbstract implements DataMapperInterface /** * Update object in db. * - * @param object $obj Model to update - * @param mixed $objId Model id - * @param \ReflectionClass $refClass Reflection class + * @param object $obj Model to update + * @param mixed $objId Model id + * @param \ReflectionClass $refClass Reflection class + * @param int $relations Create all relations as well + * @param int $depth Depth of relations to update (default = 1 = none) * * @return void * * @since 1.0.0 */ - private static function updateModel(object $obj, $objId, \ReflectionClass $refClass = null) : void + private static function updateModel(object $obj, $objId, \ReflectionClass $refClass = null, int $relations = RelationType::ALL, int $depth = 1) : void { $query = new Builder(self::$db); $query->prefix(self::$db->getPrefix()) @@ -1114,7 +1122,7 @@ class DataMapperAbstract implements DataMapperInterface ->where(static::$table . '.' . static::$primaryField, '=', $objId); foreach (static::$columns as $key => $column) { - $propertyName = \stripos($column['internal'], '/') !== false ? explode('/', $column['internal'])[0] : $column['internal']; + $propertyName = \stripos($column['internal'], '/') !== false ? \explode('/', $column['internal'])[0] : $column['internal']; if (isset(static::$hasMany[$propertyName]) || isset(static::$hasOne[$propertyName]) || $column['internal'] === static::$primaryField @@ -1130,24 +1138,24 @@ class DataMapperAbstract implements DataMapperInterface } if (isset(static::$ownsOne[$propertyName])) { - $id = self::updateOwnsOne($propertyName, $property->getValue($obj)); + $id = self::updateOwnsOne($propertyName, $property->getValue($obj), $relations, $depth); $value = self::parseValue($column['type'], $id); // todo: should not be done if the id didn't change. but for now don't know if id changed $query->set([static::$table . '.' . $column['name'] => $value], $column['type']); } elseif (isset(static::$belongsTo[$propertyName])) { - $id = self::updateBelongsTo($propertyName, $property->getValue($obj)); + $id = self::updateBelongsTo($propertyName, $property->getValue($obj), $relations, $depth); $value = self::parseValue($column['type'], $id); // todo: should not be done if the id didn't change. but for now don't know if id changed $query->set([static::$table . '.' . $column['name'] => $value], $column['type']); } elseif ($column['name'] !== static::$primaryField) { $tValue = $property->getValue($obj); - if (stripos($column['internal'], '/') !== false) { + if (\stripos($column['internal'], '/') !== false) { $path = \explode('/', $column['internal']); - array_shift($path); - $path = implode('/', $path); + \array_shift($path); + $path = \implode('/', $path); $tValue = ArrayUtils::getArray($path, $tValue, '/'); } $value = self::parseValue($column['type'], $tValue); @@ -1168,12 +1176,13 @@ class DataMapperAbstract implements DataMapperInterface * * @param mixed $obj Object reference (gets filled with insert id) * @param int $relations Create all relations as well + * @param int $depth Depth of relations to update (default = 1 = none) * * @return mixed * * @since 1.0.0 */ - public static function update($obj, int $relations = RelationType::ALL) + public static function update($obj, int $relations = RelationType::ALL, int $depth = 1) { self::extend(__CLASS__); @@ -1185,8 +1194,11 @@ class DataMapperAbstract implements DataMapperInterface $objId = self::getObjectId($obj, $refClass); $update = true; - // todo: maybe don't remove obj and just update cache... ? since it might have to be loaded again - self::removeInitialized(static::class, $objId); + if ($depth < 1) { + return $objId; + } + + self::addInitialized(static::class, $objId, $obj); if (empty($objId)) { $update = false; @@ -1194,11 +1206,11 @@ class DataMapperAbstract implements DataMapperInterface } if ($relations === RelationType::ALL) { - self::updateHasMany($refClass, $obj, $objId); + self::updateHasMany($refClass, $obj, $objId, --$depth); } if ($update) { - self::updateModel($obj, $objId, $refClass); + self::updateModel($obj, $objId, $refClass, --$depth); } return $objId; @@ -1243,7 +1255,7 @@ class DataMapperAbstract implements DataMapperInterface $relReflectionClass = null; foreach ($values as $key => &$value) { - if (!is_object($value)) { + if (!\is_object($value)) { // Is scalar => already in database $objsIds[$key] = $value; @@ -1289,7 +1301,7 @@ class DataMapperAbstract implements DataMapperInterface */ private static function deleteOwnsOne(string $propertyName, $obj) { - if (is_object($obj)) { + if (\is_object($obj)) { /** @var string $mapper */ $mapper = static::$ownsOne[$propertyName]['mapper']; @@ -1314,7 +1326,7 @@ class DataMapperAbstract implements DataMapperInterface */ private static function deleteBelongsTo(string $propertyName, $obj) { - if (is_object($obj)) { + if (\is_object($obj)) { /** @var string $mapper */ $mapper = static::$belongsTo[$propertyName]['mapper']; @@ -1484,7 +1496,7 @@ class DataMapperAbstract implements DataMapperInterface $parts = \explode('\\', $class); $name = $parts[$c = (count($parts) - 1)]; $parts[$c] = 'Null' . $name; - $class = implode('\\', $parts); + $class = \implode('\\', $parts); } if (!isset($obj)) { @@ -1777,7 +1789,7 @@ class DataMapperAbstract implements DataMapperInterface $aValue = []; $arrayPath = ''; - if (stripos(static::$columns[$column]['internal'], '/') !== false) { + if (\stripos(static::$columns[$column]['internal'], '/') !== false) { $hasPath = true; $path = \explode('/', static::$columns[$column]['internal']); $refProp = $refClass->getProperty($path[0]); @@ -1786,8 +1798,8 @@ class DataMapperAbstract implements DataMapperInterface $refProp->setAccessible(true); } - array_shift($path); - $arrayPath = implode('/', $path); + \array_shift($path); + $arrayPath = \implode('/', $path); $aValue = $refProp->getValue($obj); } else { $refProp = $refClass->getProperty(static::$columns[$column]['internal']); @@ -1851,11 +1863,11 @@ class DataMapperAbstract implements DataMapperInterface foreach ($result as $column => $value) { if (isset(static::$columns[$column]['internal'])) { $path = static::$columns[$column]['internal']; - if (stripos($path, '/') !== false) { + if (\stripos($path, '/') !== false) { $path = \explode('/', $path); - array_shift($path); - $path = implode('/', $path); + \array_shift($path); + $path = \implode('/', $path); } if (\in_array(static::$columns[$column]['type'], ['string', 'int', 'float', 'bool'])) { @@ -1953,7 +1965,7 @@ class DataMapperAbstract implements DataMapperInterface $parts = \explode('\\', $class); $name = $parts[$c = (count($parts) - 1)]; $parts[$c] = 'Null' . $name; - $class = implode('\\', $parts); + $class = \implode('\\', $parts); return new $class(); } diff --git a/Localization/L11nManager.php b/Localization/L11nManager.php index 28759f624..7119c9f3e 100644 --- a/Localization/L11nManager.php +++ b/Localization/L11nManager.php @@ -106,7 +106,7 @@ final class L11nManager public function loadLanguageFromFile(string $language, string $from, string $file) : void { $lang = []; - if (file_exists($file)) { + if (\file_exists($file)) { /** @noinspection PhpIncludeInspection */ $lang = include $file; } @@ -184,6 +184,6 @@ final class L11nManager */ public function getHtml(string $code, string $module, string $theme, $translation) : string { - return htmlspecialchars($this->getText($code, $module, $theme, $translation)); + return \htmlspecialchars($this->getText($code, $module, $theme, $translation)); } } diff --git a/Math/Parser/Evaluator.php b/Math/Parser/Evaluator.php index 2aab74418..f26f0819d 100644 --- a/Math/Parser/Evaluator.php +++ b/Math/Parser/Evaluator.php @@ -15,7 +15,7 @@ declare(strict_types=1); namespace phpOMS\Math\Parser; /** - * Shape interface. + * Basic math function evaluation. * * @package Framework * @license OMS License 1.0 @@ -27,10 +27,7 @@ class Evaluator /** * Evaluate function. * - * Example: ('2*x^3-4x', ['x' => 99]) - * - * @param string $formula Formula to differentiate - * @param array $vars Variables to evaluate + * @param string $equation Formula to evaluate * * @return float * @@ -38,18 +35,118 @@ class Evaluator * * @since 1.0.0 */ - public static function evaluate(string $formula, array $vars) : float + public static function evaluate(string $equation) : ?float { - // todo: do i need array_values here? - $formula = \str_replace(array_keys($vars), array_values($vars), $formula); - - // todo: this is horrible in case things like mod etc. need to be supported - if (\preg_match('#[^0-9\+\-\*\/\(\)]#', $formula)) { - throw new \Exception('Bad elements'); + if (\preg_match('#[^0-9\+\-\*\/\(\)\ \^\.]#', $equation)) { + return null; } - // todo: create parser + $stack = []; + $postfix = self::shuntingYard($equation); - return 0; + foreach ($postfix as $i => $value) { + if (\is_numeric($value)) { + $stack[] = $value; + } else { + $a = self::parseValue(\array_pop($stack)); + $b = self::parseValue(\array_pop($stack)); + + if ($value === '+') { + $stack[] = $a + $b; + } elseif ($value === '-') { + $stack[] = $b - $a; + } elseif ($value === '*') { + $stack[] = $a * $b; + } elseif ($value === '/') { + $stack[] = $b / $a; + } elseif ($value === '^') { + $stack[] = $b ** $a; + } + } + } + + $result = \array_pop($stack); + + return \is_numeric($result) ? (float) $result : null; + } + + /** + * Parse value. + * + * @param mixed $value Value to parse + * + * @return mixed + * + * @since 1.0.0 + */ + private static function parseValue($value) + { + return !\is_string($value) ? $value : (\stripos($value, '.') === false ? (int) $value : (float) $value); + } + + /** + * Shunting Yard algorithm. + * + * @param string $equation Equation to convert + * + * @return array + * + * @since 1.0.0 + */ + private static function shuntingYard(string $equation) : array + { + $stack = []; + $operators = [ + '^' => ['precedence' => 4, 'order' => 1], + '*' => ['precedence' => 3, 'order' => -1], + '/' => ['precedence' => 3, 'order' => -1], + '+' => ['precedence' => 2, 'order' => -1], + '-' => ['precedence' => 2, 'order' => -1], + ]; + $output = []; + + $equation = \str_replace(' ', '', $equation); + $equation = \preg_split('/([\+\-\*\/\^\(\)])/', $equation, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); + + if ($equation === false) { + return []; + } + + $equation = \array_filter($equation, function($n) { + return $n !== ''; + }); + + foreach ($equation as $i => $token) { + if (\is_numeric($token)) { + $output[] = $token; + } elseif (\strpbrk($token, '^*/+-') !== false) { + $o1 = $token; + $o2 = end($stack); + + while ($o2 !== false && \strpbrk($o2, '^*/+-') !== false + && (($operators[$o1]['order'] === -1 && $operators[$o1]['precedence'] <= $operators[$o2]['precedence']) + || ($operators[$o1]['order'] === 1 && $operators[$o1]['precedence'] < $operators[$o2]['precedence'])) + ) { + $output[] = \array_pop($stack); + $o2 = end($stack); + } + + $stack[] = $o1; + } elseif ($token === '(') { + $stack[] = $token; + } elseif ($token === ')') { + while (end($stack) !== '(') { + $output[] = \array_pop($stack); + } + + \array_pop($stack); + } + } + + while (count($stack) > 0) { + $output[] = \array_pop($stack); + } + + return $output; } } diff --git a/Module/ModuleAbstract.php b/Module/ModuleAbstract.php index 70a777e40..018b4351e 100644 --- a/Module/ModuleAbstract.php +++ b/Module/ModuleAbstract.php @@ -120,7 +120,7 @@ abstract class ModuleAbstract $lang = []; if (file_exists($oldPath = __DIR__ . '/../../Modules/' . static::MODULE_NAME . '/Theme/' . $destination . '/Lang/' . $language . '.lang.php')) { /** @noinspection PhpIncludeInspection */ - $lang = include $oldPath; + return include $oldPath; } return $lang; diff --git a/tests/Math/Parser/EvaluatorTest.php b/tests/Math/Parser/EvaluatorTest.php index a3b4729f5..6adfadd34 100644 --- a/tests/Math/Parser/EvaluatorTest.php +++ b/tests/Math/Parser/EvaluatorTest.php @@ -17,8 +17,11 @@ use phpOMS\Math\Parser\Evaluator; class EvaluatorTest extends \PHPUnit\Framework\TestCase { - public function testPlaceholder() + public function testBasicEvaluation() { - self::markTestIncomplete(); + self::assertEquals(4.5, Evaluator::evaluate('3 + 4 * 2 / ( 1 - 5 ) ^ 2 ^ 3 + 1.5'), '', 2); + self::assertEquals(4.5, Evaluator::evaluate('3+4*2/(1-5)^2^3+1.5'), '', 2); + self::assertEquals(null, Evaluator::evaluate('invalid')); + self::assertEquals(null, Evaluator::evaluate('3+4*2/(1-5^2^3+1.5')); } } From 16e0462a8921d92380ad5304faf8b368f8a5048f Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 2 Aug 2018 18:30:20 +0200 Subject: [PATCH 069/136] fixes #26 --- Utils/TaskSchedule/Cron.php | 15 --------------- Utils/TaskSchedule/CronJob.php | 20 +++++++++++++++++--- Utils/TaskSchedule/Schedule.php | 24 ++++++++++++------------ Utils/TaskSchedule/SchedulerAbstract.php | 14 ++++++++++++++ Utils/TaskSchedule/TaskScheduler.php | 14 -------------- 5 files changed, 43 insertions(+), 44 deletions(-) diff --git a/Utils/TaskSchedule/Cron.php b/Utils/TaskSchedule/Cron.php index c0f333e89..082888d67 100644 --- a/Utils/TaskSchedule/Cron.php +++ b/Utils/TaskSchedule/Cron.php @@ -25,21 +25,6 @@ namespace phpOMS\Utils\TaskSchedule; */ class Cron extends SchedulerAbstract { - - /** - * Normalize run result for easier parsing - * - * @param string $raw Raw command output - * - * @return string Normalized string for parsing - * - * @since 1.0.0 - */ - private function normalize(string $raw) : string - { - return \str_replace("\r\n", "\n", $raw); - } - /** * {@inheritdoc} */ diff --git a/Utils/TaskSchedule/CronJob.php b/Utils/TaskSchedule/CronJob.php index 9df129406..654eff21e 100644 --- a/Utils/TaskSchedule/CronJob.php +++ b/Utils/TaskSchedule/CronJob.php @@ -14,6 +14,8 @@ declare(strict_types=1); namespace phpOMS\Utils\TaskSchedule; +use phpOMS\Validation\Base\DateTime; + /** * CronJob class. * @@ -29,10 +31,22 @@ class CronJob extends TaskAbstract */ public static function createWith(array $jobData) : TaskAbstract { - $job = new self($jobData[5], ''); + $job = new self($jobData[1], ''); - $job->setRun($jobData[5]); + $job->setRun($jobData[8]); + $job->setStatus($jobData[3]); - return $job; + if (DateTime::isValid($jobData[2])) { + $job->setNextRunTime(new \DateTime($jobData[2])); + } + + if (DateTime::isValid($jobData[5])) { + $job->setLastRuntime(new \DateTime($jobData[5])); + } + + $job->setComment($jobData[10]); + $job->addResult($jobData[6]); + + return $job; } } diff --git a/Utils/TaskSchedule/Schedule.php b/Utils/TaskSchedule/Schedule.php index ba465a1a8..f4f18e959 100644 --- a/Utils/TaskSchedule/Schedule.php +++ b/Utils/TaskSchedule/Schedule.php @@ -31,22 +31,22 @@ class Schedule extends TaskAbstract */ public static function createWith(array $jobData) : TaskAbstract { - $job = new self($jobData[1], ''); + $job = new self($jobData[1], ''); - $job->setRun($jobData[8]); - $job->setStatus($jobData[3]); + $job->setRun($jobData[8]); + $job->setStatus($jobData[3]); - if (DateTime::isValid($jobData[2])) { - $job->setNextRunTime(new \DateTime($jobData[2])); - } + if (DateTime::isValid($jobData[2])) { + $job->setNextRunTime(new \DateTime($jobData[2])); + } - if (DateTime::isValid($jobData[5])) { - $job->setLastRuntime(new \DateTime($jobData[5])); - } + if (DateTime::isValid($jobData[5])) { + $job->setLastRuntime(new \DateTime($jobData[5])); + } - $job->setComment($jobData[10]); - $job->addResult($jobData[6]); + $job->setComment($jobData[10]); + $job->addResult($jobData[6]); - return $job; + return $job; } } diff --git a/Utils/TaskSchedule/SchedulerAbstract.php b/Utils/TaskSchedule/SchedulerAbstract.php index 489ae85aa..5b8a00126 100644 --- a/Utils/TaskSchedule/SchedulerAbstract.php +++ b/Utils/TaskSchedule/SchedulerAbstract.php @@ -182,6 +182,20 @@ abstract class SchedulerAbstract $this->run($task->getCommand()); } + /** + * Normalize run result for easier parsing + * + * @param string $raw Raw command output + * + * @return string Normalized string for parsing + * + * @since 1.0.0 + */ + protected function normalize(string $raw) : string + { + return \str_replace("\r\n", "\n", $raw); + } + /** * Get all jobs/tasks by name * diff --git a/Utils/TaskSchedule/TaskScheduler.php b/Utils/TaskSchedule/TaskScheduler.php index bc0544237..a57ffc8ae 100644 --- a/Utils/TaskSchedule/TaskScheduler.php +++ b/Utils/TaskSchedule/TaskScheduler.php @@ -25,20 +25,6 @@ namespace phpOMS\Utils\TaskSchedule; */ class TaskScheduler extends SchedulerAbstract { - /** - * Normalize run result for easier parsing - * - * @param string $raw Raw command output - * - * @return string Normalized string for parsing - * - * @since 1.0.0 - */ - private function normalize(string $raw) : string - { - return \str_replace("\r\n", "\n", $raw); - } - /** * {@inheritdoc} */ From e61c1fb5dd28ae94dfc5f541152f8d7cd78cf2b0 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 2 Aug 2018 18:30:24 +0200 Subject: [PATCH 070/136] fixes #26 --- Utils/TaskSchedule/CronJob.php | 14 -------------- Utils/TaskSchedule/Schedule.php | 1 - 2 files changed, 15 deletions(-) diff --git a/Utils/TaskSchedule/CronJob.php b/Utils/TaskSchedule/CronJob.php index 654eff21e..821e2e14e 100644 --- a/Utils/TaskSchedule/CronJob.php +++ b/Utils/TaskSchedule/CronJob.php @@ -33,20 +33,6 @@ class CronJob extends TaskAbstract { $job = new self($jobData[1], ''); - $job->setRun($jobData[8]); - $job->setStatus($jobData[3]); - - if (DateTime::isValid($jobData[2])) { - $job->setNextRunTime(new \DateTime($jobData[2])); - } - - if (DateTime::isValid($jobData[5])) { - $job->setLastRuntime(new \DateTime($jobData[5])); - } - - $job->setComment($jobData[10]); - $job->addResult($jobData[6]); - return $job; } } diff --git a/Utils/TaskSchedule/Schedule.php b/Utils/TaskSchedule/Schedule.php index f4f18e959..380afd9cd 100644 --- a/Utils/TaskSchedule/Schedule.php +++ b/Utils/TaskSchedule/Schedule.php @@ -45,7 +45,6 @@ class Schedule extends TaskAbstract } $job->setComment($jobData[10]); - $job->addResult($jobData[6]); return $job; } From ed3fc48e346702c7fe1f4978799a7485ed93452a Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 2 Aug 2018 18:45:36 +0200 Subject: [PATCH 071/136] fixes #26 --- Utils/TaskSchedule/SchedulerAbstract.php | 22 ++++++++++++++++++++++ tests/Utils/TaskSchedule/CronTest.php | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/Utils/TaskSchedule/SchedulerAbstract.php b/Utils/TaskSchedule/SchedulerAbstract.php index 5b8a00126..2237e10ec 100644 --- a/Utils/TaskSchedule/SchedulerAbstract.php +++ b/Utils/TaskSchedule/SchedulerAbstract.php @@ -182,6 +182,28 @@ abstract class SchedulerAbstract $this->run($task->getCommand()); } + /** + * Update task + * + * @param TaskAbstract $task Task to update + * + * @return void + * + * @since 1.0.0 + */ + abstract public function update(TaskAbstract $task) : void; + + /** + * Delete task + * + * @param TaskAbstract $task Task to delete + * + * @return void + * + * @since 1.0.0 + */ + abstract public function delete(TaskAbstract $task) : void; + /** * Normalize run result for easier parsing * diff --git a/tests/Utils/TaskSchedule/CronTest.php b/tests/Utils/TaskSchedule/CronTest.php index d828b97ad..ee7035a95 100644 --- a/tests/Utils/TaskSchedule/CronTest.php +++ b/tests/Utils/TaskSchedule/CronTest.php @@ -14,6 +14,7 @@ namespace phpOMS\tests\Utils\TaskSchedule; use phpOMS\Utils\TaskSchedule\Cron; +use phpOMS\Utils\TaskSchedule\CronJob; class CronTest extends \PHPUnit\Framework\TestCase { @@ -21,4 +22,26 @@ class CronTest extends \PHPUnit\Framework\TestCase { self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\SchedulerAbstract', new Cron()); } + + public function testCRUD() + { + $cron = new Cron(); + + self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + + $cron->create( + new CronJob('testCronJob', 'testFile') + ); + self::assertEquals('testFile', $cron->getRun()); + + $cron->update( + new CronJob('testCronJob', 'testFile2') + ); + self::assertEquals('testFile2', $cron->getRun()); + + $cron->delete( + new CronJob('testCronJob', 'testFile2') + ); + self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + } } From a33a7be9549444b213cd118f574769d91501928e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 2 Aug 2018 19:18:34 +0200 Subject: [PATCH 072/136] fixes #26 --- Utils/TaskSchedule/Cron.php | 68 +++++++++++++++++++ Utils/TaskSchedule/CronJob.php | 8 +++ Utils/TaskSchedule/Schedule.php | 8 +++ Utils/TaskSchedule/SchedulerAbstract.php | 5 +- Utils/TaskSchedule/TaskAbstract.php | 9 +++ Utils/TaskSchedule/TaskScheduler.php | 24 +++++++ tests/Utils/TaskSchedule/CronTest.php | 32 +++++---- .../Utils/TaskSchedule/TaskSchedulerTest.php | 24 +++++++ 8 files changed, 159 insertions(+), 19 deletions(-) diff --git a/Utils/TaskSchedule/Cron.php b/Utils/TaskSchedule/Cron.php index 082888d67..424166596 100644 --- a/Utils/TaskSchedule/Cron.php +++ b/Utils/TaskSchedule/Cron.php @@ -25,6 +25,74 @@ namespace phpOMS\Utils\TaskSchedule; */ class Cron extends SchedulerAbstract { + /** + * {@inheritdoc} + */ + public function create(TaskAbstract $task) : void + { + $this->run('-l > tmpcron'); + \file_put_contents('tmpcron', "\n" . $task->__toString(), FILE_APPEND); + $this->run('tmpcron'); + } + + /** + * {@inheritdoc} + */ + public function update(TaskAbstract $task) : void + { + $this->run('-l > tmpcron'); + + $new = ''; + $fp = \fopen('tmpcron', 'r+'); + + if ($fp) { + $line = \fgets($fp); + while ($line !== false) { + if ($line[0] !== '#' && \stripos($line, '/tn = ' . $task->getId()) !== false) { + $new .= $task->__toString(); + } else { + $new .= $line . "\n"; + } + + $line = \fgets($fp); + } + + \fwrite($fp, $new); + \fclose($fp); + } + + $this->run('tmpcron'); + } + + /** + * {@inheritdoc} + */ + public function delete(TaskAbstract $task) : void + { + $this->run('-l > tmpcron'); + + $new = ''; + $fp = \fopen('tmpcron', 'r+'); + + if ($fp) { + $line = \fgets($fp); + while ($line !== false) { + if ($line[0] !== '#' && \stripos($line, '/tn = ' . $task->getId()) !== false) { + $line = \fgets($fp); + continue; + } + + $new .= $line . "\n"; + $line = \fgets($fp); + } + + \fwrite($fp, $new); + \fclose($fp); + } + + $this->run('tmpcron'); + } + /** * {@inheritdoc} */ diff --git a/Utils/TaskSchedule/CronJob.php b/Utils/TaskSchedule/CronJob.php index 821e2e14e..8a825b058 100644 --- a/Utils/TaskSchedule/CronJob.php +++ b/Utils/TaskSchedule/CronJob.php @@ -26,6 +26,14 @@ use phpOMS\Validation\Base\DateTime; */ class CronJob extends TaskAbstract { + /** + * {@inheritdoc} + */ + public function __toString() : string + { + return ''; + } + /** * {@inheritdoc} */ diff --git a/Utils/TaskSchedule/Schedule.php b/Utils/TaskSchedule/Schedule.php index 380afd9cd..c98469305 100644 --- a/Utils/TaskSchedule/Schedule.php +++ b/Utils/TaskSchedule/Schedule.php @@ -26,6 +26,14 @@ use phpOMS\Validation\Base\DateTime; */ class Schedule extends TaskAbstract { + /** + * {@inheritdoc} + */ + public function __toString() : string + { + return ''; + } + /** * {@inheritdoc} */ diff --git a/Utils/TaskSchedule/SchedulerAbstract.php b/Utils/TaskSchedule/SchedulerAbstract.php index 2237e10ec..4873fd18e 100644 --- a/Utils/TaskSchedule/SchedulerAbstract.php +++ b/Utils/TaskSchedule/SchedulerAbstract.php @@ -177,10 +177,7 @@ abstract class SchedulerAbstract * * @since 1.0.0 */ - public function create(TaskAbstract $task) : void - { - $this->run($task->getCommand()); - } + abstract public function create(TaskAbstract $task) : void; /** * Update task diff --git a/Utils/TaskSchedule/TaskAbstract.php b/Utils/TaskSchedule/TaskAbstract.php index 76df199b4..b809b4878 100644 --- a/Utils/TaskSchedule/TaskAbstract.php +++ b/Utils/TaskSchedule/TaskAbstract.php @@ -111,6 +111,15 @@ abstract class TaskAbstract return $this->id; } + /** + * Stringify task for direct handling + * + * @return string + * + * @since 1.0.0 + */ + abstract public function __toString() : string; + /** * Get command to create the task * diff --git a/Utils/TaskSchedule/TaskScheduler.php b/Utils/TaskSchedule/TaskScheduler.php index a57ffc8ae..4248d738a 100644 --- a/Utils/TaskSchedule/TaskScheduler.php +++ b/Utils/TaskSchedule/TaskScheduler.php @@ -25,6 +25,30 @@ namespace phpOMS\Utils\TaskSchedule; */ class TaskScheduler extends SchedulerAbstract { + /** + * {@inheritdoc} + */ + public function create(TaskAbstract $task) : void + { + $this->run('/Create ' . $task->__toString()); + } + + /** + * {@inheritdoc} + */ + public function update(TaskAbstract $task) : void + { + $this->run('/Change ' . $task->__toString()); + } + + /** + * {@inheritdoc} + */ + public function delete(TaskAbstract $task) : void + { + $this->run('/Delete /TN ' . $task->getId()); + } + /** * {@inheritdoc} */ diff --git a/tests/Utils/TaskSchedule/CronTest.php b/tests/Utils/TaskSchedule/CronTest.php index ee7035a95..7e2dc5c1c 100644 --- a/tests/Utils/TaskSchedule/CronTest.php +++ b/tests/Utils/TaskSchedule/CronTest.php @@ -25,23 +25,25 @@ class CronTest extends \PHPUnit\Framework\TestCase public function testCRUD() { - $cron = new Cron(); + if (\stristr(PHP_OS, 'LINUX')) { + $cron = new Cron(); - self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); - - $cron->create( - new CronJob('testCronJob', 'testFile') - ); - self::assertEquals('testFile', $cron->getRun()); + self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + + $cron->create( + new CronJob('testCronJob', 'testFile') + ); + self::assertEquals('testFile', $cron->getRun()); - $cron->update( - new CronJob('testCronJob', 'testFile2') - ); - self::assertEquals('testFile2', $cron->getRun()); + $cron->update( + new CronJob('testCronJob', 'testFile2') + ); + self::assertEquals('testFile2', $cron->getRun()); - $cron->delete( - new CronJob('testCronJob', 'testFile2') - ); - self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + $cron->delete( + new CronJob('testCronJob', 'testFile2') + ); + self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + } } } diff --git a/tests/Utils/TaskSchedule/TaskSchedulerTest.php b/tests/Utils/TaskSchedule/TaskSchedulerTest.php index 187ff86a0..6de0a9c16 100644 --- a/tests/Utils/TaskSchedule/TaskSchedulerTest.php +++ b/tests/Utils/TaskSchedule/TaskSchedulerTest.php @@ -21,4 +21,28 @@ class TaskSchedulerTest extends \PHPUnit\Framework\TestCase { self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\SchedulerAbstract', new TaskScheduler()); } + + public function testCRUD() + { + if (\stristr(PHP_OS, 'WIN')) { + $cron = new Cron(); + + self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + + $cron->create( + new CronJob('testCronJob', 'testFile') + ); + self::assertEquals('testFile', $cron->getRun()); + + $cron->update( + new CronJob('testCronJob', 'testFile2') + ); + self::assertEquals('testFile2', $cron->getRun()); + + $cron->delete( + new CronJob('testCronJob', 'testFile2') + ); + self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + } + } } From d7337e9e1b48a27965623b7764a4df057978bd1e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 13:20:57 +0200 Subject: [PATCH 073/136] Fix schedule/cron implementation --- Utils/TaskSchedule/Cron.php | 97 ++++++++++++------- Utils/TaskSchedule/CronJob.php | 5 +- Utils/TaskSchedule/NullCronJob.php | 27 ++++++ Utils/TaskSchedule/NullSchedule.php | 27 ++++++ Utils/TaskSchedule/Schedule.php | 3 +- Utils/TaskSchedule/SchedulerAbstract.php | 13 +++ Utils/TaskSchedule/TaskAbstract.php | 21 ++-- Utils/TaskSchedule/TaskScheduler.php | 10 +- tests/Utils/TaskSchedule/CronTest.php | 31 +++--- .../TaskSchedule/SchedulerAbstractTest.php | 2 +- tests/Utils/TaskSchedule/TaskAbstractTest.php | 9 +- .../Utils/TaskSchedule/TaskSchedulerTest.php | 34 ++++--- 12 files changed, 197 insertions(+), 82 deletions(-) create mode 100644 Utils/TaskSchedule/NullCronJob.php create mode 100644 Utils/TaskSchedule/NullSchedule.php diff --git a/Utils/TaskSchedule/Cron.php b/Utils/TaskSchedule/Cron.php index 424166596..7b6d2ca56 100644 --- a/Utils/TaskSchedule/Cron.php +++ b/Utils/TaskSchedule/Cron.php @@ -30,9 +30,10 @@ class Cron extends SchedulerAbstract */ public function create(TaskAbstract $task) : void { - $this->run('-l > tmpcron'); - \file_put_contents('tmpcron', "\n" . $task->__toString(), FILE_APPEND); - $this->run('tmpcron'); + $this->run('-l > ' . __DIR__ . '/tmpcron.tmp'); + \file_put_contents(__DIR__ . '/tmpcron.tmp', $task->__toString() . "\n", FILE_APPEND); + $this->run(__DIR__ . '/tmpcron.tmp'); + unlink(__DIR__ . '/tmpcron.tmp'); } /** @@ -40,16 +41,16 @@ class Cron extends SchedulerAbstract */ public function update(TaskAbstract $task) : void { - $this->run('-l > tmpcron'); + $this->run('-l > ' . __DIR__ . '/tmpcron.tmp'); $new = ''; - $fp = \fopen('tmpcron', 'r+'); + $fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+'); if ($fp) { $line = \fgets($fp); while ($line !== false) { - if ($line[0] !== '#' && \stripos($line, '/tn = ' . $task->getId()) !== false) { - $new .= $task->__toString(); + if ($line[0] !== '#' && \stripos($line, 'name="' . $task->getId()) !== false) { + $new .= $task->__toString() . "\n"; } else { $new .= $line . "\n"; } @@ -57,11 +58,12 @@ class Cron extends SchedulerAbstract $line = \fgets($fp); } - \fwrite($fp, $new); \fclose($fp); + \file_put_contents(__DIR__ . '/tmpcron.tmp', $new); } - $this->run('tmpcron'); + $this->run(__DIR__ . '/tmpcron.tmp'); + unlink(__DIR__ . '/tmpcron.tmp'); } /** @@ -69,15 +71,23 @@ class Cron extends SchedulerAbstract */ public function delete(TaskAbstract $task) : void { - $this->run('-l > tmpcron'); + $this->deleteByName($task->getId()); + } + + /** + * {@inheritdoc} + */ + public function deleteByName(string $name) : void + { + $this->run('-l > ' . __DIR__ . '/tmpcron.tmp'); $new = ''; - $fp = \fopen('tmpcron', 'r+'); + $fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+'); if ($fp) { $line = \fgets($fp); while ($line !== false) { - if ($line[0] !== '#' && \stripos($line, '/tn = ' . $task->getId()) !== false) { + if ($line[0] !== '#' && \stripos($line, 'name="' . $name) !== false) { $line = \fgets($fp); continue; } @@ -86,11 +96,12 @@ class Cron extends SchedulerAbstract $line = \fgets($fp); } - \fwrite($fp, $new); \fclose($fp); + \file_put_contents(__DIR__ . '/tmpcron.tmp', $new); } - $this->run('tmpcron'); + $this->run(__DIR__ . '/tmpcron.tmp'); + unlink(__DIR__ . '/tmpcron.tmp'); } /** @@ -98,16 +109,31 @@ class Cron extends SchedulerAbstract */ public function getAll() : array { - $lines = \explode("\n", $this->normalize($this->run('-l'))); - unset($lines[0]); + $this->run('-l > ' . __DIR__ . '/tmpcron.tmp'); $jobs = []; - foreach ($lines as $line) { - if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false) { - $jobs[] = CronJob::createWith(\str_getcsv($line, ' ')); + $fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+'); + + if ($fp) { + $line = \fgets($fp); + while ($line !== false) { + if ($line[0] !== '#') { + $elements = []; + $namePos = \stripos($line, 'name="'); + $elements[] = \substr($line, $namePos + 6, \stripos($line, '"', $namePos + 7) - 1); + $elements += \explode(' ', $line); + $jobs[] = CronJob::createWith($elements); + } + + $line = \fgets($fp); } + + \fclose($fp); } + $this->run(__DIR__ . '/tmpcron.tmp'); + unlink(__DIR__ . '/tmpcron.tmp'); + return $jobs; } @@ -116,29 +142,30 @@ class Cron extends SchedulerAbstract */ public function getAllByName(string $name, bool $exact = true) : array { - $lines = \explode("\n", $this->normalize($this->run('-l'))); - unset($lines[0]); + $this->run('-l > ' . __DIR__ . '/tmpcron.tmp'); - if ($exact) { - $jobs = []; - foreach ($lines as $line) { - $csv = \str_getcsv($line, ' '); + $jobs = []; + $fp = \fopen(__DIR__ . '/tmpcron.tmp', 'r+'); - if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false && $csv[5] === $name) { - $jobs[] = CronJob::createWith($csv); + if ($fp) { + $line = \fgets($fp); + while ($line !== false) { + if ($line[0] !== '#' && \stripos($line, '# name="' . $name) !== false) { + $elements = []; + $elements[] = $name; + $elements += \explode(' ', $line); + $jobs[] = CronJob::createWith($elements); } - } - } else { - $jobs = []; - foreach ($lines as $line) { - $csv = \str_getcsv($line, ' '); - if ($line !== '' && \strrpos($line, '#', -\strlen($line)) === false && \stripos($csv[5], $name) !== false) { - $jobs[] = CronJob::createWith($csv); - } + $line = \fgets($fp); } + + \fclose($fp); } + $this->run(__DIR__ . '/tmpcron.tmp'); + unlink(__DIR__ . '/tmpcron.tmp'); + return $jobs; } } diff --git a/Utils/TaskSchedule/CronJob.php b/Utils/TaskSchedule/CronJob.php index 8a825b058..be874ef24 100644 --- a/Utils/TaskSchedule/CronJob.php +++ b/Utils/TaskSchedule/CronJob.php @@ -31,7 +31,7 @@ class CronJob extends TaskAbstract */ public function __toString() : string { - return ''; + return $this->interval . ' ' . $this->command . ' # name="' . $this->id . '" ' . $this->comment; } /** @@ -39,7 +39,8 @@ class CronJob extends TaskAbstract */ public static function createWith(array $jobData) : TaskAbstract { - $job = new self($jobData[1], ''); + $interval = \array_splice($jobData, 1, 4); + $job = new self($jobData[0], $jobData[1], \implode(' ', $interval)); return $job; } diff --git a/Utils/TaskSchedule/NullCronJob.php b/Utils/TaskSchedule/NullCronJob.php new file mode 100644 index 000000000..03928ac29 --- /dev/null +++ b/Utils/TaskSchedule/NullCronJob.php @@ -0,0 +1,27 @@ +setRun($jobData[8]); $job->setStatus($jobData[3]); if (DateTime::isValid($jobData[2])) { diff --git a/Utils/TaskSchedule/SchedulerAbstract.php b/Utils/TaskSchedule/SchedulerAbstract.php index 4873fd18e..86bd2b094 100644 --- a/Utils/TaskSchedule/SchedulerAbstract.php +++ b/Utils/TaskSchedule/SchedulerAbstract.php @@ -83,6 +83,8 @@ abstract class SchedulerAbstract 'e:/WINDOWS/system32/schtasks.exe', 'f:/WINDOWS/system32/schtasks.exe', '/usr/bin/crontab', + '/usr/local/bin/crontab', + '/usr/local/sbin/crontab', '/usr/sbin/crontab', '/bin/crontab', '/sbin/crontab', @@ -190,6 +192,17 @@ abstract class SchedulerAbstract */ abstract public function update(TaskAbstract $task) : void; + /** + * Delete task by name + * + * @param string $name Task name + * + * @return void + * + * @since 1.0.0 + */ + abstract public function deleteByName(string $name) : void; + /** * Delete task * diff --git a/Utils/TaskSchedule/TaskAbstract.php b/Utils/TaskSchedule/TaskAbstract.php index b809b4878..ca8607a93 100644 --- a/Utils/TaskSchedule/TaskAbstract.php +++ b/Utils/TaskSchedule/TaskAbstract.php @@ -41,12 +41,12 @@ abstract class TaskAbstract protected $command = ''; /** - * Command/script to run. + * Run interval * * @var string * @since 1.0.0 */ - protected $run = ''; + protected $interval = ''; /** * Status of the task @@ -91,10 +91,11 @@ abstract class TaskAbstract * * @since 1.0.0 */ - public function __construct(string $name, string $cmd = '') + public function __construct(string $name, string $cmd = '', string $interval = '') { $this->id = $name; $this->command = $cmd; + $this->interval = $interval; $this->lastRunTime = new \DateTime('1900-01-01'); $this->nextRunTime = new \DateTime('1900-01-01'); } @@ -147,29 +148,29 @@ abstract class TaskAbstract } /** - * Get command/script to run + * Get interval to create the task * * @return string * * @since 1.0.0 */ - public function getRun() : string + public function getInterval() : string { - return $this->run; + return $this->interval; } /** - * Set script to run + * Set interval to create the task * - * @param string $run Command/script to run + * @param string $interval Interval * * @return void * * @since 1.0.0 */ - public function setRun(string $run) : void + public function setInterval(string $interval) : void { - $this->run = $run; + $this->interval = $interval; } /** diff --git a/Utils/TaskSchedule/TaskScheduler.php b/Utils/TaskSchedule/TaskScheduler.php index 4248d738a..3f88a392e 100644 --- a/Utils/TaskSchedule/TaskScheduler.php +++ b/Utils/TaskSchedule/TaskScheduler.php @@ -41,12 +41,20 @@ class TaskScheduler extends SchedulerAbstract $this->run('/Change ' . $task->__toString()); } + /** + * {@inheritdoc} + */ + public function deleteByName(string $name) : void + { + $this->run('/Delete /TN ' . $name); + } + /** * {@inheritdoc} */ public function delete(TaskAbstract $task) : void { - $this->run('/Delete /TN ' . $task->getId()); + $this->deleteByName($task->getId()); } /** diff --git a/tests/Utils/TaskSchedule/CronTest.php b/tests/Utils/TaskSchedule/CronTest.php index 7e2dc5c1c..8cf1b8078 100644 --- a/tests/Utils/TaskSchedule/CronTest.php +++ b/tests/Utils/TaskSchedule/CronTest.php @@ -26,24 +26,29 @@ class CronTest extends \PHPUnit\Framework\TestCase public function testCRUD() { if (\stristr(PHP_OS, 'LINUX')) { + Cron::guessBin(); $cron = new Cron(); - self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + self::assertEquals([], $cron->getAllByName('testCronJob', false)); - $cron->create( - new CronJob('testCronJob', 'testFile') - ); - self::assertEquals('testFile', $cron->getRun()); + $job = new CronJob('testCronJob', 'testFile', '0 0 1 1 *'); + $cron->create($job); + + self::assertTrue(!empty($cron->getAllByName('testCronJob', false))); + if (!empty($cron->getAllByName('testCronJob', false))) { + self::assertEquals('testFile', $cron->getAllByName('testCronJob', false)[0]->getCommand()); + } - $cron->update( - new CronJob('testCronJob', 'testFile2') - ); - self::assertEquals('testFile2', $cron->getRun()); + $job->setCommand('testFile2'); + $cron->update($job); - $cron->delete( - new CronJob('testCronJob', 'testFile2') - ); - self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + self::assertTrue(!empty($cron->getAllByName('testCronJob', false))); + if (!empty($cron->getAllByName('testCronJob', false))) { + self::assertEquals('testFile2', $cron->getAllByName('testCronJob', false)[0]->getCommand()); + } + + $cron->delete($job); + self::assertEquals([], $cron->getAllByName('testCronJob', false)); } } } diff --git a/tests/Utils/TaskSchedule/SchedulerAbstractTest.php b/tests/Utils/TaskSchedule/SchedulerAbstractTest.php index 0462f84cf..f3cacd58a 100644 --- a/tests/Utils/TaskSchedule/SchedulerAbstractTest.php +++ b/tests/Utils/TaskSchedule/SchedulerAbstractTest.php @@ -19,6 +19,6 @@ class SchedulerAbstractTest extends \PHPUnit\Framework\TestCase { public function testDefault() { - self::assertEquals('', SchedulerAbstract::getBin()); + self::assertTrue(SchedulerAbstract::getBin() === '' || \file_exists(SchedulerAbstract::getBin() )); } } diff --git a/tests/Utils/TaskSchedule/TaskAbstractTest.php b/tests/Utils/TaskSchedule/TaskAbstractTest.php index 41f4ebcd2..12fae0da4 100644 --- a/tests/Utils/TaskSchedule/TaskAbstractTest.php +++ b/tests/Utils/TaskSchedule/TaskAbstractTest.php @@ -22,6 +22,11 @@ class TaskAbstractTest extends \PHPUnit\Framework\TestCase protected function setUp() { $this->class = new class('') extends TaskAbstract { + public function __toString() : string + { + return ''; + } + public static function createWith(array $jobData) : TaskAbstract { @@ -33,7 +38,6 @@ class TaskAbstractTest extends \PHPUnit\Framework\TestCase { self::assertEquals('', $this->class->getId()); self::assertEquals('', $this->class->getCommand()); - self::assertEquals('', $this->class->getRun()); self::assertEquals('', $this->class->getStatus()); self::assertInstanceOf('\DateTime', $this->class->getNextRunTime()); self::assertInstanceOf('\DateTime', $this->class->getLastRuntime()); @@ -45,9 +49,6 @@ class TaskAbstractTest extends \PHPUnit\Framework\TestCase $this->class->setCommand('Command'); self::assertEquals('Command', $this->class->getCommand()); - $this->class->setRun('Run'); - self::assertEquals('Run', $this->class->getRun()); - $this->class->setStatus('Status'); self::assertEquals('Status', $this->class->getStatus()); diff --git a/tests/Utils/TaskSchedule/TaskSchedulerTest.php b/tests/Utils/TaskSchedule/TaskSchedulerTest.php index 6de0a9c16..b6bf0cb87 100644 --- a/tests/Utils/TaskSchedule/TaskSchedulerTest.php +++ b/tests/Utils/TaskSchedule/TaskSchedulerTest.php @@ -14,6 +14,7 @@ namespace phpOMS\tests\Utils\TaskSchedule; use phpOMS\Utils\TaskSchedule\TaskScheduler; +use phpOMS\Utils\TaskSchedule\Schedule; class TaskSchedulerTest extends \PHPUnit\Framework\TestCase { @@ -25,24 +26,29 @@ class TaskSchedulerTest extends \PHPUnit\Framework\TestCase public function testCRUD() { if (\stristr(PHP_OS, 'WIN')) { - $cron = new Cron(); + TaskScheduler::guessBin(); + $cron = new TaskScheduler(); - self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + self::assertEquals([], $cron->getAllByName('testCronJob', false)); - $cron->create( - new CronJob('testCronJob', 'testFile') - ); - self::assertEquals('testFile', $cron->getRun()); + $job = new Schedule('testCronJob', 'testFile', '0 0 1 1 *'); + $cron->create($job); + + self::assertTrue(!empty($cron->getAllByName('testCronJob', false))); + if (!empty($cron->getAllByName('testCronJob', false))) { + self::assertEquals('testFile', $cron->getAllByName('testCronJob', false)[0]->getCommand()); + } - $cron->update( - new CronJob('testCronJob', 'testFile2') - ); - self::assertEquals('testFile2', $cron->getRun()); + $job->setCommand('testFile2'); + $cron->update($job); - $cron->delete( - new CronJob('testCronJob', 'testFile2') - ); - self::assertInstanceOf('\phpOMS\Utils\TaskSchedule\NullCronJob', $cron->getAllByName('testCronJob', false)); + self::assertTrue(!empty($cron->getAllByName('testCronJob', false))); + if (!empty($cron->getAllByName('testCronJob', false))) { + self::assertEquals('testFile2', $cron->getAllByName('testCronJob', false)[0]->getCommand()); + } + + $cron->delete($job); + self::assertEquals([], $cron->getAllByName('testCronJob', false)); } } } From d4ed7b0e1994a64a8bb517318d25134a533cc32e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 13:43:59 +0200 Subject: [PATCH 074/136] Fix invalid stripos --- Utils/TaskSchedule/Cron.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/Utils/TaskSchedule/Cron.php b/Utils/TaskSchedule/Cron.php index 7b6d2ca56..1bc6035c5 100644 --- a/Utils/TaskSchedule/Cron.php +++ b/Utils/TaskSchedule/Cron.php @@ -120,9 +120,14 @@ class Cron extends SchedulerAbstract if ($line[0] !== '#') { $elements = []; $namePos = \stripos($line, 'name="'); - $elements[] = \substr($line, $namePos + 6, \stripos($line, '"', $namePos + 7) - 1); - $elements += \explode(' ', $line); - $jobs[] = CronJob::createWith($elements); + $nameEndPos = \stripos($line, '"', $namePos + 7); + + if ($namePos !== false && $nameEndPos !== false) { + $elements[] = \substr($line, $namePos + 6, $nameEndPos - 1); + } + + $elements = \array_merge($elements, \explode(' ', $line)); + $jobs[] = CronJob::createWith($elements); } $line = \fgets($fp); From 121fb836955335be9da4a4f0f36e37b7a29e8d55 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:04:01 +0200 Subject: [PATCH 075/136] Test travis build --- .travis.yml | 8 +++ composer.json | 9 +++- tests/Bootstrap.php | 93 ++++++++++++++++++++++++++++++++++- tests/phpunit_no_coverage.xml | 28 +++++++++++ 4 files changed, 135 insertions(+), 3 deletions(-) create mode 100644 .travis.yml create mode 100644 tests/phpunit_no_coverage.xml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 000000000..4445b8ead --- /dev/null +++ b/.travis.yml @@ -0,0 +1,8 @@ +language: php +php: + - '7.2' + - nightly +before_script: + - composer install +script: + - vendor/bin/phpunit --configuration tests/phpunit_no_coverage.xm \ No newline at end of file diff --git a/composer.json b/composer.json index 3190c2f28..b26c9d730 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,14 @@ } ], "require": { - "php": "^7.0" + "php": "^7.2" + }, + "require-dev": { + "phpunit/phpunit": "~6.4", + "squizlabs/php_codesniffer": "~3.2", + "phpmd/phpmd": "~2.6", + "phpstan/phpstan": "~0.10.1", + "phan/phan": "~0.12.0" }, "repositories": [ { diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index 3b0892a21..e74461292 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -3,13 +3,102 @@ ini_set('memory_limit', '2048M'); require_once __DIR__ . '/../../vendor/autoload.php'; -require_once __DIR__ . '/Autoloader.php'; -$CONFIG = require_once __DIR__ . '/../../config.php'; +require_once __DIR__ . '/../Autoloader.php'; use phpOMS\DataStorage\Session\HttpSession; use phpOMS\DataStorage\Database\DatabasePool; use phpOMS\DataStorage\Database\DataMapperAbstract; +$CONFIG = [ + 'db' => [ + 'core' => [ + 'masters' => [ + 'admin' => [ + 'db' => 'mysql', /* db type */ + 'host' => '127.0.0.1', /* db host address */ + 'port' => '3306', /* db host port */ + 'login' => 'root', /* db login name */ + 'password' => '123456', /* db login password */ + 'database' => 'oms', /* db name */ + 'prefix' => 'oms_', /* db table prefix */ + 'weight' => 1000, /* db table prefix */ + ], + 'insert' => [ + 'db' => 'mysql', /* db type */ + 'host' => '127.0.0.1', /* db host address */ + 'port' => '3306', /* db host port */ + 'login' => 'root', /* db login name */ + 'password' => '123456', /* db login password */ + 'database' => 'oms', /* db name */ + 'prefix' => 'oms_', /* db table prefix */ + 'weight' => 1000, /* db table prefix */ + ], + 'select' => [ + 'db' => 'mysql', /* db type */ + 'host' => '127.0.0.1', /* db host address */ + 'port' => '3306', /* db host port */ + 'login' => 'root', /* db login name */ + 'password' => '123456', /* db login password */ + 'database' => 'oms', /* db name */ + 'prefix' => 'oms_', /* db table prefix */ + 'weight' => 1000, /* db table prefix */ + ], + 'update' => [ + 'db' => 'mysql', /* db type */ + 'host' => '127.0.0.1', /* db host address */ + 'port' => '3306', /* db host port */ + 'login' => 'root', /* db login name */ + 'password' => '123456', /* db login password */ + 'database' => 'oms', /* db name */ + 'prefix' => 'oms_', /* db table prefix */ + 'weight' => 1000, /* db table prefix */ + ], + 'delete' => [ + 'db' => 'mysql', /* db type */ + 'host' => '127.0.0.1', /* db host address */ + 'port' => '3306', /* db host port */ + 'login' => 'root', /* db login name */ + 'password' => '123456', /* db login password */ + 'database' => 'oms', /* db name */ + 'prefix' => 'oms_', /* db table prefix */ + 'weight' => 1000, /* db table prefix */ + ], + 'schema' => [ + 'db' => 'mysql', /* db type */ + 'host' => '127.0.0.1', /* db host address */ + 'port' => '3306', /* db host port */ + 'login' => 'root', /* db login name */ + 'password' => '123456', /* db login password */ + 'database' => 'oms', /* db name */ + 'prefix' => 'oms_', /* db table prefix */ + 'weight' => 1000, /* db table prefix */ + ], + ], + ], + ], + 'log' => [ + 'file' => [ + 'path' => __DIR__ . '/Logs', + ], + ], + 'page' => [ + 'root' => '/', + 'https' => false, + ], + 'socket' => [ + 'master' => [ + 'host' => '127.0.0.1', + 'limit' => 300, + 'port' => 4310, + ], + ], + 'language' => [ + 'en', + ], + 'apis' => [ + ] +]; + // Reset database $db = new \PDO($CONFIG['db']['core']['masters']['admin']['db'] . ':host=' . $CONFIG['db']['core']['masters']['admin']['host'], diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml new file mode 100644 index 000000000..743d2f4dd --- /dev/null +++ b/tests/phpunit_no_coverage.xml @@ -0,0 +1,28 @@ + + + + + ../* + Module/ModuleManagerTest.php + + + + + ../* + + ../* + ../* + ../* + ../Build/* + + + + From 3e9d5f410861f21e2825a0b60f3f469b69c98922 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:09:38 +0200 Subject: [PATCH 076/136] install ast --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 4445b8ead..cfdabbf67 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,6 +3,7 @@ php: - '7.2' - nightly before_script: + - pecl install ast - composer install script: - vendor/bin/phpunit --configuration tests/phpunit_no_coverage.xm \ No newline at end of file From e45895b8502e40967be3ef96568b3fcc90c5a27d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:12:57 +0200 Subject: [PATCH 077/136] Fix composer structure --- composer.json | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/composer.json b/composer.json index b26c9d730..386679a72 100644 --- a/composer.json +++ b/composer.json @@ -7,25 +7,11 @@ "email": "spl1nes.com@googlemail.com" } ], - "require": { - "php": "^7.2" - }, "require-dev": { "phpunit/phpunit": "~6.4", "squizlabs/php_codesniffer": "~3.2", "phpmd/phpmd": "~2.6", "phpstan/phpstan": "~0.10.1", "phan/phan": "~0.12.0" - }, - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/Orange-Management/phpOMS.git" - } - ], - "autoload": { - "psr-0" : { - "phpOMS" : "" - } } } \ No newline at end of file From a8e32cadfffcce4b0f3f2278090ce34523f66375 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:25:42 +0200 Subject: [PATCH 078/136] Fix config path --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index cfdabbf67..4497cd0a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,4 +6,4 @@ before_script: - pecl install ast - composer install script: - - vendor/bin/phpunit --configuration tests/phpunit_no_coverage.xm \ No newline at end of file + - vendor/bin/phpunit --configuration tests/phpunit_no_coverage.xml \ No newline at end of file From 16bddd7866dc80c2a298bc0081cbcdd12d226be1 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:32:21 +0200 Subject: [PATCH 079/136] Fix vendor path --- tests/Bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index e74461292..93566f30a 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -2,7 +2,7 @@ ini_set('memory_limit', '2048M'); -require_once __DIR__ . '/../../vendor/autoload.php'; +require_once __DIR__ . 'vendor/autoload.php'; require_once __DIR__ . '/../Autoloader.php'; use phpOMS\DataStorage\Session\HttpSession; From cbac4401417264c3a63bb38fa7018de1fcf6da5e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:34:49 +0200 Subject: [PATCH 080/136] Fix vendor path --- tests/Bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index 93566f30a..f119c9435 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -2,7 +2,7 @@ ini_set('memory_limit', '2048M'); -require_once __DIR__ . 'vendor/autoload.php'; +require_once 'vendor/autoload.php'; require_once __DIR__ . '/../Autoloader.php'; use phpOMS\DataStorage\Session\HttpSession; From 3dbd88770241260b4fd148dbf70de68d91b14e0a Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:39:39 +0200 Subject: [PATCH 081/136] Fix mysql database --- .travis.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4497cd0a0..560f9eecc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,10 @@ language: php php: - '7.2' - nightly +services: + - mysql before_script: + - sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" - pecl install ast - composer install script: From c44b9f09496c89d4de3088e9e570ee0033d9260c Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:48:32 +0200 Subject: [PATCH 082/136] Use sudo --- .travis.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 560f9eecc..0ff8b1b33 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,19 @@ language: php +sudo: required php: - '7.2' - nightly -services: - - mysql +addons: + apt: + sources: + - mysql-5.7-trusty + packages: + - mysql-server + - mysql-client before_script: - sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" + - sudo mysql_upgrade + - sudo service mysql restart - pecl install ast - composer install script: From 26b6a605ad3e80fbcc011aa2b24e37b02a60ea7f Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:51:15 +0200 Subject: [PATCH 083/136] Test sudo --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0ff8b1b33..f8f1d9f8e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,5 @@ language: php +dist: trusty sudo: required php: - '7.2' @@ -6,10 +7,10 @@ php: addons: apt: sources: - - mysql-5.7-trusty + - mysql-5.7-trusty packages: - - mysql-server - - mysql-client + - mysql-server + - mysql-client before_script: - sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" - sudo mysql_upgrade From 73192e179ac69092504dd527f48430e35ebf9e11 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:51:56 +0200 Subject: [PATCH 084/136] Remove sudo --- .travis.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index f8f1d9f8e..74c118c4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ language: php -dist: trusty -sudo: required php: - '7.2' - nightly @@ -12,9 +10,9 @@ addons: - mysql-server - mysql-client before_script: - - sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" - - sudo mysql_upgrade - - sudo service mysql restart + - mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" + - mysql_upgrade + - service mysql restart - pecl install ast - composer install script: From 4f968d442095b86b7c30da4d695a24429ab961ef Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:55:01 +0200 Subject: [PATCH 085/136] Test db variation --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 74c118c4d..1dc84473a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: php +dist: trusty +sudo: required php: - '7.2' - nightly From 1783ef3804126c9bb81bb6d0cad8097c827d4678 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:57:11 +0200 Subject: [PATCH 086/136] Use old db version --- .travis.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1dc84473a..feb1c3079 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,19 +1,11 @@ language: php -dist: trusty -sudo: required php: - '7.2' - nightly -addons: - apt: - sources: - - mysql-5.7-trusty - packages: - - mysql-server - - mysql-client +services: + - mysql before_script: - mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" - - mysql_upgrade - service mysql restart - pecl install ast - composer install From 06757d9a83e86e00787392ca8fc96dd70e626921 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 15:59:28 +0200 Subject: [PATCH 087/136] try sudo --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index feb1c3079..9c2e40d1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ services: - mysql before_script: - mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" - - service mysql restart + - sudo service mysql restart - pecl install ast - composer install script: From 9fa2d7067a04c8983c718e99917418692b6d138d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:00:13 +0200 Subject: [PATCH 088/136] Use sudo --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 9c2e40d1f..ae138b32a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,6 @@ language: php +dist: trusty +sudo: required php: - '7.2' - nightly From 886cc8b6bf32f633db74cdf0347a032c2c31dd36 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:01:29 +0200 Subject: [PATCH 089/136] Check without mysql restart --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index ae138b32a..5553a2dd8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ language: php -dist: trusty -sudo: required php: - '7.2' - nightly @@ -8,7 +6,6 @@ services: - mysql before_script: - mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" - - sudo service mysql restart - pecl install ast - composer install script: From 04076594459228d07256e7fce1e85673e9be7c05 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:05:44 +0200 Subject: [PATCH 090/136] use different password change --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 5553a2dd8..103fbeb6c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ php: services: - mysql before_script: - - mysql -e "use mysql; update user set authentication_string=PASSWORD('123456') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" + - echo "USE mysql;\nUPDATE user SET password=PASSWORD('password') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root" - pecl install ast - composer install script: From 5001003414e4096ccb92f9c24e4d4a690089bea1 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:07:38 +0200 Subject: [PATCH 091/136] Fix change password command --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 103fbeb6c..cd4023d96 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ php: services: - mysql before_script: - - echo "USE mysql;\nUPDATE user SET password=PASSWORD('password') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root" + - echo "USE mysql;\nUPDATE user SET password=PASSWORD('password') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root - pecl install ast - composer install script: From 5a7114458884b3680a65957f8a626c0b297bcb69 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:10:40 +0200 Subject: [PATCH 092/136] Try to restart mysql --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index cd4023d96..b1b0c7d90 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,6 +6,7 @@ services: - mysql before_script: - echo "USE mysql;\nUPDATE user SET password=PASSWORD('password') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root + - sudo service mysql restart - pecl install ast - composer install script: From 75c3ca9ffc798bbe71887e1e3abc3109b1fa0f82 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:16:10 +0200 Subject: [PATCH 093/136] Try to restart mysql --- .travis.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index b1b0c7d90..c617e2614 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,19 @@ language: php +sudo: true +dist: trusty php: - '7.2' - nightly -services: - - mysql +addons: + apt: + sources: + - mysql-5.7-trusty + packages: + - mysql-server + - mysql-client before_script: - - echo "USE mysql;\nUPDATE user SET password=PASSWORD('password') WHERE user='root';\nFLUSH PRIVILEGES;\n" | mysql -u root + - sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('new_password') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" + - sudo mysql_upgrade - sudo service mysql restart - pecl install ast - composer install From 7b799ee7d89506bfca623ddaa579249eab57ab60 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:19:57 +0200 Subject: [PATCH 094/136] Try to restart mysql --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c617e2614..615adeba2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php -sudo: true dist: trusty +sudo: required php: - '7.2' - nightly From 2f01932b4322a9b193b1eb253397d87bf3a904de Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:20:48 +0200 Subject: [PATCH 095/136] Use older mysql --- .travis.yml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 615adeba2..85b7e0878 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,13 +4,8 @@ sudo: required php: - '7.2' - nightly -addons: - apt: - sources: - - mysql-5.7-trusty - packages: - - mysql-server - - mysql-client +services: + - mysql before_script: - sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('new_password') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" - sudo mysql_upgrade From eb222ae98a9c0c313427ef87fc50493f7fa8d602 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:22:51 +0200 Subject: [PATCH 096/136] Remove container etc --- .travis.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 85b7e0878..2aabe27f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,4 @@ language: php -dist: trusty -sudo: required php: - '7.2' - nightly From 2ea3b16828c14af7b3b84a673ff350ef6f9344ce Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:24:51 +0200 Subject: [PATCH 097/136] Remove db password --- .travis.yml | 3 --- tests/Bootstrap.php | 12 ++++++------ 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2aabe27f1..d348a6a30 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,6 @@ php: services: - mysql before_script: - - sudo mysql -e "use mysql; update user set authentication_string=PASSWORD('new_password') where User='root'; update user set plugin='mysql_native_password';FLUSH PRIVILEGES;" - - sudo mysql_upgrade - - sudo service mysql restart - pecl install ast - composer install script: diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index f119c9435..348ecd78c 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -18,7 +18,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -28,7 +28,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -38,7 +38,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -48,7 +48,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -58,7 +58,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -68,7 +68,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ From fdb5c9818dc19ce7dc6cb37daafc5161a2c4522d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:28:33 +0200 Subject: [PATCH 098/136] Remove phan --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 386679a72..08dffc6fd 100644 --- a/composer.json +++ b/composer.json @@ -12,6 +12,5 @@ "squizlabs/php_codesniffer": "~3.2", "phpmd/phpmd": "~2.6", "phpstan/phpstan": "~0.10.1", - "phan/phan": "~0.12.0" } } \ No newline at end of file From f03399369d01c4bc2c5e54d471eea7cfbb839bb9 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:28:45 +0200 Subject: [PATCH 099/136] Remove phan --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 08dffc6fd..2dd5e5ba9 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,6 @@ "phpunit/phpunit": "~6.4", "squizlabs/php_codesniffer": "~3.2", "phpmd/phpmd": "~2.6", - "phpstan/phpstan": "~0.10.1", + "phpstan/phpstan": "~0.10.1" } } \ No newline at end of file From ca7d6f8b54c89744bbc427d50f3bdbe73f2aa47e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:38:40 +0200 Subject: [PATCH 100/136] Use default phpunit --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index d348a6a30..ef9705922 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,4 +8,4 @@ before_script: - pecl install ast - composer install script: - - vendor/bin/phpunit --configuration tests/phpunit_no_coverage.xml \ No newline at end of file + - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml \ No newline at end of file From aed9ec74a51addaa9a8e8692bc93b1b8d796dee1 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:43:49 +0200 Subject: [PATCH 101/136] Fix test files --- tests/Bootstrap.php | 3 ++- tests/phpunit_no_coverage.xml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index 348ecd78c..5b6876689 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -2,7 +2,8 @@ ini_set('memory_limit', '2048M'); -require_once 'vendor/autoload.php'; +include_once 'vendor/autoload.php'; +include_once '../../vendor/autoload.php'; require_once __DIR__ . '/../Autoloader.php'; use phpOMS\DataStorage\Session\HttpSession; diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index 743d2f4dd..e8f0f9508 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -10,13 +10,13 @@ > - ../* + .* Module/ModuleManagerTest.php - ../* + .* ../* ../* From e6be0fe09f4f0d1179de47623f99859cef943f4e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:49:06 +0200 Subject: [PATCH 102/136] Exclude vendor --- tests/phpunit_no_coverage.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index e8f0f9508..37c2279a7 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -18,6 +18,7 @@ .* + vendor/* ../* ../* ../* From e39ad5a2f9176c62a5d37c93ccc034cb26c30484 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:54:16 +0200 Subject: [PATCH 103/136] Exclude vendor --- tests/phpunit_no_coverage.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index 37c2279a7..a7a9d3174 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -12,13 +12,13 @@ .* Module/ModuleManagerTest.php + vendor* .* - vendor/* ../* ../* ../* From 55b2d30837d6fb7c103a5e13495fe55d59a08728 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 16:55:56 +0200 Subject: [PATCH 104/136] Exclude vendor --- tests/phpunit_no_coverage.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index a7a9d3174..bc6ea2cdd 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -12,7 +12,7 @@ .* Module/ModuleManagerTest.php - vendor* + vendor* From 165f74885063409411ae275108d6735d58207b2e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 18:54:42 +0200 Subject: [PATCH 105/136] fixes #25 --- Utils/TaskSchedule/Schedule.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Utils/TaskSchedule/Schedule.php b/Utils/TaskSchedule/Schedule.php index 88f7d2618..0c8f1fecc 100644 --- a/Utils/TaskSchedule/Schedule.php +++ b/Utils/TaskSchedule/Schedule.php @@ -31,9 +31,9 @@ class Schedule extends TaskAbstract */ public function __toString() : string { - return ''; + return '/tn ' . $this->id . ' ' . $this->interval . ' ' . $this->command; } - + /** * {@inheritdoc} */ From a4f8b114bbee9155a1c64becf452680b8732c652 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 20:22:33 +0200 Subject: [PATCH 106/136] Cleanup minor visual bugs --- tests/Bootstrap.php | 20 +++++++++++-------- tests/DataStorage/Session/HttpSessionTest.php | 1 - 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index 5b6876689..42437c99b 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -2,8 +2,12 @@ ini_set('memory_limit', '2048M'); -include_once 'vendor/autoload.php'; -include_once '../../vendor/autoload.php'; +if (file_exists('vendor/autoload.php')) { + include_once 'vendor/autoload.php'; +} elseif (file_exists('../../vendor/autoload.php')) { + include_once '../../vendor/autoload.php'; +} + require_once __DIR__ . '/../Autoloader.php'; use phpOMS\DataStorage\Session\HttpSession; @@ -19,7 +23,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '', /* db login password */ + 'password' => '123456', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -29,7 +33,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '', /* db login password */ + 'password' => '123456', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -39,7 +43,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '', /* db login password */ + 'password' => '123456', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -49,7 +53,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '', /* db login password */ + 'password' => '123456', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -59,7 +63,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '', /* db login password */ + 'password' => '123456', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -69,7 +73,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '', /* db login password */ + 'password' => '123456', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ diff --git a/tests/DataStorage/Session/HttpSessionTest.php b/tests/DataStorage/Session/HttpSessionTest.php index f18121296..95d60e730 100644 --- a/tests/DataStorage/Session/HttpSessionTest.php +++ b/tests/DataStorage/Session/HttpSessionTest.php @@ -21,7 +21,6 @@ class HttpSessionTest extends \PHPUnit\Framework\TestCase { $session = new HttpSession(); self::assertEquals(null, $session->get('key')); - self::assertGreaterThan(0, strlen($session->getSID())); self::assertFalse(HttpSession::isLocked()); } From 175be313d2715a848210f661908582658a7599fc Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 4 Aug 2018 20:23:35 +0200 Subject: [PATCH 107/136] Remove pw --- tests/Bootstrap.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php index 42437c99b..186173f1e 100644 --- a/tests/Bootstrap.php +++ b/tests/Bootstrap.php @@ -23,7 +23,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -33,7 +33,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -43,7 +43,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -53,7 +53,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -63,7 +63,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ @@ -73,7 +73,7 @@ $CONFIG = [ 'host' => '127.0.0.1', /* db host address */ 'port' => '3306', /* db host port */ 'login' => 'root', /* db login name */ - 'password' => '123456', /* db login password */ + 'password' => '', /* db login password */ 'database' => 'oms', /* db name */ 'prefix' => 'oms_', /* db table prefix */ 'weight' => 1000, /* db table prefix */ From 24659e324fbf28320ed98bbfe94668e0fe2dee4e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Thu, 9 Aug 2018 18:43:03 +0200 Subject: [PATCH 108/136] fixes #158 --- .../Math/Matrix/CholeskyDecompositionTest.php | 16 ++++- tests/Math/Matrix/QRDecompositionTest.php | 69 +++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 tests/Math/Matrix/QRDecompositionTest.php diff --git a/tests/Math/Matrix/CholeskyDecompositionTest.php b/tests/Math/Matrix/CholeskyDecompositionTest.php index 8d433f07c..ee9773f8c 100644 --- a/tests/Math/Matrix/CholeskyDecompositionTest.php +++ b/tests/Math/Matrix/CholeskyDecompositionTest.php @@ -36,11 +36,23 @@ class CholeskyDecompositionTest extends \PHPUnit\Framework\TestCase [-1, 1, 3], ], $cholesky->getL()->toArray(), '', 0.2); + self::assertTrue($cholesky->isSpd()); + } + + public function testSolve() + { + $A = new Matrix(); + $A->setMatrix([ + [25, 15, -5], + [15, 17, 0], + [-5, 0, 11], + ]); + + $cholesky = new CholeskyDecomposition($A); + $vec = new Vector(); $vec->setMatrix([[40], [49], [28]]); self::assertEquals([[1], [2], [3]], $cholesky->solve($vec)->toArray(), '', 0.2); - - self::assertTrue($cholesky->isSpd()); } /** diff --git a/tests/Math/Matrix/QRDecompositionTest.php b/tests/Math/Matrix/QRDecompositionTest.php new file mode 100644 index 000000000..7c473c25f --- /dev/null +++ b/tests/Math/Matrix/QRDecompositionTest.php @@ -0,0 +1,69 @@ +setMatrix([ + [12, -51, 4], + [6, 167, -68], + [-4, 24, -41], + ]); + + $QR = new QRDecomposition($A); + + self::assertTrue($QR->isFullRank()); + + self::assertEquals([ + [12, -69, -58 / 5], + [6, 158, 6 / 5], + [-4, 30, -33], + ], $QR->getH()->toArray(), '', 0.2); + + self::assertEquals([ + [6 / 7, -69 / 175, -58 / 175], + [3 / 7, 158 / 175, 6 / 175], + [-2 / 7, 6 / 35, -33 / 35], + ], $QR->getQ()->toArray(), '', 0.2); + + self::assertEquals([ + [14, 21, -14], + [0, 175, -70], + [0, 0, 35], + ], $QR->getR()->toArray(), '', 0.2); + }*/ + + public function testSolve() + { + $A = new Matrix(); + $A->setMatrix([ + [25, 15, -5], + [15, 17, 0], + [-5, 0, 11], + ]); + + $QR = new QRDecomposition($A); + + $vec = new Vector(); + $vec->setMatrix([[40], [49], [28]]); + self::assertEquals([[1], [2], [3]], $QR->solve($vec)->toArray(), '', 0.2); + } +} From e5c70b1b4328957ed253110b2b2719c5930fd398 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 12:10:21 +0200 Subject: [PATCH 109/136] Extend build script --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ef9705922..a2d2995d6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,5 +7,10 @@ services: before_script: - pecl install ast - composer install + - git clone -b develop https://github.com/Orange-Management/Build.git + - ls -l script: - - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml \ No newline at end of file + - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml + - Build/Hooks/travis.sh +notifications: + email: false \ No newline at end of file From 08d5987553442036bd442848aba104518c8e3300 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 12:10:36 +0200 Subject: [PATCH 110/136] Use global namespace --- DataStorage/Database/DataMapperAbstract.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/DataStorage/Database/DataMapperAbstract.php b/DataStorage/Database/DataMapperAbstract.php index 578362bc1..eb1893316 100644 --- a/DataStorage/Database/DataMapperAbstract.php +++ b/DataStorage/Database/DataMapperAbstract.php @@ -672,7 +672,7 @@ class DataMapperAbstract implements DataMapperInterface $objsIds = []; foreach ($values as $key => &$value) { - if (!is_array($value)) { + if (!\is_array($value)) { // Is scalar => already in database $objsIds[$key] = $value; @@ -760,7 +760,7 @@ class DataMapperAbstract implements DataMapperInterface */ private static function createOwnsOneArray(string $propertyName, array &$obj) { - if (is_array($obj)) { + if (\is_array($obj)) { $mapper = static::$ownsOne[$propertyName]['mapper']; $primaryKey = $obj[static::$columns[static::$primaryField]['internal']]; @@ -817,7 +817,7 @@ class DataMapperAbstract implements DataMapperInterface */ private static function createBelongsToArray(string $propertyName, array $obj) { - if (is_array($obj)) { + if (\is_array($obj)) { /** @var string $mapper */ $mapper = static::$belongsTo[$propertyName]['mapper']; $primaryKey = $obj[static::$columns[static::$primaryField]['internal']]; @@ -1533,7 +1533,7 @@ class DataMapperAbstract implements DataMapperInterface } $objects = $mapper::get($values, RelationType::ALL, null, $depth); - $refProp->setValue($obj, !is_array($objects) ? [$objects->getId() => $objects] : $objects); + $refProp->setValue($obj, !\is_array($objects) ? [$objects->getId() => $objects] : $objects); if (!$accessible) { $refProp->setAccessible(false); @@ -1599,7 +1599,7 @@ class DataMapperAbstract implements DataMapperInterface continue; } - $id = is_object($id) ? self::getObjectId($id) : $id; + $id = \is_object($id) ? self::getObjectId($id) : $id; $value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth); $refProp->setValue($obj, $value); @@ -1665,7 +1665,7 @@ class DataMapperAbstract implements DataMapperInterface continue; } - $id = is_object($id) ? self::getObjectId($id) : $id; + $id = \is_object($id) ? self::getObjectId($id) : $id; $value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth); $refProp->setValue($obj, $value); @@ -1731,7 +1731,7 @@ class DataMapperAbstract implements DataMapperInterface continue; } - $id = is_object($id) ? self::getObjectId($id) : $id; + $id = \is_object($id) ? self::getObjectId($id) : $id; $value = self::getInitialized($mapper, $id) ?? $mapper::get($id, RelationType::ALL, null, $depth); $refProp->setValue($obj, $value); From 0b6adc9244eded3fc0481c529946e18b6d91450b Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 12:31:08 +0200 Subject: [PATCH 111/136] Make build hooks executable --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index a2d2995d6..584ac3b4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,7 @@ before_script: - pecl install ast - composer install - git clone -b develop https://github.com/Orange-Management/Build.git + - chmod 755 -R Build/ - ls -l script: - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml From 891b94a889da6e384bc673759a16a1f7dbf9000a Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 12:31:11 +0200 Subject: [PATCH 112/136] Make build hooks executable --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 584ac3b4e..13e8b07d5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ before_script: - pecl install ast - composer install - git clone -b develop https://github.com/Orange-Management/Build.git - - chmod 755 -R Build/ + - chmod 755 -R Build/Hooks - ls -l script: - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml From d8494e439cfc17e4c155850e3ef9e3066c721e52 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 12:46:36 +0200 Subject: [PATCH 113/136] Try to fix unittests for travis --- tests/phpunit_no_coverage.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index bc6ea2cdd..12c01a59a 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -10,9 +10,10 @@ > - .* + tests Module/ModuleManagerTest.php vendor* + Build* From 828ee4f2ed3cd37c3f54a6faaae9bc115319ae36 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 12:51:05 +0200 Subject: [PATCH 114/136] Get current path --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 13e8b07d5..d71dc2638 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,6 +12,7 @@ before_script: - ls -l script: - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml + - pwd - Build/Hooks/travis.sh notifications: email: false \ No newline at end of file From 108ad59bd9dd6c1def0177c77bababcec58baee5 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 13:16:29 +0200 Subject: [PATCH 115/136] Fix some travis build bugs --- .travis.yml | 2 +- tests/phpunit_no_coverage.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index d71dc2638..ee5792ae3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ before_script: - pecl install ast - composer install - git clone -b develop https://github.com/Orange-Management/Build.git - - chmod 755 -R Build/Hooks + - chmod -R 755 Build/Hooks - ls -l script: - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index 12c01a59a..3cc98c85d 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -23,7 +23,7 @@ ../* ../* ../* - ../Build/* + Build/* From 71022d13b1b77d89dbb5a1e4126adb029766ccaf Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 13:28:55 +0200 Subject: [PATCH 116/136] Fix some travis build bugs --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ee5792ae3..6e03ff00c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,6 +13,6 @@ before_script: script: - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml - pwd - - Build/Hooks/travis.sh + - ./Build/Hooks/travis.sh notifications: email: false \ No newline at end of file From bd87ffadff412ff30b8b70e4d0bb88189a327fcf Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 13:51:41 +0200 Subject: [PATCH 117/136] More build fix tests --- tests/phpunit_no_coverage.xml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index 3cc98c85d..2cdead0d3 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -10,10 +10,11 @@ > - tests + ./ + ./tests Module/ModuleManagerTest.php - vendor* - Build* + ./vendor + ./Build @@ -23,7 +24,7 @@ ../* ../* ../* - Build/* + ./Build From 356027981f5e91cce8f23f5677c7b692614ea704 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 14:20:21 +0200 Subject: [PATCH 118/136] Use local phpunit --- .travis.yml | 3 +-- tests/phpunit_no_coverage.xml | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6e03ff00c..db918fcae 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,8 @@ before_script: - composer install - git clone -b develop https://github.com/Orange-Management/Build.git - chmod -R 755 Build/Hooks - - ls -l script: - - phpunit --version && phpunit --configuration tests/phpunit_no_coverage.xml + - vendor/bin/phpunit --version && vendor/bin/phpunit --configuration tests/phpunit_no_coverage.xml - pwd - ./Build/Hooks/travis.sh notifications: diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index 2cdead0d3..b95dbd154 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -11,7 +11,7 @@ ./ - ./tests + ./tests/ Module/ModuleManagerTest.php ./vendor ./Build From 2b29a3c012958d1169d98879fc693467f11e1357 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 14:51:53 +0200 Subject: [PATCH 119/136] Fix catching throwables --- Localization/L11nManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Localization/L11nManager.php b/Localization/L11nManager.php index 7119c9f3e..0f9d6541d 100644 --- a/Localization/L11nManager.php +++ b/Localization/L11nManager.php @@ -158,7 +158,7 @@ final class L11nManager if (!isset($this->language[$code][$module][$translation])) { return 'ERROR'; } - } catch (\Exception $e) { + } catch (\Throwable $e) { FileLogger::getInstance()->warning(FileLogger::MSG_FULL, [ 'message' => 'Undefined translation for \'' . $code . '/' . $module . '/' . $translation . '\'.', ]); From 9085fa7a7ef268345db6e162b44763e9cb7f6820 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 15:01:01 +0200 Subject: [PATCH 120/136] Fix separate phpOMS tests without other components --- Module/ModuleFactory.php | 2 +- tests/Module/ModuleFactoryTest.php | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Module/ModuleFactory.php b/Module/ModuleFactory.php index 0097bb5f0..dc1f54076 100644 --- a/Module/ModuleFactory.php +++ b/Module/ModuleFactory.php @@ -79,7 +79,7 @@ final class ModuleFactory self::$loaded[$module] = $obj; self::registerRequesting($obj); self::registerProvided($obj); - } catch (\Exception $e) { + } catch (\Throwable $e) { self::$loaded[$module] = new NullModule($app); } } else { diff --git a/tests/Module/ModuleFactoryTest.php b/tests/Module/ModuleFactoryTest.php index 960c45d8f..9436b5264 100644 --- a/tests/Module/ModuleFactoryTest.php +++ b/tests/Module/ModuleFactoryTest.php @@ -17,11 +17,17 @@ require_once __DIR__ . '/../Autoloader.php'; use phpOMS\ApplicationAbstract; use phpOMS\Module\ModuleFactory; +use phpOMS\Module\NullModule; class ModuleFactoryTest extends \PHPUnit\Framework\TestCase { public function testFactory() { - self::assertInstanceOf(\Modules\Admin\Controller::class, ModuleFactory::getInstance('Admin', new class extends ApplicationAbstract {})); + $instance = NullModule::class; + if (\file_exists(__DIR__ . '/../../../Modules')) { + $instance = \Modules\Admin\Controller::class; + } + + self::assertInstanceOf($instance, ModuleFactory::getInstance('Admin', new class extends ApplicationAbstract {})); } } From 94eb099fb9baada7df5811df290633793e9ddd7f Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 15:10:05 +0200 Subject: [PATCH 121/136] Check correct cron/schedule path --- tests/Utils/TaskSchedule/CronTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/Utils/TaskSchedule/CronTest.php b/tests/Utils/TaskSchedule/CronTest.php index 8cf1b8078..0b71b6198 100644 --- a/tests/Utils/TaskSchedule/CronTest.php +++ b/tests/Utils/TaskSchedule/CronTest.php @@ -25,15 +25,16 @@ class CronTest extends \PHPUnit\Framework\TestCase public function testCRUD() { + self::assertTrue(Cron::guessBin()); + if (\stristr(PHP_OS, 'LINUX')) { - Cron::guessBin(); $cron = new Cron(); self::assertEquals([], $cron->getAllByName('testCronJob', false)); - + $job = new CronJob('testCronJob', 'testFile', '0 0 1 1 *'); $cron->create($job); - + self::assertTrue(!empty($cron->getAllByName('testCronJob', false))); if (!empty($cron->getAllByName('testCronJob', false))) { self::assertEquals('testFile', $cron->getAllByName('testCronJob', false)[0]->getCommand()); From ac3711768c244fea0dc8d9d6d29abf9b06a4b09c Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 15:11:46 +0200 Subject: [PATCH 122/136] Test path guessing --- tests/Utils/TaskSchedule/CronTest.php | 3 +-- tests/Utils/TaskSchedule/TaskSchedulerTest.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/Utils/TaskSchedule/CronTest.php b/tests/Utils/TaskSchedule/CronTest.php index 0b71b6198..cd670efbd 100644 --- a/tests/Utils/TaskSchedule/CronTest.php +++ b/tests/Utils/TaskSchedule/CronTest.php @@ -25,9 +25,8 @@ class CronTest extends \PHPUnit\Framework\TestCase public function testCRUD() { - self::assertTrue(Cron::guessBin()); - if (\stristr(PHP_OS, 'LINUX')) { + self::assertTrue(Cron::guessBin()); $cron = new Cron(); self::assertEquals([], $cron->getAllByName('testCronJob', false)); diff --git a/tests/Utils/TaskSchedule/TaskSchedulerTest.php b/tests/Utils/TaskSchedule/TaskSchedulerTest.php index b6bf0cb87..3f18146fa 100644 --- a/tests/Utils/TaskSchedule/TaskSchedulerTest.php +++ b/tests/Utils/TaskSchedule/TaskSchedulerTest.php @@ -26,7 +26,7 @@ class TaskSchedulerTest extends \PHPUnit\Framework\TestCase public function testCRUD() { if (\stristr(PHP_OS, 'WIN')) { - TaskScheduler::guessBin(); + self::assertTrue(TaskScheduler::guessBin()); $cron = new TaskScheduler(); self::assertEquals([], $cron->getAllByName('testCronJob', false)); From ce469cbae359d06f5e48ef6baa34e62084c20cfb Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 15:25:17 +0200 Subject: [PATCH 123/136] Disable test for travis --- tests/Utils/TaskSchedule/CronTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Utils/TaskSchedule/CronTest.php b/tests/Utils/TaskSchedule/CronTest.php index cd670efbd..0712511af 100644 --- a/tests/Utils/TaskSchedule/CronTest.php +++ b/tests/Utils/TaskSchedule/CronTest.php @@ -25,7 +25,7 @@ class CronTest extends \PHPUnit\Framework\TestCase public function testCRUD() { - if (\stristr(PHP_OS, 'LINUX')) { + if (\stripos(PHP_OS, 'LINUX') !== false && \stripos(__DIR__, '/travis/') === false) { self::assertTrue(Cron::guessBin()); $cron = new Cron(); From b2037ddf9281c3daabcdce7244d3d5db27a4002f Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 16:13:17 +0200 Subject: [PATCH 124/136] Test invalid php syntax --- Autoloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Autoloader.php b/Autoloader.php index 9ee328ee4..c5e8e3a36 100644 --- a/Autoloader.php +++ b/Autoloader.php @@ -12,7 +12,7 @@ */ declare(strict_types=1); -namespace phpOMS; +namespace phpOMS; spl_autoload_register('\phpOMS\Autoloader::defaultAutoloader'); From f5ec5b320d4f5b764f8cb2658c84ee95eca63954 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 16:30:04 +0200 Subject: [PATCH 125/136] Test invalid php syntax --- Autoloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Autoloader.php b/Autoloader.php index c5e8e3a36..29b28cb4d 100644 --- a/Autoloader.php +++ b/Autoloader.php @@ -12,7 +12,7 @@ */ declare(strict_types=1); -namespace phpOMS; +namespace phpOMS; spl_autoload_register('\phpOMS\Autoloader::defaultAutoloader'); From 2b49245901962f0c49af0777c933261fcd2d491d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 16:36:36 +0200 Subject: [PATCH 126/136] Test invalid php syntax --- Autoloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Autoloader.php b/Autoloader.php index 29b28cb4d..c5e8e3a36 100644 --- a/Autoloader.php +++ b/Autoloader.php @@ -12,7 +12,7 @@ */ declare(strict_types=1); -namespace phpOMS; +namespace phpOMS; spl_autoload_register('\phpOMS\Autoloader::defaultAutoloader'); From d89ba9832af8836253af4a447833eec8f18df93d Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 11 Aug 2018 16:42:11 +0200 Subject: [PATCH 127/136] Test invalid php syntax --- Autoloader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Autoloader.php b/Autoloader.php index c5e8e3a36..9ee328ee4 100644 --- a/Autoloader.php +++ b/Autoloader.php @@ -12,7 +12,7 @@ */ declare(strict_types=1); -namespace phpOMS; +namespace phpOMS; spl_autoload_register('\phpOMS\Autoloader::defaultAutoloader'); From bd935810bf747a81b93a7336d93105c9c8bae3c2 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 12 Aug 2018 10:12:46 +0200 Subject: [PATCH 128/136] Add code coverage --- .gitignore | 3 ++- .travis.yml | 6 ++++++ composer.json | 5 +++-- tests/phpunit_no_coverage.xml | 3 +++ 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 5ed14d0f6..954fa8953 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ *.log -.directory \ No newline at end of file +.directory +vendor \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index db918fcae..857485eed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,15 @@ before_script: - composer install - git clone -b develop https://github.com/Orange-Management/Build.git - chmod -R 755 Build/Hooks +addons: + code_climate: + repo_token: + secure: "zXoveZL6QPXXcdyGxfgjlIRGSFbTgwi2NU6V9tROypLMA+5IWRd0CvvQkl4vx2lIAF5Pn3jOGqG6p6qinqwSzX2tE/RsdDEDz8LPKpN+AShyxLzzYu2ohDSqm3rSXysdgbjQBB1YoUIumhUGABfYIdZk+7g1Yjc3RLFdAs3YzB7CdG4zeBA1Xe82KHUDwZb2M/MG/Bf9jsi9HmjrBeMTmCiW8v6wclYG9rbkIoXY4mv4H0ywiTv4lHuyRWs19kJn4kKI3oLqmv0UcUmLv0wNgPrww2STtN/7ghlaiLNSrdKQV1EuVi/nRxxNlH2z+h8cMPAcksqZ29TT9RYkK32433QIUHYzN6t4LB8PgNkFPMc6zI6uzD9We4oYAw4bVIxkEgHXJBInfYSNRfoGPGHZ9WU+Ph9zt2nyB4mS6014gHgjBZSF+DV/r1mHa9XtXPDzxrbHJF7rIp99iOBnpGBcn4ERVhLP6onuam86TSgXjgyUrnTGazwKoc6cfwvb9RswpVtTvNJIYgzfJG6+QFAsltOSo3iRvKq+F2X3Lh/3dOAAcqh3TOZaSPee2sHCDFYq5d0qpNFJq/o6tEcPP9J6PmKsD7Ql9Zu1qNJ2MevheE/U/3sh2dy/5rhDSFCig2TRMy/53QATcCm2ngIfBJkeVyLQ2VMUsMXOk5v2uF16E6k=" script: - vendor/bin/phpunit --version && vendor/bin/phpunit --configuration tests/phpunit_no_coverage.xml - pwd - ./Build/Hooks/travis.sh +after_script: + - vendor/bin/test-reporter notifications: email: false \ No newline at end of file diff --git a/composer.json b/composer.json index 2dd5e5ba9..9a403e873 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "phpunit/phpunit": "~6.4", "squizlabs/php_codesniffer": "~3.2", "phpmd/phpmd": "~2.6", - "phpstan/phpstan": "~0.10.1" + "phpstan/phpstan": "~0.10.1", + "codeclimate/php-test-reporter": "^0.4.4" } -} \ No newline at end of file +} diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index b95dbd154..932e5d755 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -28,4 +28,7 @@ + + + From 1017a3a00379d9b7381bd6ef3ce62ba61684a6b5 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 12 Aug 2018 10:26:57 +0200 Subject: [PATCH 129/136] Fix coverage path --- tests/phpunit_no_coverage.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index 932e5d755..010857bc9 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -29,6 +29,6 @@ - + From df8d6c42c013b362f628986831efb8620a5c6211 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 12 Aug 2018 10:43:33 +0200 Subject: [PATCH 130/136] Exclude vendor --- tests/phpunit_no_coverage.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index 010857bc9..f8c8a4baa 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -25,6 +25,7 @@ ../* ../* ./Build + */vendor/* From 4994050839e1af6b8ca3c528fa6e7b13debb51e4 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 12 Aug 2018 10:52:58 +0200 Subject: [PATCH 131/136] Exclude vendor --- tests/phpunit_no_coverage.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/phpunit_no_coverage.xml b/tests/phpunit_no_coverage.xml index f8c8a4baa..06ec01ec2 100644 --- a/tests/phpunit_no_coverage.xml +++ b/tests/phpunit_no_coverage.xml @@ -25,7 +25,9 @@ ../* ../* ./Build - */vendor/* + *vendor* + ./vendor + ../vendor From 8a3893b36b27a50df24d10673e7cbf8e774bd2b6 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sun, 12 Aug 2018 11:17:24 +0200 Subject: [PATCH 132/136] Add build status --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3c5784431..336b975ff 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![Maintainability](https://api.codeclimate.com/v1/badges/7e83e9f82ea1b19e1574/maintainability)](https://codeclimate.com/github/Orange-Management/phpOMS/maintainability) +[![Build Status](https://travis-ci.org/Orange-Management/phpOMS.svg?branch=develop)](https://travis-ci.org/Orange-Management/phpOMS) # General From cd8f4945e6eb5d99125e3d10c7514bd9c6a143d1 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 17 Aug 2018 19:56:21 +0200 Subject: [PATCH 133/136] Implement permission check in routes --- Autoloader.php | 4 ++-- Router/Router.php | 26 +++++++++++++------------- tests/Router/RouterTest.php | 9 --------- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/Autoloader.php b/Autoloader.php index 9ee328ee4..d05b6c2d0 100644 --- a/Autoloader.php +++ b/Autoloader.php @@ -81,7 +81,7 @@ final class Autoloader $class = \str_replace(['_', '\\'], '/', $class); foreach (self::$paths as $path) { - if (file_exists($file = $path . $class . '.php')) { + if (\file_exists($file = $path . $class . '.php')) { include_once $file; return; @@ -106,7 +106,7 @@ final class Autoloader $class = \str_replace(['_', '\\'], '/', $class); foreach (self::$paths as $path) { - if (file_exists($file = $path . $class . '.php')) { + if (\file_exists($file = $path . $class . '.php')) { return true; } } diff --git a/Router/Router.php b/Router/Router.php index 4200e5230..5d71c7dba 100644 --- a/Router/Router.php +++ b/Router/Router.php @@ -60,7 +60,7 @@ final class Router * Add route. * * @param string $route Route regex - * @param mixed $destination Destination e.g. Module:function & verb + * @param mixed $destination Destination e.g. Module:function string or callback * @param int $verb Request verb * * @return void @@ -91,22 +91,22 @@ final class Router * * @since 1.0.0 */ - public function route($request, int $verb = RouteVerb::GET) : array + public function route(string $request, int $verb = RouteVerb::GET, string $app = '', string $orgId = '', $account = null) : array { - if ($request instanceof RequestAbstract) { - $uri = $request->getUri()->getRoute(); - $verb = $request->getRouteVerb(); - } elseif (\is_string($request)) { - $uri = $request; - } else { - throw new \InvalidArgumentException(); - } - $bound = []; foreach ($this->routes as $route => $destination) { foreach ($destination as $d) { - if ($this->match($route, $d['verb'], $uri, $verb)) { - $bound[] = ['dest' => $d['dest']]; + if ($this->match($route, $d['verb'], $request, $verb)) { + if (!isset($d['permission']) + || !isset($account) + || (isset($d['permission']) + && isset($account) + && $account->hasPermission($d['permission']['type'], $orgId, $app, $d['permission']['module'], $d['permission']['state'])) + ) { + $bound[] = ['dest' => $d['dest']]; + } else { + array_merge($bound, $this->route('/' . $app . '/e403', $verb)); + } } } } diff --git a/tests/Router/RouterTest.php b/tests/Router/RouterTest.php index 5541dfcdd..ab2f41333 100644 --- a/tests/Router/RouterTest.php +++ b/tests/Router/RouterTest.php @@ -75,13 +75,4 @@ class RouterTest extends \PHPUnit\Framework\TestCase $router->route('http://test.com/backends/admin/settings/general/something?test', RouteVerb::GET) ); } - - /** - * @expectedException \InvalidArgumentException - */ - public function testInvalidRequestType() - { - $router = new Router(); - $router->route([]); - } } From df2bd5b624e592c870050251e1537d564681c185 Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Fri, 17 Aug 2018 20:00:34 +0200 Subject: [PATCH 134/136] Fix type bug --- Router/Router.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Router/Router.php b/Router/Router.php index 5d71c7dba..25c58af58 100644 --- a/Router/Router.php +++ b/Router/Router.php @@ -91,16 +91,16 @@ final class Router * * @since 1.0.0 */ - public function route(string $request, int $verb = RouteVerb::GET, string $app = '', string $orgId = '', $account = null) : array + public function route(string $request, int $verb = RouteVerb::GET, string $app = '', int $orgId = 1, $account = null) : array { $bound = []; foreach ($this->routes as $route => $destination) { foreach ($destination as $d) { if ($this->match($route, $d['verb'], $request, $verb)) { - if (!isset($d['permission']) - || !isset($account) - || (isset($d['permission']) - && isset($account) + if (!isset($d['permission']) + || !isset($account) + || (isset($d['permission']) + && isset($account) && $account->hasPermission($d['permission']['type'], $orgId, $app, $d['permission']['module'], $d['permission']['state'])) ) { $bound[] = ['dest' => $d['dest']]; From 1caf381603b395e5bdf914fec24671d47552216b Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 18 Aug 2018 09:21:52 +0200 Subject: [PATCH 135/136] Load localization based on language or locale --- Localization/Defaults/Definitions/en_US.json | 4 +- Localization/Localization.php | 77 +++++++++++++++++--- Router/Router.php | 2 +- tests/Localization/LocalizationTest.php | 11 +-- 4 files changed, 76 insertions(+), 18 deletions(-) diff --git a/Localization/Defaults/Definitions/en_US.json b/Localization/Defaults/Definitions/en_US.json index 6ba33326d..77af7f449 100644 --- a/Localization/Defaults/Definitions/en_US.json +++ b/Localization/Defaults/Definitions/en_US.json @@ -1,6 +1,6 @@ { - "language": "EN", - "country": "USA", + "language": "en", + "country": "US", "currency": { "code": "USD", "position": 0 diff --git a/Localization/Localization.php b/Localization/Localization.php index 83fbc5382..7dc372e46 100644 --- a/Localization/Localization.php +++ b/Localization/Localization.php @@ -17,6 +17,7 @@ namespace phpOMS\Localization; use phpOMS\Stdlib\Base\Exception\InvalidEnumValue; use phpOMS\Utils\Converter\AngleType; use phpOMS\Utils\Converter\TemperatureType; +use phpOMS\System\File\Local\Directory; /** * Localization class. @@ -91,10 +92,10 @@ final class Localization /** * Time format. * - * @var string + * @var array * @since 1.0.0 */ - private $datetime = 'Y-m-d H:i:s'; + private $datetime = []; /** * Weight. @@ -137,12 +138,68 @@ final class Localization private $volume = []; /** - * Constructor. + * Load localization from language code + * + * @param string $langCode Language code + * + * @return void * * @since 1.0.0 */ - public function __construct() + public function loadFromLanguage(string $langCode) : void { + $langCode = \strtolower($langCode); + + if (!ISO639x1Enum::isValidValue($langCode)) { + throw new InvalidEnumValue($langCode); + } + + $files = Directory::list(__DIR__ . '/../Localization/Defaults/Definitions'); + + foreach ($files as $file) { + if (\stripos($file, $langCode) === 0) { + $this->importLocale( + json_decode( + \file_get_contents(__DIR__ . '/../Localization/Defaults/Definitions/' . $file), + true + ) + ); + return; + } + } + + $this->importLocale( + json_decode( + \file_get_contents(__DIR__ . '/../Localization/Defaults/Definitions/en_US.json'), + true + ) + ); + } + + /** + * Load localization from locale + * + * @param array $locale Locale data + * + * @return void + * + * @since 1.0.0 + */ + public function importLocale(array $locale) : void + { + $this->setLanguage($locale['language'] ?? 'en'); + $this->setCountry($locale['country'] ?? 'US'); + $this->setCurrency($locale['currency']['code'] ?? ISO4217Enum::_USD); + $this->setThousands($locale['thousand'] ?? ','); + $this->setDecimal($locale['decimal'] ?? '.'); + $this->setAngle($locale['angle'] ?? AngleType::DEGREE); + $this->setTemperature($locale['temperature'] ?? emperatureType::CELSIUS); + $this->setWeight($locale['weight'] ?? []); + $this->setSpeed($locale['speed'] ?? []); + $this->setLength($locale['length'] ?? []); + $this->setArea($locale['area'] ?? []); + $this->setVolume($locale['volume'] ?? []); + $this->setDatetime($locale['datetime'] ?? []); } /** @@ -232,7 +289,7 @@ final class Localization */ public function setLanguage(string $language) : void { - $language = strtolower($language); + $language = \strtolower($language); if (!ISO639x1Enum::isValidValue($language)) { throw new InvalidEnumValue($language); @@ -264,7 +321,7 @@ final class Localization */ public function setCurrency(string $currency) : void { - if (!ISO4217Enum::isValidValue($currency)) { + if (!ISO4217CharEnum::isValidValue($currency)) { throw new InvalidEnumValue($currency); } @@ -274,11 +331,11 @@ final class Localization /** * get datetime format * - * @return string + * @return array * * @since 1.0.0 */ - public function getDatetime() : string + public function getDatetime() : array { return $this->datetime; } @@ -286,13 +343,13 @@ final class Localization /** * Set datetime format * - * @param string $datetime Datetime format + * @param array $datetime Datetime format * * @return void * * @since 1.0.0 */ - public function setDatetime(string $datetime) : void + public function setDatetime(array $datetime) : void { $this->datetime = $datetime; } diff --git a/Router/Router.php b/Router/Router.php index 25c58af58..cac6691fd 100644 --- a/Router/Router.php +++ b/Router/Router.php @@ -105,7 +105,7 @@ final class Router ) { $bound[] = ['dest' => $d['dest']]; } else { - array_merge($bound, $this->route('/' . $app . '/e403', $verb)); + \array_merge($bound, $this->route('/' . $app . '/e403', $verb)); } } } diff --git a/tests/Localization/LocalizationTest.php b/tests/Localization/LocalizationTest.php index 305c488ce..60739e5a2 100644 --- a/tests/Localization/LocalizationTest.php +++ b/tests/Localization/LocalizationTest.php @@ -16,6 +16,7 @@ namespace phpOMS\tests\Localization; use phpOMS\Localization\ISO3166TwoEnum; use phpOMS\Localization\ISO4217Enum; use phpOMS\Localization\ISO639x1Enum; +use phpOMS\Localization\ISO4217CharEnum; use phpOMS\Localization\L11nManager; use phpOMS\Localization\Localization; use phpOMS\Localization\TimeZoneEnumArray; @@ -55,7 +56,7 @@ class LocalizationTest extends \PHPUnit\Framework\TestCase self::assertTrue(ISO4217Enum::isValidValue($localization->getCurrency())); self::assertEquals('.', $localization->getDecimal()); self::assertEquals(',', $localization->getThousands()); - self::assertEquals('Y-m-d H:i:s', $localization->getDatetime()); + self::assertEquals([], $localization->getDatetime()); self::assertEquals([], $localization->getSpeed()); self::assertEquals([], $localization->getWeight()); @@ -113,11 +114,11 @@ class LocalizationTest extends \PHPUnit\Framework\TestCase $localization->setLanguage(ISO639x1Enum::_DE); self::assertEquals(ISO639x1Enum::_DE, $localization->getLanguage()); - $localization->setCurrency(ISO4217Enum::_EUR); - self::assertEquals(ISO4217Enum::_EUR, $localization->getCurrency()); + $localization->setCurrency(ISO4217CharEnum::_EUR); + self::assertEquals(ISO4217CharEnum::_EUR, $localization->getCurrency()); - $localization->setDatetime('Y-m-d H:i:s'); - self::assertEquals('Y-m-d H:i:s', $localization->getDatetime()); + $localization->setDatetime(['Y-m-d H:i:s']); + self::assertEquals(['Y-m-d H:i:s'], $localization->getDatetime()); $localization->setDecimal(','); self::assertEquals(',', $localization->getDecimal()); From de2fdb61bc4b0dad5f72fef897f1a89769ac191e Mon Sep 17 00:00:00 2001 From: Dennis Eichhorn Date: Sat, 18 Aug 2018 12:41:53 +0200 Subject: [PATCH 136/136] Handle empty table name in where clause --- .../Database/Query/Grammar/Grammar.php | 39 +++++++++++-------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/DataStorage/Database/Query/Grammar/Grammar.php b/DataStorage/Database/Query/Grammar/Grammar.php index e462a20de..2552e7684 100644 --- a/DataStorage/Database/Query/Grammar/Grammar.php +++ b/DataStorage/Database/Query/Grammar/Grammar.php @@ -281,10 +281,15 @@ class Grammar extends GrammarAbstract $expression = ''; if (!$first) { - $expression = ' ' . strtoupper($element['boolean']) . ' '; + $expression = ' ' . \strtoupper($element['boolean']) . ' '; } - if (is_string($element['column'])) { + if (\is_string($element['column'])) { + // handle bug when no table is specified in the where column + if (count($query->from) === 1 && \stripos($element['column'], '.') === false) { + $element['column'] = $query->from[0] . '.' . $element['column']; + } + $expression .= $this->compileSystem($element['column'], $query->getPrefix()); } elseif ($element['column'] instanceof \Closure) { $expression .= $element['column'](); @@ -297,9 +302,9 @@ class Grammar extends GrammarAbstract // todo: handle IN(...) as operator if (isset($element['value'])) { - $expression .= ' ' . strtoupper($element['operator']) . ' ' . $this->compileValue($query, $element['value'], $query->getPrefix()); + $expression .= ' ' . \strtoupper($element['operator']) . ' ' . $this->compileValue($query, $element['value'], $query->getPrefix()); } else { - $operator = strtoupper($element['operator']) === '=' ? 'IS' : 'IS NOT'; + $operator = \strtoupper($element['operator']) === '=' ? 'IS' : 'IS NOT'; $expression .= ' ' . $operator . ' ' . $this->compileValue($query, $element['value'], $query->getPrefix()); } @@ -327,29 +332,29 @@ class Grammar extends GrammarAbstract */ protected function compileValue(Builder $query, $value, string $prefix = '') : string { - if (is_string($value)) { - if (strpos($value, ':') === 0) { + if (\is_string($value)) { + if (\strpos($value, ':') === 0) { return $value; } return $query->quote($value); - } elseif (is_int($value)) { + } elseif (\is_int($value)) { return (string) $value; - } elseif (is_array($value)) { + } elseif (\is_array($value)) { $values = ''; foreach ($value as $val) { $values .= $this->compileValue($query, $val, $prefix) . ', '; } - return '(' . rtrim($values, ', ') . ')'; + return '(' . \rtrim($values, ', ') . ')'; } elseif ($value instanceof \DateTime) { return $query->quote($value->format('Y-m-d H:i:s')); } elseif ($value === null) { return 'NULL'; - } elseif (is_bool($value)) { + } elseif (\is_bool($value)) { return (string) ((int) $value); - } elseif (is_float($value)) { + } elseif (\is_float($value)) { return (string) $value; } elseif ($value instanceof Column) { return $this->compileSystem($value->getColumn(), $prefix); @@ -411,7 +416,7 @@ class Grammar extends GrammarAbstract $expression .= $this->compileSystem($group, $query->getPrefix()) . ', '; } - $expression = rtrim($expression, ', '); + $expression = \rtrim($expression, ', '); return 'GROUP BY ' . $expression; } @@ -435,7 +440,7 @@ class Grammar extends GrammarAbstract $expression .= $this->compileSystem($column, $query->getPrefix()) . ', '; } - $expression = rtrim($expression, ', '); + $expression = \rtrim($expression, ', '); $expression .= ' ' . $key . ', '; } @@ -443,7 +448,7 @@ class Grammar extends GrammarAbstract return ''; } - $expression = rtrim($expression, ', '); + $expression = \rtrim($expression, ', '); return 'ORDER BY ' . $expression; } @@ -495,7 +500,7 @@ class Grammar extends GrammarAbstract return ''; } - return '(' . rtrim($cols, ', ') . ')'; + return '(' . \rtrim($cols, ', ') . ')'; } /** @@ -520,7 +525,7 @@ class Grammar extends GrammarAbstract return ''; } - return 'VALUES ' . rtrim($vals, ', '); + return 'VALUES ' . \rtrim($vals, ', '); } /** @@ -548,6 +553,6 @@ class Grammar extends GrammarAbstract return ''; } - return 'SET ' . rtrim($vals, ', '); + return 'SET ' . \rtrim($vals, ', '); } }