From 9fa556539c79ac651cbf8755ffc33308803af9ff Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 21 Mar 2018 19:02:27 +0100 Subject: [PATCH 1/5] composer.json: update phinx. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c19dcaa..4515289 100644 --- a/composer.json +++ b/composer.json @@ -1,6 +1,6 @@ { "require": { - "robmorgan/phinx": "^0.6.2", + "robmorgan/phinx": "^0.9.2", "opauth/google": "^0.2.2", "opauth/twitter": "^0.3.1", "opauth/github": "^0.1.0" From ec539cfe7e3107cf36f3d807967c25e6fb6c68e6 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 21 Mar 2018 19:09:59 +0100 Subject: [PATCH 2/5] gitignore: do not ignore *.lock --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 146a914..8f0edd6 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,6 @@ app/cache/ node_modules/ /vendor -*.lock app/data/* app/config/conf.local.yml From 4be824a96204e3142690eb1a1fdf951d43364c5e Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 21 Mar 2018 19:10:16 +0100 Subject: [PATCH 3/5] adding composer.lock --- composer.lock | 676 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 676 insertions(+) create mode 100644 composer.lock diff --git a/composer.lock b/composer.lock new file mode 100644 index 0000000..711d59a --- /dev/null +++ b/composer.lock @@ -0,0 +1,676 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" + ], + "hash": "36a75ff648970b9639580a2cb7013090", + "content-hash": "ac20c7c56c417cb600cb228332de7513", + "packages": [ + { + "name": "opauth/github", + "version": "0.1.0", + "source": { + "type": "git", + "url": "https://github.com/opauth/github.git", + "reference": "9c4fe16dc6498b2c94f4c2a41ab93b0fe4b7fa73" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opauth/github/zipball/9c4fe16dc6498b2c94f4c2a41ab93b0fe4b7fa73", + "reference": "9c4fe16dc6498b2c94f4c2a41ab93b0fe4b7fa73", + "shasum": "" + }, + "require": { + "opauth/opauth": ">=0.4.0", + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "U-Zyn Chua", + "email": "chua@uzyn.com", + "homepage": "http://uzyn.com" + } + ], + "description": "GitHub authentication strategy for Opauth", + "homepage": "http://opauth.org", + "keywords": [ + "Authentication", + "auth", + "github" + ], + "time": "2012-07-23 06:13:59" + }, + { + "name": "opauth/google", + "version": "0.2.2", + "source": { + "type": "git", + "url": "https://github.com/opauth/google.git", + "reference": "35df77684c14acb346a8c3753ae3809852d1a47e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opauth/google/zipball/35df77684c14acb346a8c3753ae3809852d1a47e", + "reference": "35df77684c14acb346a8c3753ae3809852d1a47e", + "shasum": "" + }, + "require": { + "opauth/opauth": ">=0.2.0", + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "U-Zyn Chua", + "email": "chua@uzyn.com", + "homepage": "http://uzyn.com" + } + ], + "description": "Google strategy for Opauth", + "homepage": "http://opauth.org", + "keywords": [ + "Authentication", + "auth", + "google" + ], + "time": "2012-10-18 14:39:52" + }, + { + "name": "opauth/opauth", + "version": "0.4.5", + "source": { + "type": "git", + "url": "https://github.com/opauth/opauth.git", + "reference": "3f979012d0bdf2d447bb02b97f7f7d9f482c77e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opauth/opauth/zipball/3f979012d0bdf2d447bb02b97f7f7d9f482c77e8", + "reference": "3f979012d0bdf2d447bb02b97f7f7d9f482c77e8", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "suggest": { + "opauth/facebook": "Allows Facebook authentication", + "opauth/google": "Allows Google authentication", + "opauth/twitter": "Allows Twitter authentication" + }, + "type": "library", + "autoload": { + "classmap": [ + "lib/Opauth/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "U-Zyn Chua", + "email": "chua@uzyn.com", + "homepage": "http://uzyn.com" + } + ], + "description": "Multi-provider authentication framework for PHP", + "homepage": "http://opauth.org", + "keywords": [ + "Authentication", + "OpenId", + "auth", + "facebook", + "google", + "oauth", + "omniauth", + "twitter" + ], + "time": "2018-02-25 03:18:21" + }, + { + "name": "opauth/twitter", + "version": "0.3.2", + "source": { + "type": "git", + "url": "https://github.com/opauth/twitter.git", + "reference": "9c09fb3d714b8bf7b35ebc235346cf2feced69e3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/opauth/twitter/zipball/9c09fb3d714b8bf7b35ebc235346cf2feced69e3", + "reference": "9c09fb3d714b8bf7b35ebc235346cf2feced69e3", + "shasum": "" + }, + "require": { + "opauth/opauth": ">=0.2.0", + "php": ">=5.2.0" + }, + "type": "library", + "autoload": { + "psr-0": { + "": "." + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "U-Zyn Chua", + "email": "chua@uzyn.com", + "homepage": "http://uzyn.com" + } + ], + "description": "Twitter strategy for Opauth", + "homepage": "http://opauth.org", + "keywords": [ + "Authentication", + "auth", + "twitter" + ], + "time": "2017-03-28 05:03:36" + }, + { + "name": "psr/log", + "version": "1.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "shasum": "" + }, + "require": { + "php": ">=5.3.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "time": "2016-10-10 12:19:37" + }, + { + "name": "robmorgan/phinx", + "version": "0.9.2", + "source": { + "type": "git", + "url": "https://github.com/cakephp/phinx.git", + "reference": "e1698319ad55157c233b658c08f7a10617e797ca" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/cakephp/phinx/zipball/e1698319ad55157c233b658c08f7a10617e797ca", + "reference": "e1698319ad55157c233b658c08f7a10617e797ca", + "shasum": "" + }, + "require": { + "php": ">=5.4", + "symfony/config": "^2.8|^3.0|^4.0", + "symfony/console": "^2.8|^3.0|^4.0", + "symfony/yaml": "^2.8|^3.0|^4.0" + }, + "require-dev": { + "cakephp/cakephp-codesniffer": "^3.0", + "phpunit/phpunit": "^4.8.35|^5.7|^6.5" + }, + "bin": [ + "bin/phinx" + ], + "type": "library", + "autoload": { + "psr-4": { + "Phinx\\": "src/Phinx" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Woody Gilk", + "email": "woody.gilk@gmail.com", + "homepage": "http://shadowhand.me", + "role": "Developer" + }, + { + "name": "Rob Morgan", + "email": "robbym@gmail.com", + "homepage": "https://robmorgan.id.au", + "role": "Lead Developer" + }, + { + "name": "Richard Quadling", + "email": "rquadling@gmail.com", + "role": "Developer" + }, + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/phinx/graphs/contributors" + } + ], + "description": "Phinx makes it ridiculously easy to manage the database migrations for your PHP app.", + "homepage": "https://phinx.org", + "keywords": [ + "database", + "database migrations", + "db", + "migrations", + "phinx" + ], + "time": "2017-12-23 06:48:51" + }, + { + "name": "symfony/config", + "version": "v3.4.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/config.git", + "reference": "05e10567b529476a006b00746c5f538f1636810e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/config/zipball/05e10567b529476a006b00746c5f538f1636810e", + "reference": "05e10567b529476a006b00746c5f538f1636810e", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/filesystem": "~2.8|~3.0|~4.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.3", + "symfony/finder": "<3.3" + }, + "require-dev": { + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/event-dispatcher": "~3.3|~4.0", + "symfony/finder": "~3.3|~4.0", + "symfony/yaml": "~3.0|~4.0" + }, + "suggest": { + "symfony/yaml": "To use the yaml reference dumper" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Config\\": "" + }, + "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": "Symfony Config Component", + "homepage": "https://symfony.com", + "time": "2018-02-14 10:03:57" + }, + { + "name": "symfony/console", + "version": "v3.4.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/console.git", + "reference": "067339e9b8ec30d5f19f5950208893ff026b94f7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/console/zipball/067339e9b8ec30d5f19f5950208893ff026b94f7", + "reference": "067339e9b8ec30d5f19f5950208893ff026b94f7", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/polyfill-mbstring": "~1.0" + }, + "conflict": { + "symfony/dependency-injection": "<3.4", + "symfony/process": "<3.3" + }, + "require-dev": { + "psr/log": "~1.0", + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", + "symfony/process": "~3.3|~4.0" + }, + "suggest": { + "psr/log": "For using the console logger", + "symfony/event-dispatcher": "", + "symfony/lock": "", + "symfony/process": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "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": "Symfony Console Component", + "homepage": "https://symfony.com", + "time": "2018-02-26 15:46:28" + }, + { + "name": "symfony/debug", + "version": "v3.4.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/debug.git", + "reference": "9b1071f86e79e1999b3d3675d2e0e7684268b9bc" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/debug/zipball/9b1071f86e79e1999b3d3675d2e0e7684268b9bc", + "reference": "9b1071f86e79e1999b3d3675d2e0e7684268b9bc", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + }, + "require-dev": { + "symfony/http-kernel": "~2.8|~3.0|~4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Debug\\": "" + }, + "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": "Symfony Debug Component", + "homepage": "https://symfony.com", + "time": "2018-02-28 21:49:22" + }, + { + "name": "symfony/filesystem", + "version": "v3.4.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/filesystem.git", + "reference": "253a4490b528597aa14d2bf5aeded6f5e5e4a541" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/253a4490b528597aa14d2bf5aeded6f5e5e4a541", + "reference": "253a4490b528597aa14d2bf5aeded6f5e5e4a541", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Filesystem\\": "" + }, + "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": "Symfony Filesystem Component", + "homepage": "https://symfony.com", + "time": "2018-02-22 10:48:49" + }, + { + "name": "symfony/polyfill-mbstring", + "version": "v1.7.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-mbstring": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.7-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "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": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ], + "time": "2018-01-30 19:27:44" + }, + { + "name": "symfony/yaml", + "version": "v3.4.6", + "source": { + "type": "git", + "url": "https://github.com/symfony/yaml.git", + "reference": "6af42631dcf89e9c616242c900d6c52bd53bd1bb" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/yaml/zipball/6af42631dcf89e9c616242c900d6c52bd53bd1bb", + "reference": "6af42631dcf89e9c616242c900d6c52bd53bd1bb", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "conflict": { + "symfony/console": "<3.4" + }, + "require-dev": { + "symfony/console": "~3.4|~4.0" + }, + "suggest": { + "symfony/console": "For validating YAML files using the lint command" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Yaml\\": "" + }, + "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": "Symfony Yaml Component", + "homepage": "https://symfony.com", + "time": "2018-02-16 09:50:28" + } + ], + "packages-dev": [], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": [], + "prefer-stable": false, + "prefer-lowest": false, + "platform": [], + "platform-dev": [] +} From 3db175d542092f0140cfc6a7bd3327d4334ee43d Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 21 Mar 2018 19:12:16 +0100 Subject: [PATCH 4/5] adding phinx.php --- phinx.php | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 phinx.php diff --git a/phinx.php b/phinx.php new file mode 100644 index 0000000..e0fd89a --- /dev/null +++ b/phinx.php @@ -0,0 +1,31 @@ + [ + 'migrations' => 'app/migrations' + ], + 'environments' => [ + 'default_database' => 'main', + ] +]; + + +$db = $config->get('database'); +if ($db) { + $phinx['environments']['main'] = [ + 'adapter' => strtolower($db->adapter), + 'host' => $db->host, + 'user' => $db->username, + 'pass' => $db->password, + 'name' => $db->dbname, + 'charset' => $db->charset, + ]; +} + +return $phinx; From bf3d78da00ac066c446d2d24c29d894d8788d754 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Wed, 21 Mar 2018 19:12:35 +0100 Subject: [PATCH 5/5] adding base db migrations. --- .../20180321115827_create_user_table.php | 34 ++++++++++++++++ .../20180321131740_create_callback_table.php | 36 +++++++++++++++++ ...180321133533_create_request_meta_table.php | 39 +++++++++++++++++++ ...0321133715_create_request_object_table.php | 25 ++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 app/migrations/20180321115827_create_user_table.php create mode 100644 app/migrations/20180321131740_create_callback_table.php create mode 100644 app/migrations/20180321133533_create_request_meta_table.php create mode 100644 app/migrations/20180321133715_create_request_object_table.php diff --git a/app/migrations/20180321115827_create_user_table.php b/app/migrations/20180321115827_create_user_table.php new file mode 100644 index 0000000..c79e002 --- /dev/null +++ b/app/migrations/20180321115827_create_user_table.php @@ -0,0 +1,34 @@ +table('user'); + + $table->addColumn('username', 'string', [ + 'limit' => 50, + 'null' => false + ]); + + $table->addColumn('email', 'string', [ + 'limit' => 255, + 'null' => false + ]); + + $table->addColumn('status', 'enum', [ + 'null' => false, + 'default' => 'Active', + 'values' => [ 'Active', 'Deleted', 'Suspended'] + ]); + + $table->addColumn('password', 'string', [ + 'limit' => 255, + 'null' => true, + ]); + + $table->save(); + } +} diff --git a/app/migrations/20180321131740_create_callback_table.php b/app/migrations/20180321131740_create_callback_table.php new file mode 100644 index 0000000..9de7884 --- /dev/null +++ b/app/migrations/20180321131740_create_callback_table.php @@ -0,0 +1,36 @@ +table('callback'); + $table->addColumn('public_id', 'string', [ + 'length' => 12, + 'null' => false, + ])->addIndex('public_id', [ 'name' => 'UNIQUE_public_id', 'unique' => true ]); + + $table->addColumn('userid', 'integer', [ + 'null' => true, + ])->addForeignKey('userid', 'user', ['id'], [ 'constraint' => 'FK_user' ]); + + $table->addColumn('name', 'string', [ + 'length' => 64, + 'null' => false, + ]); + + $table->addColumn('created_at', 'timestamp', [ + 'default' => 'CURRENT_TIMESTAMP' + ]); + + $table->addColumn('last_request', 'timestamp', [ + 'default' => null, + 'null' => true + ]); + + $table->save(); + } +} diff --git a/app/migrations/20180321133533_create_request_meta_table.php b/app/migrations/20180321133533_create_request_meta_table.php new file mode 100644 index 0000000..124eb5f --- /dev/null +++ b/app/migrations/20180321133533_create_request_meta_table.php @@ -0,0 +1,39 @@ +table('request_meta'); + + $table->addColumn('callbackid', 'integer'); + $table->addForeignKey('callbackid', 'callback', [ 'id' ], + [ 'constraint' => 'FK_callback' ]); + + $table->addColumn('source_ip', 'string', [ + 'limit' => 50, + 'null' => true, + ]); + + $table->addColumn('method', 'enum', [ + 'null' => false, + 'default' => 'GET', + 'values' => [ 'GET', 'POST' ] + ]); + + $table->addColumn('uri', 'string', [ + 'limit' => 255, + 'null' => true, + ]); + + $table->addColumn('timestamp', 'timestamp', [ + 'default' => 'CURRENT_TIMESTAMP', + 'null' => false, + ]); + + $table->save(); + } +} diff --git a/app/migrations/20180321133715_create_request_object_table.php b/app/migrations/20180321133715_create_request_object_table.php new file mode 100644 index 0000000..29aea46 --- /dev/null +++ b/app/migrations/20180321133715_create_request_object_table.php @@ -0,0 +1,25 @@ +table('request_object'); + + $table->addForeignKey('id', 'request_meta', ['id'], + [ 'constraint' => 'FK_request_meta' ]); + + $table->addColumn('headers', 'blob', [ + 'null' => true, + ]); + + $table->addColumn('body', 'blob', [ + 'null' => true, + ]); + + $table->save(); + } +}