Added running of jobs

main
Jeroen De Meerleer 1 year ago
parent 4b06060929
commit 12380f36c4
Signed by: JeroenED
GPG Key ID: 28CCCB8F62BFADD6
  1. 2
      bootstrap.php
  2. 6
      composer.json
  3. 718
      composer.lock
  4. 3
      lib/Framework/Kernel.php
  5. 6
      public/index.php
  6. 69
      src/Command/DaemonCommand.php
  7. 15
      src/Command/RunCommand.php
  8. 87
      src/Repository/Job.php
  9. 11
      storage/database.sql
  10. 23
      webcron

@ -1,7 +1,7 @@
<?php
session_start();
require_once "../vendor/autoload.php";
require_once "vendor/autoload.php";
if( ini_get('safe_mode') ){
die("Cannot run in safe mode");

@ -8,14 +8,16 @@
}
],
"require": {
"guzzlehttp/guzzle": "^6",
"guzzlehttp/guzzle": "^7.0",
"twig/twig": "^2.14",
"doctrine/dbal": "^3.0",
"symfony/routing": "^5.2",
"symfony/dotenv": "^5.2",
"symfony/yaml": "^5.2",
"symfony/http-foundation": "^5.2",
"symfony/config": "^5.2"
"symfony/config": "^5.2",
"symfony/console": "^5.2",
"phpseclib/phpseclib": "^3.0"
},
"autoload": {
"psr-4": {

718
composer.lock generated

@ -4,20 +4,20 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "5a28828209d230b137b494fdfda60c15",
"content-hash": "220115977dffca9a54502ffb2b8d124a",
"packages": [
{
"name": "composer/package-versions-deprecated",
"version": "1.11.99.1",
"version": "1.11.99.2",
"source": {
"type": "git",
"url": "https://github.com/composer/package-versions-deprecated.git",
"reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6"
"reference": "c6522afe5540d5fc46675043d3ed5a45a740b27c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/7413f0b55a051e89485c5cb9f765fe24bb02a7b6",
"reference": "7413f0b55a051e89485c5cb9f765fe24bb02a7b6",
"url": "https://api.github.com/repos/composer/package-versions-deprecated/zipball/c6522afe5540d5fc46675043d3ed5a45a740b27c",
"reference": "c6522afe5540d5fc46675043d3ed5a45a740b27c",
"shasum": ""
},
"require": {
@ -61,7 +61,7 @@
"description": "Composer plugin that provides efficient querying for installed package versions (no runtime IO)",
"support": {
"issues": "https://github.com/composer/package-versions-deprecated/issues",
"source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.1"
"source": "https://github.com/composer/package-versions-deprecated/tree/1.11.99.2"
},
"funding": [
{
@ -77,20 +77,20 @@
"type": "tidelift"
}
],
"time": "2020-11-11T10:22:58+00:00"
"time": "2021-05-24T07:46:03+00:00"
},
{
"name": "doctrine/cache",
"version": "1.11.1",
"version": "1.11.2",
"source": {
"type": "git",
"url": "https://github.com/doctrine/cache.git",
"reference": "163074496dc7c3c7b8ccbf3d4376c0187424ed81"
"reference": "9c53086695937c50c47936ed86d96150ffbcf60d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/cache/zipball/163074496dc7c3c7b8ccbf3d4376c0187424ed81",
"reference": "163074496dc7c3c7b8ccbf3d4376c0187424ed81",
"url": "https://api.github.com/repos/doctrine/cache/zipball/9c53086695937c50c47936ed86d96150ffbcf60d",
"reference": "9c53086695937c50c47936ed86d96150ffbcf60d",
"shasum": ""
},
"require": {
@ -160,7 +160,7 @@
],
"support": {
"issues": "https://github.com/doctrine/cache/issues",
"source": "https://github.com/doctrine/cache/tree/1.11.1"
"source": "https://github.com/doctrine/cache/tree/1.11.2"
},
"funding": [
{
@ -176,7 +176,7 @@
"type": "tidelift"
}
],
"time": "2021-05-18T16:45:32+00:00"
"time": "2021-05-20T14:57:29+00:00"
},
{
"name": "doctrine/dbal",
@ -425,37 +425,44 @@
},
{
"name": "guzzlehttp/guzzle",
"version": "6.5.5",
"version": "7.3.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e"
"reference": "7008573787b430c1c1f650e3722d9bba59967628"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
"reference": "9d4290de1cfd701f38099ef7e183b64b4b7b0c5e",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/7008573787b430c1c1f650e3722d9bba59967628",
"reference": "7008573787b430c1c1f650e3722d9bba59967628",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.6.1",
"php": ">=5.5",
"symfony/polyfill-intl-idn": "^1.17.0"
"guzzlehttp/promises": "^1.4",
"guzzlehttp/psr7": "^1.7 || ^2.0",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.4.1",
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"php-http/client-integration-tests": "^3.0",
"phpunit/phpunit": "^8.5.5 || ^9.3.5",
"psr/log": "^1.1"
},
"suggest": {
"ext-curl": "Required for CURL handler support",
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.5-dev"
"dev-master": "7.3-dev"
}
},
"autoload": {
@ -475,6 +482,11 @@
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "Guzzle is a PHP HTTP client library",
@ -485,14 +497,34 @@
"framework",
"http",
"http client",
"psr-18",
"psr-7",
"rest",
"web service"
],
"support": {
"issues": "https://github.com/guzzle/guzzle/issues",
"source": "https://github.com/guzzle/guzzle/tree/6.5"
"source": "https://github.com/guzzle/guzzle/tree/7.3.0"
},
"time": "2020-06-16T21:01:06+00:00"
"funding": [
{
"url": "https://github.com/GrahamCampbell",
"type": "github"
},
{
"url": "https://github.com/Nyholm",
"type": "github"
},
{
"url": "https://github.com/alexeyshockov",
"type": "github"
},
{
"url": "https://github.com/gmponos",
"type": "github"
}
],
"time": "2021-03-23T11:33:13+00:00"
},
{
"name": "guzzlehttp/promises",
@ -624,6 +656,334 @@
},
"time": "2021-04-26T09:17:50+00:00"
},
{
"name": "paragonie/constant_time_encoding",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/paragonie/constant_time_encoding.git",
"reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/constant_time_encoding/zipball/f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c",
"reference": "f34c2b11eb9d2c9318e13540a1dbc2a3afbd939c",
"shasum": ""
},
"require": {
"php": "^7|^8"
},
"require-dev": {
"phpunit/phpunit": "^6|^7|^8|^9",
"vimeo/psalm": "^1|^2|^3|^4"
},
"type": "library",
"autoload": {
"psr-4": {
"ParagonIE\\ConstantTime\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com",
"role": "Maintainer"
},
{
"name": "Steve 'Sc00bz' Thomas",
"email": "steve@tobtu.com",
"homepage": "https://www.tobtu.com",
"role": "Original Developer"
}
],
"description": "Constant-time Implementations of RFC 4648 Encoding (Base-64, Base-32, Base-16)",
"keywords": [
"base16",
"base32",
"base32_decode",
"base32_encode",
"base64",
"base64_decode",
"base64_encode",
"bin2hex",
"encoding",
"hex",
"hex2bin",
"rfc4648"
],
"support": {
"email": "info@paragonie.com",
"issues": "https://github.com/paragonie/constant_time_encoding/issues",
"source": "https://github.com/paragonie/constant_time_encoding"
},
"time": "2020-12-06T15:14:20+00:00"
},
{
"name": "paragonie/random_compat",
"version": "v9.99.100",
"source": {
"type": "git",
"url": "https://github.com/paragonie/random_compat.git",
"reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/996434e5492cb4c3edcb9168db6fbb1359ef965a",
"reference": "996434e5492cb4c3edcb9168db6fbb1359ef965a",
"shasum": ""
},
"require": {
"php": ">= 7"
},
"require-dev": {
"phpunit/phpunit": "4.*|5.*",
"vimeo/psalm": "^1"
},
"suggest": {
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
},
"type": "library",
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Paragon Initiative Enterprises",
"email": "security@paragonie.com",
"homepage": "https://paragonie.com"
}
],
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
"keywords": [
"csprng",
"polyfill",
"pseudorandom",
"random"
],
"support": {
"email": "info@paragonie.com",
"issues": "https://github.com/paragonie/random_compat/issues",
"source": "https://github.com/paragonie/random_compat"
},
"time": "2020-10-15T08:29:30+00:00"
},
{
"name": "phpseclib/phpseclib",
"version": "3.0.8",
"source": {
"type": "git",
"url": "https://github.com/phpseclib/phpseclib.git",
"reference": "d9615a6fb970d9933866ca8b4036ec3407b020b6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d9615a6fb970d9933866ca8b4036ec3407b020b6",
"reference": "d9615a6fb970d9933866ca8b4036ec3407b020b6",
"shasum": ""
},
"require": {
"paragonie/constant_time_encoding": "^1|^2",
"paragonie/random_compat": "^1.4|^2.0|^9.99.99",
"php": ">=5.6.1"
},
"require-dev": {
"phing/phing": "~2.7",
"phpunit/phpunit": "^5.7|^6.0|^9.4",
"squizlabs/php_codesniffer": "~2.0"
},
"suggest": {
"ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.",
"ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.",
"ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.",
"ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations."
},
"type": "library",
"autoload": {
"files": [
"phpseclib/bootstrap.php"
],
"psr-4": {
"phpseclib3\\": "phpseclib/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Jim Wigginton",
"email": "terrafrost@php.net",
"role": "Lead Developer"
},
{
"name": "Patrick Monnerat",
"email": "pm@datasphere.ch",
"role": "Developer"
},
{
"name": "Andreas Fischer",
"email": "bantu@phpbb.com",
"role": "Developer"
},
{
"name": "Hans-Jürgen Petrich",
"email": "petrich@tronic-media.com",
"role": "Developer"
},
{
"name": "Graham Campbell",
"email": "graham@alt-three.com",
"role": "Developer"
}
],
"description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.",
"homepage": "http://phpseclib.sourceforge.net",
"keywords": [
"BigInteger",
"aes",
"asn.1",
"asn1",
"blowfish",
"crypto",
"cryptography",
"encryption",
"rsa",
"security",
"sftp",
"signature",
"signing",
"ssh",
"twofish",
"x.509",
"x509"
],
"support": {
"issues": "https://github.com/phpseclib/phpseclib/issues",
"source": "https://github.com/phpseclib/phpseclib/tree/3.0.8"
},
"funding": [
{
"url": "https://github.com/terrafrost",
"type": "github"
},
{
"url": "https://www.patreon.com/phpseclib",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib",
"type": "tidelift"
}
],
"time": "2021-04-19T03:20:48+00:00"
},
{
"name": "psr/container",
"version": "1.1.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/container.git",
"reference": "8622567409010282b7aeebe4bb841fe98b58dcaf"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/container/zipball/8622567409010282b7aeebe4bb841fe98b58dcaf",
"reference": "8622567409010282b7aeebe4bb841fe98b58dcaf",
"shasum": ""
},
"require": {
"php": ">=7.2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Psr\\Container\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common Container Interface (PHP FIG PSR-11)",
"homepage": "https://github.com/php-fig/container",
"keywords": [
"PSR-11",
"container",
"container-interface",
"container-interop",
"psr"
],
"support": {
"issues": "https://github.com/php-fig/container/issues",
"source": "https://github.com/php-fig/container/tree/1.1.1"
},
"time": "2021-03-05T17:36:06+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"reference": "2dfb5f6c5eff0e91e20e913f8c5452ed95b86621",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"support": {
"source": "https://github.com/php-fig/http-client/tree/master"
},
"time": "2020-06-29T06:28:15+00:00"
},
{
"name": "psr/http-message",
"version": "1.0.1",
@ -799,6 +1159,103 @@
],
"time": "2021-05-07T13:41:16+00:00"
},
{
"name": "symfony/console",
"version": "v5.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/console.git",
"reference": "864568fdc0208b3eba3638b6000b69d2386e6768"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/864568fdc0208b3eba3638b6000b69d2386e6768",
"reference": "864568fdc0208b3eba3638b6000b69d2386e6768",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php73": "^1.8",
"symfony/polyfill-php80": "^1.15",
"symfony/service-contracts": "^1.1|^2",
"symfony/string": "^5.1"
},
"conflict": {
"symfony/dependency-injection": "<4.4",
"symfony/dotenv": "<5.1",
"symfony/event-dispatcher": "<4.4",
"symfony/lock": "<4.4",
"symfony/process": "<4.4"
},
"provide": {
"psr/log-implementation": "1.0"
},
"require-dev": {
"psr/log": "~1.0",
"symfony/config": "^4.4|^5.0",
"symfony/dependency-injection": "^4.4|^5.0",
"symfony/event-dispatcher": "^4.4|^5.0",
"symfony/lock": "^4.4|^5.0",
"symfony/process": "^4.4|^5.0",
"symfony/var-dumper": "^4.4|^5.0"
},
"suggest": {
"psr/log": "For using the console logger",
"symfony/event-dispatcher": "",
"symfony/lock": "",
"symfony/process": ""
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\Console\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Eases the creation of beautiful and testable command line interfaces",
"homepage": "https://symfony.com",
"keywords": [
"cli",
"command line",
"console",
"terminal"
],
"support": {
"source": "https://github.com/symfony/console/tree/v5.2.8"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-05-11T15:45:21+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.4.0",
@ -1151,23 +1608,21 @@
"time": "2021-01-07T16:49:33+00:00"
},
{
"name": "symfony/polyfill-intl-idn",
"name": "symfony/polyfill-intl-grapheme",
"version": "v1.22.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-intl-idn.git",
"reference": "2d63434d922daf7da8dd863e7907e67ee3031483"
"url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/2d63434d922daf7da8dd863e7907e67ee3031483",
"reference": "2d63434d922daf7da8dd863e7907e67ee3031483",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/5601e09b69f26c1828b13b6bb87cb07cddba3170",
"reference": "5601e09b69f26c1828b13b6bb87cb07cddba3170",
"shasum": ""
},
"require": {
"php": ">=7.1",
"symfony/polyfill-intl-normalizer": "^1.10",
"symfony/polyfill-php72": "^1.10"
"php": ">=7.1"
},
"suggest": {
"ext-intl": "For best performance"
@ -1184,7 +1639,7 @@
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Intl\\Idn\\": ""
"Symfony\\Polyfill\\Intl\\Grapheme\\": ""
},
"files": [
"bootstrap.php"
@ -1196,30 +1651,26 @@
],
"authors": [
{
"name": "Laurent Bassin",
"email": "laurent@bassin.info"
},
{
"name": "Trevor Rowbotham",
"email": "trevor.rowbotham@pm.me"
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions",
"description": "Symfony polyfill for intl's grapheme_* functions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"idn",
"grapheme",
"intl",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-intl-idn/tree/v1.22.1"
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.22.1"
},
"funding": [
{
@ -1402,17 +1853,17 @@
"time": "2021-01-22T09:19:47+00:00"
},
{
"name": "symfony/polyfill-php72",
"name": "symfony/polyfill-php73",
"version": "v1.22.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php72.git",
"reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9"
"url": "https://github.com/symfony/polyfill-php73.git",
"reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9",
"reference": "cc6e6f9b39fe8075b3dabfbaf5b5f645ae1340c9",
"url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
"reference": "a678b42e92f86eca04b7fa4c0f6f19d097fb69e2",
"shasum": ""
},
"require": {
@ -1430,10 +1881,13 @@
},
"autoload": {
"psr-4": {
"Symfony\\Polyfill\\Php72\\": ""
"Symfony\\Polyfill\\Php73\\": ""
},
"files": [
"bootstrap.php"
],
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
@ -1450,7 +1904,7 @@
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions",
"description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
@ -1459,7 +1913,7 @@
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php72/tree/v1.22.1"
"source": "https://github.com/symfony/polyfill-php73/tree/v1.22.1"
},
"funding": [
{
@ -1649,6 +2103,168 @@
],
"time": "2021-05-16T13:07:46+00:00"
},
{
"name": "symfony/service-contracts",
"version": "v2.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
"reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/service-contracts/zipball/f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"reference": "f040a30e04b57fbcc9c6cbcf4dbaa96bd318b9bb",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"psr/container": "^1.1"
},
"suggest": {
"symfony/service-implementation": ""
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.4-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"psr-4": {
"Symfony\\Contracts\\Service\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Generic abstractions related to writing services",
"homepage": "https://symfony.com",
"keywords": [
"abstractions",
"contracts",
"decoupling",
"interfaces",
"interoperability",
"standards"
],
"support": {
"source": "https://github.com/symfony/service-contracts/tree/v2.4.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-04-01T10:43:52+00:00"
},
{
"name": "symfony/string",
"version": "v5.2.8",
"source": {
"type": "git",
"url": "https://github.com/symfony/string.git",
"reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db",
"reference": "01b35eb64cac8467c3f94cd0ce2d0d376bb7d1db",
"shasum": ""
},
"require": {
"php": ">=7.2.5",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-intl-grapheme": "~1.0",
"symfony/polyfill-intl-normalizer": "~1.0",
"symfony/polyfill-mbstring": "~1.0",
"symfony/polyfill-php80": "~1.15"
},
"require-dev": {
"symfony/error-handler": "^4.4|^5.0",
"symfony/http-client": "^4.4|^5.0",
"symfony/translation-contracts": "^1.1|^2",
"symfony/var-exporter": "^4.4|^5.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\String\\": ""
},
"files": [
"Resources/functions.php"
],
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an object-oriented API to strings and deals with bytes, UTF-8 code points and grapheme clusters in a unified way",
"homepage": "https://symfony.com",
"keywords": [
"grapheme",
"i18n",
"string",
"unicode",
"utf-8",
"utf8"
],
"support": {
"source": "https://github.com/symfony/string/tree/v5.2.8"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2021-05-10T14:56:10+00:00"
},
{
"name": "symfony/yaml",
"version": "v5.2.9",

@ -80,14 +80,13 @@ class Kernel
public function handle(): Response
{
$this->parseDotEnv($this->getProjectDir() . '/.env');
$this->router = new Router();
$this->router->parseRoutes($this->getConfigDir(), 'routes.yaml');
$request = $this->parseRequest();
return $this->router->route($request, $this);
}
private function parseDotEnv(string $path): void
public function parseDotEnv(string $path): void
{
$dotenv = new Dotenv();
$dotenv->loadEnv($path);

@ -3,13 +3,13 @@ error_reporting(E_ALL);
ini_set('display_errors', true);
use JeroenED\Framework\Kernel;
require_once '../bootstrap.php';
chdir(__DIR__ . '/..');
require_once 'bootstrap.php';
$kernel = new Kernel();
chdir(__DIR__ . '/..');
$kernel->setProjectDir(getcwd());
$kernel->setConfigDir(getcwd() . '/config/');
$kernel->setTemplateDir(getcwd() . '/templates/');
$kernel->parseDotEnv($kernel->getProjectDir() . '/.env');
$kernel->handle()->send();

@ -0,0 +1,69 @@
<?php
namespace JeroenED\Webcron\Command;
use JeroenED\Framework\Kernel;
use JeroenED\Webcron\Repository\Job;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class DaemonCommand extends Command
{
protected static $defaultName = 'daemon';
protected $kernel;
public function __construct(Kernel $kernel)
{
$this->kernel = $kernel;
parent::__construct();
}
protected function configure()
{
$this
->setDescription('The deamon slayer of webcron')
->setHelp('This command is the daemon process of webcron, enabling webcron to actually run jobs on time')
->addOption('time-limit', 't', InputOption::VALUE_REQUIRED, 'Time limit in seconds before stopping the daemon.');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$jobRepo = new Job($this->kernel->getDbCon());
$timelimit = $input->getOption('time-limit') ?? false;
if ($timelimit === false) {
$endofscript = false;
} elseif(is_numeric($timelimit)) {
$endofscript = time() + $timelimit;
} else {
throw new \InvalidArgumentException('Time limit has incorrect value');
}
while(1) {
if($endofscript !== false && time() > $endofscript) break;
$jobsToRun = $jobRepo->getJobsDue();
if(!empty($jobsToRun)) {
foreach($jobsToRun as $job) {
$jobRepo->setJobRunning($job, true);
$pid = -1;
//$pid = pcntl_fork();
if($pid == -1) {
$jobRepo->RunJob($job);
$jobRepo->setJobRunning($job, false);
} elseif ($pid == 0) {
$jobRepo->RunJob($job);
$jobRepo->setJobRunning($job, false);
exit;
}
}
}
}
$output->writeln('Ended after ' . $timelimit . ' seconds');
return Command::SUCCESS;
}
}

@ -0,0 +1,15 @@
<?php
namespace JeroenED\Webcron\Command;
use Symfony\Component\Console\Command\Command;
class RunCommand extends Command
{
protected static $defaultName = 'run';
protected function configure()
{
}
}

@ -6,6 +6,9 @@ namespace JeroenED\Webcron\Repository;
use DateTime;
use Doctrine\DBAL\Connection;
use GuzzleHttp\Client;
use phpseclib3\Crypt\PublicKeyLoader;
use phpseclib3\Net\SSH2;
class Job
{
@ -20,7 +23,7 @@ class Job
{
$jobsSql = "SELECT * FROM job";
$jobsStmt = $this->dbcon->prepare($jobsSql);
$jobsRslt = $jobsStmt->execute();
$jobsRslt = $jobsStmt->executeQuery();
$jobs = $jobsRslt->fetchAllAssociative();
foreach ($jobs as $key=>&$job) {
$job['data'] = json_decode($job['data'], true);
@ -28,6 +31,84 @@ class Job
return $jobs;
}
public function getJobsDue()
{
$jobsSql = "SELECT id FROM job WHERE nextrun <= :timestamp AND running = 0";
$jobsStmt = $this->dbcon->prepare($jobsSql);
$jobsRslt = $jobsStmt->executeQuery([':timestamp' => time()]);
$jobs = $jobsRslt->fetchAllAssociative();
$return = [];
foreach ($jobs as $job) {
$return[] = $job['id'];
}
return $return;
}
public function setJobRunning(int $job, bool $status): void
{
$jobsSql = "UPDATE job SET running = :status WHERE id = :id";
$jobsStmt = $this->dbcon->prepare($jobsSql);
$jobsStmt->executeQuery([':id' => $job, ':status' => $status ? 1 : 0]);
return;
}
public function runJob(int $job)
{
$job = $this->getJob($job, true);
if($job['data']['crontype'] == 'http') {
$client = new Client();
foreach($job['data']['vars'] as $key => $var) {
$job['data']['basicauth-username'] = str_replace('{' . $key . '}', $var['value'], $job['data']['basicauth-username']);
$job['data']['url'] = str_replace('{' . $key . '}', $var['value'], $job['data']['url']);
}
$url = $job['data']['url'];
$options['http_errors'] = false;
$options['auth'] = [$job['data']['basicauth-username'], $job['data']['basicauth-password']];
$res = $client->request('GET', $url, $options);
$exitcode = $res->getStatusCode();
$output = $res->getBody();
} elseif($job['data']['crontype'] == 'command') {
if($job['data']['hosttype'] == 'ssh') {
$ssh = new SSH2($job['data']['host']);
$key = null;
if(!empty($job['data']['ssh-privkey'])) {
if(!empty($job['data']['privkey-password'])) {
$key = PublicKeyLoader::load(base64_decode($job['data']['ssh-privkey']), $job['data']['privkey-password']);
} else {
$key = PublicKeyLoader::load(base64_decode($job['data']['ssh-privkey']));
}
} elseif (!empty($job['data']['privkey-password'])) {
$key = $job['data']['ssh-privkey'];
}
if (!$ssh->login($job['data']['user'], $key)) {
throw new \Exception('Login failed');
}
$output = $ssh->exec($job['data']['command']);
$exitcode = $ssh->getExitStatus();
}
}
// handling of response
$addRunSql = 'INSERT INTO run(job_id, exitcode, output) VALUES (:job_id, :exitcode, :output)';
$addRunStmt = $this->dbcon->prepare($addRunSql);
$addRunStmt->executeQuery([':job_id' => $job['id'], ':exitcode' => $exitcode, ':output' => $output]);
// setting nextrun to next run
$nextrun = $job['nextrun'];
do {
$nextrun = $nextrun + $job['interval'];
} while ($nextrun < time());
$addRunSql = 'UPDATE job SET nextrun = :nextrun WHERE id = :id';
$addRunStmt = $this->dbcon->prepare($addRunSql);
$addRunStmt->executeQuery([':id' => $job['id'], ':nextrun' => $nextrun]);
}
public function addJob(array $values)
{
if(empty($values['crontype']) ||
@ -40,10 +121,10 @@ class Job
$data = $this->prepareJob($values);
$data['data'] = json_encode($data['data']);
$addJobSql = "INSERT INTO job(name, data, interval, nextrun, lastrun) VALUES (:name, :data, :interval, :nextrun, :lastrun)";
$addJobSql = "INSERT INTO job(name, data, interval, nextrun, lastrun, running) VALUES (:name, :data, :interval, :nextrun, :lastrun, :running)";
$addJobStmt = $this->dbcon->prepare($addJobSql);
$addJobStmt->executeQuery([':name' => $data['name'], ':data' => $data['data'], ':interval' => $data['interval'], ':nextrun' => $data['nextrun'], ':lastrun' => $data['lastrun'], ]);
$addJobStmt->executeQuery([':name' => $data['name'], ':data' => $data['data'], ':interval' => $data['interval'], ':nextrun' => $data['nextrun'], ':lastrun' => $data['lastrun'], ':running' => 0]);
return ['success' => true, 'message' => 'Cronjob succesfully added'];
}

@ -5,7 +5,8 @@ CREATE TABLE job (
"data" TEXT NOT NULL,
interval INTEGER,
nextrun INTEGER,
lastrun INTEGER
lastrun INTEGER,
running INTEGER
);
@ -14,4 +15,12 @@ CREATE TABLE "user" (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
email TEXT(50) NOT NULL,
password TEXT(72) NOT NULL
);
-- run definition
CREATE TABLE run (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
job_id INTEGER NOT NULL,
exitcode TEXT NOT NULL,
output TEXT NOT NULL
);

@ -0,0 +1,23 @@
#!/usr/bin/env php
<?php
require_once 'bootstrap.php';
use JeroenED\Framework\Kernel;
use JeroenED\Webcron\Command\DaemonCommand;
use JeroenED\Webcron\Command\RunCommand;
use Symfony\Component\Console\Application;
$application = new Application();
$kernel = new Kernel();
chdir(__DIR__);
$kernel->setProjectDir(getcwd());
$kernel->setConfigDir(getcwd() . '/config/');
$kernel->setTemplateDir(getcwd() . '/templates/');
$kernel->parseDotEnv($kernel->getProjectDir() . '/.env');
$application->add(new RunCommand());
$application->add(new DaemonCommand($kernel));
$application->run();
Loading…
Cancel
Save