From 19c58cf70e0bf2765aa968e7bb93bf1a32aec175 Mon Sep 17 00:00:00 2001 From: alexweissman Date: Mon, 16 Oct 2017 21:44:27 -0400 Subject: [PATCH 001/237] Implement withRaw, withSum, withAvg, withMin, withMax See https://github.com/laravel/framework/pull/16815 --- CHANGELOG.md | 3 + app/defines.php | 2 +- app/sprinkles/core/src/Database/Builder.php | 134 +++++++++++++++++++- 3 files changed, 137 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d0af8c2d1..817fe8b06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Change Log +## v4.1.14-alpha +- Implement withRaw, withSum, withAvg, withMin, withMax (see https://github.com/laravel/framework/pull/16815) + ## v4.1.13-alpha - `ufTable`: Implement `rowTemplate` for customizing how rows are rendered (#787) - `ufTable`: Support for passing callbacks for column templates instead of Handlebars templates diff --git a/app/defines.php b/app/defines.php index 1db821937..b188f7eb1 100755 --- a/app/defines.php +++ b/app/defines.php @@ -3,7 +3,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.1.13-alpha'); +define('UserFrosting\VERSION', '4.1.14-alpha'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\DEBUG_CONFIG', false); diff --git a/app/sprinkles/core/src/Database/Builder.php b/app/sprinkles/core/src/Database/Builder.php index 8e27b7cc4..381eec717 100644 --- a/app/sprinkles/core/src/Database/Builder.php +++ b/app/sprinkles/core/src/Database/Builder.php @@ -9,9 +9,10 @@ use Illuminate\Database\Capsule\Manager as DB; use Illuminate\Database\Query\Builder as LaravelBuilder; +use Illuminate\Database\Query\Expression; /** - * UFBuilder Class + * UserFrosting's custom Builder Class * * The base Eloquent data model, from which all UserFrosting data classes extend. * @author Alex Weissman (https://alexanderweissman.com) @@ -81,6 +82,137 @@ public function orLike($field, $value) return $this->orWhere($field, 'LIKE', "%$value%"); } + /** + * Add subselect queries to average a column value of a relation. + * + * @param mixed $relation + * @param string $column + * @return $this + */ + public function withAvg($relation, $column) + { + return $this->withAggregate('avg', $relation, $column); + } + + /** + * Add subselect queries to count the relations. + * + * @param mixed $relations + * @return $this + */ + public function withCount($relations) + { + $relations = is_array($relations) ? $relations : func_get_args(); + + return $this->withRaw($relations, new Expression('count(*)'), 'count'); + } + + /** + * Add subselect queries to get max column value of a relation. + * + * @param mixed $relation + * @param string $column + * @return $this + */ + public function withMax($relation, $column) + { + return $this->withAggregate('max', $relation, $column); + } + + /** + * Add subselect queries to get min column value of a relation. + * + * @param mixed $relation + * @param string $column + * @return $this + */ + public function withMin($relation, $column) + { + return $this->withAggregate('min', $relation, $column); + } + + /** + * Add subselect queries to sum a column value of a relation. + * + * @param mixed $relation + * @param string $column + * @return $this + */ + public function withSum($relation, $column) + { + return $this->withAggregate('sum', $relation, $column); + } + + /** + * Add subselect queries to aggregate a column value of a relation. + * + * @param string $aggregate + * @param mixed $relation + * @param string $column + * @return $this + */ + protected function withAggregate($aggregate, $relation, $column) + { + return $this->withRaw($relation, new Expression($aggregate.'('.$this->query->getGrammar()->wrap($column).')'), $aggregate); + } + + /** + * Add subselect queries to aggregate all rows or a column value of a relation. + * + * @param array|mixed $relations + * @param mixed $expression + * @param string $suffix + * @return $this + */ + public function withRaw($relations, $expression, $suffix = null) + { + if (is_null($this->query->columns)) { + $this->query->select(['*']); + } + + $relations = is_array($relations) ? $relations : [$relations]; + + foreach ($this->parseWithRelations($relations) as $name => $constraints) { + // First we will determine if the name has been aliased using an "as" clause on the name + // and if it has we will extract the actual relationship name and the desired name of + // the resulting column. This allows multiple counts on the same relationship name. + $segments = explode(' ', $name); + + if (count($segments) == 3 && Str::lower($segments[1]) == 'as') { + list($name, $alias) = [$segments[0], $segments[2]]; + } + + $relation = $this->getHasRelationQuery($name); + + // Here we will get the relationship query and prepare to add it to the main query + // as a sub-select. First, we'll get the "has" query and use that to get the raw relation + // query. + $query = $relation->getRelationQuery( + $relation->getRelated()->newQuery(), $this, $expression + ); + + $query->callScope($constraints); + + $query->mergeModelDefinedRelationConstraints($relation->getQuery()); + + // Finally we will add the proper result column alias to the query and run the subselect + // statement against the query builder. If the alias has not been set, we will normalize + // the relation name then append _$suffix as the name. Then we will return the builder + // instance back to the developer for further constraint chaining that needs to take + // place on it. + if (isset($alias)) { + $column = snake_case($alias); + unset($alias); + } else { + $column = snake_case($name.'_'.(is_null($suffix) ? 'aggregate' : $suffix)); + } + + $this->selectSub($query->toBase(), $column); + } + + return $this; + } + /** * Execute the query as a "select" statement. * From f093184373a9be856e092e5ae2fd456112c596b4 Mon Sep 17 00:00:00 2001 From: alexweissman Date: Tue, 17 Oct 2017 13:02:59 -0400 Subject: [PATCH 002/237] move methods to custom Eloquent Builder class --- app/sprinkles/core/src/Database/Builder.php | 135 +----------------- .../core/src/Database/EloquentBuilder.php | 134 +++++++++++++++++ .../core/src/Database/Models/Model.php | 17 +++ .../src/ServicesProvider/ServicesProvider.php | 1 + 4 files changed, 153 insertions(+), 134 deletions(-) create mode 100644 app/sprinkles/core/src/Database/EloquentBuilder.php diff --git a/app/sprinkles/core/src/Database/Builder.php b/app/sprinkles/core/src/Database/Builder.php index 381eec717..eba79df6e 100644 --- a/app/sprinkles/core/src/Database/Builder.php +++ b/app/sprinkles/core/src/Database/Builder.php @@ -9,12 +9,10 @@ use Illuminate\Database\Capsule\Manager as DB; use Illuminate\Database\Query\Builder as LaravelBuilder; -use Illuminate\Database\Query\Expression; /** - * UserFrosting's custom Builder Class + * UserFrosting's custom Query Builder Class * - * The base Eloquent data model, from which all UserFrosting data classes extend. * @author Alex Weissman (https://alexanderweissman.com) */ class Builder extends LaravelBuilder @@ -82,137 +80,6 @@ public function orLike($field, $value) return $this->orWhere($field, 'LIKE', "%$value%"); } - /** - * Add subselect queries to average a column value of a relation. - * - * @param mixed $relation - * @param string $column - * @return $this - */ - public function withAvg($relation, $column) - { - return $this->withAggregate('avg', $relation, $column); - } - - /** - * Add subselect queries to count the relations. - * - * @param mixed $relations - * @return $this - */ - public function withCount($relations) - { - $relations = is_array($relations) ? $relations : func_get_args(); - - return $this->withRaw($relations, new Expression('count(*)'), 'count'); - } - - /** - * Add subselect queries to get max column value of a relation. - * - * @param mixed $relation - * @param string $column - * @return $this - */ - public function withMax($relation, $column) - { - return $this->withAggregate('max', $relation, $column); - } - - /** - * Add subselect queries to get min column value of a relation. - * - * @param mixed $relation - * @param string $column - * @return $this - */ - public function withMin($relation, $column) - { - return $this->withAggregate('min', $relation, $column); - } - - /** - * Add subselect queries to sum a column value of a relation. - * - * @param mixed $relation - * @param string $column - * @return $this - */ - public function withSum($relation, $column) - { - return $this->withAggregate('sum', $relation, $column); - } - - /** - * Add subselect queries to aggregate a column value of a relation. - * - * @param string $aggregate - * @param mixed $relation - * @param string $column - * @return $this - */ - protected function withAggregate($aggregate, $relation, $column) - { - return $this->withRaw($relation, new Expression($aggregate.'('.$this->query->getGrammar()->wrap($column).')'), $aggregate); - } - - /** - * Add subselect queries to aggregate all rows or a column value of a relation. - * - * @param array|mixed $relations - * @param mixed $expression - * @param string $suffix - * @return $this - */ - public function withRaw($relations, $expression, $suffix = null) - { - if (is_null($this->query->columns)) { - $this->query->select(['*']); - } - - $relations = is_array($relations) ? $relations : [$relations]; - - foreach ($this->parseWithRelations($relations) as $name => $constraints) { - // First we will determine if the name has been aliased using an "as" clause on the name - // and if it has we will extract the actual relationship name and the desired name of - // the resulting column. This allows multiple counts on the same relationship name. - $segments = explode(' ', $name); - - if (count($segments) == 3 && Str::lower($segments[1]) == 'as') { - list($name, $alias) = [$segments[0], $segments[2]]; - } - - $relation = $this->getHasRelationQuery($name); - - // Here we will get the relationship query and prepare to add it to the main query - // as a sub-select. First, we'll get the "has" query and use that to get the raw relation - // query. - $query = $relation->getRelationQuery( - $relation->getRelated()->newQuery(), $this, $expression - ); - - $query->callScope($constraints); - - $query->mergeModelDefinedRelationConstraints($relation->getQuery()); - - // Finally we will add the proper result column alias to the query and run the subselect - // statement against the query builder. If the alias has not been set, we will normalize - // the relation name then append _$suffix as the name. Then we will return the builder - // instance back to the developer for further constraint chaining that needs to take - // place on it. - if (isset($alias)) { - $column = snake_case($alias); - unset($alias); - } else { - $column = snake_case($name.'_'.(is_null($suffix) ? 'aggregate' : $suffix)); - } - - $this->selectSub($query->toBase(), $column); - } - - return $this; - } - /** * Execute the query as a "select" statement. * diff --git a/app/sprinkles/core/src/Database/EloquentBuilder.php b/app/sprinkles/core/src/Database/EloquentBuilder.php new file mode 100644 index 000000000..0e46d1787 --- /dev/null +++ b/app/sprinkles/core/src/Database/EloquentBuilder.php @@ -0,0 +1,134 @@ +withAggregate($relations, 'SUM'); + } + + /** + * Add subselect queries to max the relations. + * + * @param mixed $relations + * @return $this + */ + public function withMax($relations) + { + $relations = is_array($relations) ? $relations : func_get_args(); + + return $this->withAggregate($relations, 'MAX'); + } + + /** + * Add subselect queries to min the relations. + * + * @param mixed $relations + * @return $this + */ + public function withMin($relations) + { + $relations = is_array($relations) ? $relations : func_get_args(); + + return $this->withAggregate($relations, 'MIN'); + } + + /** + * Add subselect queries to min the relations. + * + * @param mixed $relations + * @return $this + */ + public function withAvg($relations) + { + $relations = is_array($relations) ? $relations : func_get_args(); + + return $this->withAggregate($relations, 'AVG'); + } + + /** + * use the MySQL aggregate functions including AVG COUNT, SUM, MAX and MIN. + * + * @param array $relations + * @param string $function + * @return $this + */ + public function withAggregate($relations, $function = 'COUNT') + { + if (is_null($this->query->columns)) { + $this->query->select([$this->query->from.'.*']); + } + + $function = Str::lower($function); + + foreach ($this->parseWithRelations($relations) as $name => $constraints) { + // First we will determine if the name has been aliased using an "as" clause on the name + // and if it has we will extract the actual relationship name and the desired name of + // the resulting column. This allows multiple counts on the same relationship name. + $segments = explode(' ', $name); + + unset($alias); + + if (count($segments) == 3 && Str::lower($segments[1]) == 'as') { + list($name, $alias) = [$segments[0], $segments[2]]; + } + + // set the default column as * or primary key + $column = ($function == 'count') ? '*' : $this->model->getKeyName(); + + if (Str::contains($name, ':')) { + list($name, $column) = explode(':', $name); + } + + $relation = $this->getRelationWithoutConstraints($name); + + $expression = new Expression($function.'('.$this->query->getGrammar()->wrap($column).')'); + + // Here we will get the relationship aggregate query and prepare to add it to the main query + // as a sub-select. First, we'll get the "has" query and use that to get the relation + // count query. We will normalize the relation name then append the aggregate type as the name. + $query = $relation->getRelationExistenceQuery( + $relation->getRelated()->newQuery(), + $this, + $expression + ); + + $query->callScope($constraints); + + $query->mergeConstraintsFrom($relation->getQuery()); + + // Finally we will add the proper result column alias to the query and run the subselect + // statement against the query builder. Then we will return the builder instance back + // to the developer for further constraint chaining that needs to take place on it. + $column = snake_case(isset($alias) ? $alias : $name).'_'.$function; + + $this->selectSub($query->toBase(), $column); + } + + return $this; + } +} diff --git a/app/sprinkles/core/src/Database/Models/Model.php b/app/sprinkles/core/src/Database/Models/Model.php index 1c18c2c85..0d020144c 100644 --- a/app/sprinkles/core/src/Database/Models/Model.php +++ b/app/sprinkles/core/src/Database/Models/Model.php @@ -94,6 +94,23 @@ public function store() return $this->id; } + /** + * Overrides Laravel's base Model to return our custom Eloquent builder object. + * + * @param \UserFrosting\Sprinkles\Core\Database\Builder $query + * @return \UserFrosting\Sprinkles\Core\Database\EloquentBuilder + */ + public function newEloquentBuilder($query) + { + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = static::$ci->classMapper; + + return $classMapper->createInstance( + 'eloquent_builder', + $query + ); + } + /** * Overrides Laravel's base Model to return our custom query builder object. * diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 0fb02b551..67697bfa3 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -188,6 +188,7 @@ public function register(ContainerInterface $container) $container['classMapper'] = function ($c) { $classMapper = new ClassMapper(); $classMapper->setClassMapping('query_builder', 'UserFrosting\Sprinkle\Core\Database\Builder'); + $classMapper->setClassMapping('eloquent_builder', 'UserFrosting\Sprinkle\Core\Database\EloquentBuilder'); $classMapper->setClassMapping('throttle', 'UserFrosting\Sprinkle\Core\Database\Models\Throttle'); return $classMapper; }; From 24f298bc5f91fb0e0edd3267950626a319e9e213 Mon Sep 17 00:00:00 2001 From: alexweissman Date: Tue, 17 Oct 2017 15:59:44 -0400 Subject: [PATCH 003/237] use ~ for column separator in withAggregate --- app/sprinkles/core/src/Database/EloquentBuilder.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/core/src/Database/EloquentBuilder.php b/app/sprinkles/core/src/Database/EloquentBuilder.php index 0e46d1787..00ceab8c7 100644 --- a/app/sprinkles/core/src/Database/EloquentBuilder.php +++ b/app/sprinkles/core/src/Database/EloquentBuilder.php @@ -100,8 +100,8 @@ public function withAggregate($relations, $function = 'COUNT') // set the default column as * or primary key $column = ($function == 'count') ? '*' : $this->model->getKeyName(); - if (Str::contains($name, ':')) { - list($name, $column) = explode(':', $name); + if (Str::contains($name, '~')) { + list($name, $column) = explode('~', $name); } $relation = $this->getRelationWithoutConstraints($name); From 8de19dae41e95af26918c1f6ef89e28132c5ae60 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Tue, 12 Dec 2017 17:59:30 +1100 Subject: [PATCH 004/237] Support npm as frontend vendor asset source (fixes #737) and other misc. changes - Duplicate frontend vendor packages are no longer downloaded (fixes #727). - Detect dependency conflicts between frontend vendor packages. - Fixed Portugese translations. - Improve URL reliability under docker. - Stopped bower from complaining about sudo when using containers like docker. - Deprecated `assetLoader` service. --- .gitignore | 3 + CHANGELOG.md | 11 + README.md | 2 +- app/defines.php | 8 +- app/sprinkles/account/bower.json | 24 - .../account/locale/pt_PT/messages.php | 1 - app/sprinkles/core/bower.json | 48 - app/sprinkles/core/bundle.config.json | 2 +- app/sprinkles/core/composer.json | 17 +- app/sprinkles/core/config/default.php | 1 + app/sprinkles/core/package.json | 26 + app/sprinkles/core/routes/routes.php | 2 +- .../core/src/Controller/CoreController.php | 21 - .../ServicesProvider/CoreServicesProvider.php | 86 +- app/sprinkles/core/src/Twig/CoreExtension.php | 3 +- app/sprinkles/core/src/Util/AssetLoader.php | 113 + .../core/src/Util/RawAssetBundles.php | 123 + build/build.php | 24 +- build/gulpfile.js | 199 +- build/package-lock.json | 4533 +++++++++++++++++ build/package.json | 28 +- 21 files changed, 5058 insertions(+), 217 deletions(-) delete mode 100644 app/sprinkles/account/bower.json delete mode 100644 app/sprinkles/core/bower.json create mode 100644 app/sprinkles/core/package.json create mode 100644 app/sprinkles/core/src/Util/AssetLoader.php create mode 100644 app/sprinkles/core/src/Util/RawAssetBundles.php create mode 100644 build/package-lock.json diff --git a/.gitignore b/.gitignore index 326b6e4ac..96360bcb1 100644 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,6 @@ public/css/min/* # Ignore personal config files (v0.3.x) app/config-userfrosting.php + +# Ignore vendor assets +app/assets/* \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a1bf4aa87..1a47baf42 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,16 @@ # Change Log +## v4.0.25-Alpha +- Support npm for frontend vendor assets, and deprecation of bower (#737) +- Duplicate frontend vendor assets are no longer downloaded (#727) +- Detect incompatibilites between frontend vendor assets (related to #727) +- Improved reliability of generated base URL, especially when using docker +- Fixed syntax error in Portugese translations +- Minimise verbosity of assets build scripts when not in 'dev' mode +- Fix to stop bower complaining about sudo when using docker +- The `assetLoader` service has been deprecated, and may be removed in the future. +- **Potential breaking change:** Some packages like `Handlebars` are organised differently at npm. If referencing vendor assets introduced by UF, make sure they are still correct. + ## v4.0.24-Alpha - Fixes to nginx config file, and add location block for LE acme challenge - Fix JS errors when `#alerts-page` is not present on a page diff --git a/README.md b/README.md index cb6d5f187..bf9ec7e78 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ Louis's a civil engineer in Montréal, Québec who also has a passion for coding ### Jordan Mele -Jordan's a developer at Mayvin Training and a student studying Computer Science at the University of Wollongong. His passion is creating software-based solutions to overcomplicated problems, without taking control away from the user. He's also Australian. +Jordan's a former developer of Mayvin Training and a student studying Computer Science at the University of Wollongong, Australia. His passion is creating software-based solutions to overcomplicated problems, while keeping the user in control. ### Mike Jacobs diff --git a/app/defines.php b/app/defines.php index 2e51f4dc7..df5f23fd6 100755 --- a/app/defines.php +++ b/app/defines.php @@ -3,7 +3,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.0.24-alpha'); +define('UserFrosting\VERSION', '4.0.25-alpha'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\DEBUG_CONFIG', false); @@ -21,6 +21,7 @@ // Composer's vendor directory define('UserFrosting\VENDOR_DIR', APP_DIR . '/vendor'); +// Directory names define('UserFrosting\APP_DIR_NAME', basename(__DIR__)); define('UserFrosting\ASSET_DIR_NAME', 'assets'); define('UserFrosting\BUILD_DIR_NAME', 'build'); @@ -35,3 +36,8 @@ define('UserFrosting\SRC_DIR_NAME', 'src'); define('UserFrosting\SPRINKLES_DIR_NAME', 'sprinkles'); define('UserFrosting\TEMPLATE_DIR_NAME', 'templates'); +define('UserFrosting\PUBLIC_DIR_NAME', 'public'); + +// Vendor asset directories +define('UserFrosting\NPM_ASSET_DIR', APP_DIR_NAME . DS . ASSET_DIR_NAME . DS . 'node_modules'); +define('UserFrosting\BOWER_ASSET_DIR', APP_DIR_NAME . DS . ASSET_DIR_NAME . DS . 'bower_components'); \ No newline at end of file diff --git a/app/sprinkles/account/bower.json b/app/sprinkles/account/bower.json deleted file mode 100644 index a801f6798..000000000 --- a/app/sprinkles/account/bower.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "core-assets", - "version": "0.0.1", - "homepage": "https://github.com/userfrosting", - "authors": [ - "ssnukala" - ], - "moduleType": [ - "node" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "assets/vendor", - "examples", - "demo-resources", - "demo", - "test", - "tests" - ], - "dependencies": {} -} \ No newline at end of file diff --git a/app/sprinkles/account/locale/pt_PT/messages.php b/app/sprinkles/account/locale/pt_PT/messages.php index 0acdb8ac1..c2391fb28 100644 --- a/app/sprinkles/account/locale/pt_PT/messages.php +++ b/app/sprinkles/account/locale/pt_PT/messages.php @@ -108,7 +108,6 @@ "PAGE" => "Obtenha um link para fazer reset à sua password.", "REQUEST_CANNED" => "Pedido de password esquecida foi cancelado.", "REQUEST_SENT" => "Se o email {{email}} corresponder a uma conta em nosso sistema, um link de redefinição de senha será enviado para {{email}}." - ], ], "RESET" => [ diff --git a/app/sprinkles/core/bower.json b/app/sprinkles/core/bower.json deleted file mode 100644 index d2c3ae7ee..000000000 --- a/app/sprinkles/core/bower.json +++ /dev/null @@ -1,48 +0,0 @@ -{ - "name": "core-assets", - "version": "0.0.1", - "homepage": "https://github.com/userfrosting", - "authors": [ - "ssnukala" - ], - "moduleType": [ - "node" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "assets/vendor", - "examples", - "demo-resources", - "demo", - "test", - "tests" - ], - "dependencies": { - "bootstrap": "^3.3.6", - "clipboard": "1.5.16", - "font-awesome": "4.7.0", - "handlebars": "3.0.3", - "jquery": ">= 2.2.4", - "jquery-ui": "jquery.ui#~1.11.4", - "jquery-validation": "~1.14.0", - "select2": "4.0.3", - "select2-bootstrap-theme": "0.1.0-beta.9", - "tablesorter": "jquery.tablesorter#2.28.5", - "accounting.js": "*", - "moment": "2.17.1", - "speakingurl": "11.0.0", - "icheck": "^1.0.1", - "jquery-slimscroll": "~1.3.8", - "fastclick": "^1.0.6", - "ionicons": "^2.0.1", - "urijs": "1.18.4" - }, - "resolutions": { - "jquery": ">= 2.2.4", - "bootstrap": "3.x", - "jquery-validation": "~1.14.0" - } -} diff --git a/app/sprinkles/core/bundle.config.json b/app/sprinkles/core/bundle.config.json index 739e028d0..5fc0fd69b 100644 --- a/app/sprinkles/core/bundle.config.json +++ b/app/sprinkles/core/bundle.config.json @@ -3,7 +3,7 @@ "js/main": { "scripts": [ "vendor/bootstrap/dist/js/bootstrap.js", - "vendor/handlebars/handlebars.js", + "vendor/handlebars/dist/handlebars.js", "vendor/jquery-validation/dist/jquery.validate.js", "vendor/jquery-validation/dist/additional-methods.js", "vendor/jquery-slimscroll/jquery.slimscroll.min.js", diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index b2a89f0e7..a56a4d73a 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -9,6 +9,19 @@ { "name": "Alexander Weissman", "homepage": "https://alexanderweissman.com" + }, + { + "name": "Louis Charette" + }, + { + "name": "Jordan Mele", + "email": "SiliconSoldier@outlook.com.au" + }, + { + "name": "Mike Jacobs" + }, + { + "name": "Srinivas Nukala" } ], "version": "4.0", @@ -27,12 +40,12 @@ "slim/twig-view": "^1.2", "symfony/http-foundation": "*", "twig/twig": "^1.18", - "userfrosting/assets": "~4.0.0", + "userfrosting/assets": ">=5", "userfrosting/config": "~4.0.0", "userfrosting/fortress": "~4.0.0", "userfrosting/i18n": "~4.0.1", "userfrosting/session": "~4.0.0", - "userfrosting/support": "~4.0.0", + "userfrosting/support": "^4.0.0", "vlucas/phpdotenv": "^2" }, "minimum-stability": "dev", diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 8e9dd467a..bb1103eee 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -146,6 +146,7 @@ 'title' => 'UserFrosting', // URLs 'uri' => [ + // 'base' settings are no longer used to generate the uri frequently used in Twig (site.uri.public). This is due to Slim doing a better job of figuring this out on its own. This key has been kept to ensure backwards compatibility. 'base' => [ 'host' => isset($_SERVER['SERVER_NAME']) ? trim($_SERVER['SERVER_NAME'], '/') : 'localhost', 'scheme' => empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https', diff --git a/app/sprinkles/core/package.json b/app/sprinkles/core/package.json new file mode 100644 index 000000000..1cbf62e88 --- /dev/null +++ b/app/sprinkles/core/package.json @@ -0,0 +1,26 @@ +{ + "private": true, + "dependencies": { + "bootstrap": "^3.3.6", + "clipboard": "^1.5.16", + "font-awesome": "^4.7.0", + "handlebars": "^3.0.3", + "jquery": ">=2.2.4", + "jquery-ui": "^1.12.0", + "jquery-validation": "~1.14.0", + "select2": "^4.0.3", + "select2-bootstrap-theme": "0.1.0-beta.9", + "tablesorter": "^2.28.5", + "accounting-js": "^1.1.1", + "moment": "^2.17.1", + "speakingurl": "^11.0.0", + "icheck": "^1.0.1", + "jquery-slimscroll": "~1.3.8", + "fastclick": "^1.0.6", + "ionicons": "^2.0.1", + "urijs": "^1.18.10" + }, + "resolutions": { + "optimist": "0.6.1" + } +} diff --git a/app/sprinkles/core/routes/routes.php b/app/sprinkles/core/routes/routes.php index 216afa93e..8792a785e 100755 --- a/app/sprinkles/core/routes/routes.php +++ b/app/sprinkles/core/routes/routes.php @@ -22,4 +22,4 @@ $app->get('/privacy', 'UserFrosting\Sprinkle\Core\Controller\CoreController:pagePrivacy'); -$app->get('/' . $config['assets.raw.path'] . '/{url:.+}', 'UserFrosting\Sprinkle\Core\Controller\CoreController:getAsset'); +$app->get('/' . $config['assets.raw.path'] . '/{url:.+}', 'UserFrosting\Assets\ServeAsset\SlimServeAsset:serveAsset'); diff --git a/app/sprinkles/core/src/Controller/CoreController.php b/app/sprinkles/core/src/Controller/CoreController.php index aed8bf1a2..1bdb94661 100644 --- a/app/sprinkles/core/src/Controller/CoreController.php +++ b/app/sprinkles/core/src/Controller/CoreController.php @@ -72,25 +72,4 @@ public function jsonAlerts($request, $response, $args) { return $response->withJson($this->ci->alerts->getAndClearMessages()); } - - /** - * Handle all requests for raw assets. - * Request type: GET - */ - public function getAsset($request, $response, $args) - { - // By starting this service, we ensure that the timezone gets set. - $config = $this->ci->config; - - $assetLoader = $this->ci->assetLoader; - - if (!$assetLoader->loadAsset($args['url'])) { - throw new NotFoundException($request, $response); - } - - return $response - ->withHeader('Content-Type', $assetLoader->getType()) - ->withHeader('Content-Length', $assetLoader->getLength()) - ->write($assetLoader->getContent()); - } } diff --git a/app/sprinkles/core/src/ServicesProvider/CoreServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/CoreServicesProvider.php index ee0dbb219..edd76d1d3 100755 --- a/app/sprinkles/core/src/ServicesProvider/CoreServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/CoreServicesProvider.php @@ -33,10 +33,10 @@ use Slim\Views\TwigExtension; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use UserFrosting\Assets\AssetBundleSchema; -use UserFrosting\Assets\AssetLoader; -use UserFrosting\Assets\AssetManager; -use UserFrosting\Assets\UrlBuilder\AssetUrlBuilder; -use UserFrosting\Assets\UrlBuilder\CompiledAssetUrlBuilder; +use UserFrosting\Assets\Assets; +use UserFrosting\Assets\PathTransformer\PrefixTransformer; +use UserFrosting\Assets\AssetBundles\GulpBundleAssetsCompiledBundles as CompiledAssetBundles; +use UserFrosting\Sprinkle\Core\Util\RawAssetBundles; use UserFrosting\I18n\MessageTranslator; use UserFrosting\Session\Session; use UserFrosting\Sprinkle\Core\Twig\CoreExtension; @@ -50,6 +50,7 @@ use UserFrosting\Sprinkle\Core\Throttle\ThrottleRule; use UserFrosting\Sprinkle\Core\Util\CheckEnvironment; use UserFrosting\Sprinkle\Core\Util\ClassMapper; +use UserFrosting\Sprinkle\Core\Util\AssetLoader; use UserFrosting\Support\Exception\BadRequestException; /** @@ -77,17 +78,18 @@ public function register(ContainerInterface $container) }; /** - * Asset loader service. - * + * Asset loader service + * * Loads assets from a specified relative location. * Assets are Javascript, CSS, image, and other files used by your site. + * + * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. */ $container['assetLoader'] = function ($c) { $basePath = \UserFrosting\APP_DIR . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME; $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; - $al = new AssetLoader($basePath, $pattern); - return $al; + return new AssetLoader($basePath, $pattern); }; /** @@ -99,35 +101,56 @@ public function register(ContainerInterface $container) $container['assets'] = function ($c) { $config = $c->config; $locator = $c->locator; + + // Hacky way to clean up locator paths. + $locatorPaths = []; + foreach ($locator->getPaths('assets') as $pathSet) { + foreach ($pathSet as $path) { + $locatorPaths[] = $path; + } + } // Load asset schema if ($config['assets.use_raw']) { $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; - $removePrefix = \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME; - $aub = new AssetUrlBuilder($locator, $baseUrl, $removePrefix, 'assets'); - - $as = new AssetBundleSchema($aub); - $as->loadRawSchemaFile($locator->findResource("sprinkles://core/" . $config['assets.raw.schema'], true, true)); - // Extend for loaded sprinkles $sprinkles = $c->sprinkleManager->getSprinkles(); + + $prefixTransformer = new PrefixTransformer(); + $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); + $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); + foreach ($sprinkles as $sprinkle) { + $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); + } + $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); + + // Load raw asset bundles for each Sprinkle. + + // Create asset bundle accessor with core as base. + $bundles = new RawAssetBundles($locator->findResource("sprinkles://core/" . $config['assets.raw.schema'], true, true)); + + // Extend asset bundle accessor for every subsequent sprinkle. + foreach ($c->sprinkleManager->getSprinkles() as $sprinkle) { $resource = $locator->findResource("sprinkles://$sprinkle/" . $config['assets.raw.schema'], true, true); if (file_exists($resource)) { - $as->loadRawSchemaFile($resource); + // Extend for bundles. + $bundles->extend($resource); } } + + // Add bundles to asset manager. + $assets->addAssetBundles($bundles); } else { $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; - $aub = new CompiledAssetUrlBuilder($baseUrl); + $assets = new Assets($locator, 'assets', $baseUrl); + $assets->overrideBasePath($locator->getBase() . '/public/assets'); - $as = new AssetBundleSchema($aub); - $as->loadCompiledSchemaFile($locator->findResource("build://" . $config['assets.compiled.schema'], true, true)); + // Load compiled asset bundle. + $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); } - $am = new AssetManager($aub, $as); - - return $am; + return $assets; }; /** @@ -208,17 +231,10 @@ public function register(ContainerInterface $container) // Construct base url from components, if not explicitly specified if (!isset($config['site.uri.public'])) { - $base_uri = $config['site.uri.base']; - - $public = new Uri( - $base_uri['scheme'], - $base_uri['host'], - $base_uri['port'], - $base_uri['path'] - ); + $uri = $c->request->getUri(); // Slim\Http\Uri likes to add trailing slashes when the path is empty, so this fixes that. - $config['site.uri.public'] = trim($public, '/'); + $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); } if (isset($config['display_errors'])) { @@ -235,6 +251,12 @@ public function register(ContainerInterface $container) date_default_timezone_set($config['timezone']); } + // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) + if (!$config['assets.use_raw']) { + $c->locator->resetScheme('assets'); + $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); + } + return $config; }; @@ -385,6 +407,10 @@ public function register(ContainerInterface $container) $locator->addPath('cache', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\CACHE_DIR_NAME); $locator->addPath('session', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\SESSION_DIR_NAME); $locator->addPath('sprinkles', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\SPRINKLES_DIR_NAME); + $locator->addPath('assets', 'vendor', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME . '/' . 'bower_components'); + $locator->addPath('assets', 'vendor', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME . '/' . 'node_modules'); + + // NOTE: 'assets://' scheme is reset to point to 'public/assets/' when application is in production mode. This occurs within the config service. // Use locator to initialize streams ReadOnlyStream::setLocator($locator); diff --git a/app/sprinkles/core/src/Twig/CoreExtension.php b/app/sprinkles/core/src/Twig/CoreExtension.php index 96f5f8b2c..007051d11 100755 --- a/app/sprinkles/core/src/Twig/CoreExtension.php +++ b/app/sprinkles/core/src/Twig/CoreExtension.php @@ -10,6 +10,7 @@ use Interop\Container\ContainerInterface; use UserFrosting\Sprinkle\Core\Util\Util; +use UserFrosting\Assets\AssetsTemplatePlugin; /** * Extends Twig functionality for the Core sprinkle. @@ -119,7 +120,7 @@ public function getGlobals() return [ 'site' => $site, - 'assets' => $this->services->assets + 'assets' => new AssetsTemplatePlugin($this->services->assets) ]; } } diff --git a/app/sprinkles/core/src/Util/AssetLoader.php b/app/sprinkles/core/src/Util/AssetLoader.php new file mode 100644 index 000000000..be76fd021 --- /dev/null +++ b/app/sprinkles/core/src/Util/AssetLoader.php @@ -0,0 +1,113 @@ +basePath = rtrim($basePath, "/\\") . '/'; + + $this->pattern = $pattern; + + $this->fullPath = ''; + } + + /** + * Compute the full filesystem path for the specified relative path (usually extracted from a URL). + * + * Also checks to make sure that the file actually exists. + * @param string $relativePath + * @return bool True if the file exists, false otherwise + */ + public function loadAsset($relativePath) + { + // 1. Remove any query string + $relativePath = preg_replace('/\?.*/', '', $relativePath); + + // 2. Normalize path, to prevent directory traversal + $relativePath = Util::normalizePath($relativePath); + + // 3. Check that the beginning of the path matches the allowed paths pattern + if (!preg_match($this->pattern, $relativePath)) { + return false; + } + + // 4. Build full path to file + $this->fullPath = $this->basePath . $relativePath; + + // Return false if file does not exist + if (!file_exists($this->fullPath)) { + return false; + } + + return true; + } + + /** + * Get the raw contents of the currently targeted file. + * + * @return string + */ + public function getContent() + { + return file_get_contents($this->fullPath); + } + + /** + * Get the length in bytes of the currently targeted file. + * + * @return int + */ + public function getLength() + { + return filesize($this->fullPath); + } + + /** + * Get the best-guess MIME type of the currently targeted file, based on the file extension. + * + * @return string + */ + public function getType() + { + return MimeType::detectByFilename($this->fullPath); + } +} \ No newline at end of file diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php new file mode 100644 index 000000000..cf978225d --- /dev/null +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -0,0 +1,123 @@ +readSchema($filePath); + + // Process bundles + if (isset($bundlesFile->bundle)) { + foreach ($bundlesFile->bundle as $bundleName => $bundle) { + // Get collision setting. + $collisionRule = (isset($bundle->options->sprinkle->onCollision) ?: 'replace'); + + // Handle CSS bundle if specified. + if (isset($bundle->styles)) { + // Attempt to add CSS bundle + try { + $standardisedBundle = $this->standardiseBundle($bundle->styles); + if (!array_key_exists($bundleName, $this->cssBundles)) { + $this->cssBundles[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { + case 'replace': + // Replaces the existing bundle. + $this->cssBundles[$bundleName] = $standardisedBundle; + break; + case 'merge': + // Merge with existing bundle. + foreach ($standardisedBundle as $assetPath) { + if (!in_array($assetPath, $this->cssBundles[$bundleName])) { + $this->cssBundles[$bundleName][] = $assetPath; + } + } + break; + case 'ignore': + break; + case 'error': + throw new \ErrorException("The bundle '$bundleName' is already defined."); + break; + default: + throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); + break; + } + } + } + catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing styles property for '$bundleName' for file '$filePath'", 0, $e); + } + } + + // Handle JS bundle if specified. + if (isset($bundle->scripts)) { + // Attempt to add JS bundle + try { + $standardisedBundle = $this->standardiseBundle($bundle->scripts); + if (!array_key_exists($bundleName, $this->jsBundles)) { + $this->jsBundles[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { + case 'replace': + // Replaces the existing bundle. + $this->jsBundles[$bundleName] = $standardisedBundle; + break; + case 'merge': + // Merge with existing bundle. + foreach ($standardisedBundle as $assetPath) { + if (!in_array($assetPath, $this->jsBundles[$bundleName])) { + $this->jsBundles[$bundleName][] = $assetPath; + } + } + break; + case 'ignore': + break; + case 'error': + throw new \ErrorException("The bundle '$bundleName' is already defined."); + break; + default: + throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); + break; + } + } + } + catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing scripts property for '$bundleName' for file '$filePath'", 0, $e); + } + } + } + } + } +} \ No newline at end of file diff --git a/build/build.php b/build/build.php index 31db46774..af5ee2e78 100644 --- a/build/build.php +++ b/build/build.php @@ -7,18 +7,24 @@ echo "/*******************************/\n/* UserFrosting's Build Assets */\n/*******************************/\n"; + $failCheck = 0; + // Install npm - passthru("npm install --prefix ../build"); + passthru("npm install", $failCheck); - // Install bower - passthru("npm run uf-assets-install --prefix ../build"); + // Check npm install succeeded. + if ($failCheck !== 0) { + echo PHP_EOL.PHP_EOL . "ERROR :: npm install failed."; + exit(1); + } + + // Install vendor assets + passthru("npm run uf-assets-install"); - // Test it did worked - $coreVendorFiles = glob(UserFrosting\APP_DIR . '/' . UserFrosting\SPRINKLES_DIR_NAME . "/core/assets/vendor/*"); - if (!$coreVendorFiles){ - echo PHP_EOL.PHP_EOL."ERROR :: NPM bundle failed. Directory '" . UserFrosting\APP_DIR . '/' . UserFrosting\SPRINKLES_DIR_NAME . "/core/assets/vendor/' is empty." .PHP_EOL; + // Check vendor asset installation succeeded. + if ($failCheck !== 0) { + echo PHP_EOL.PHP_EOL."ERROR :: Frontend asset installation failed."; exit(1); } else { - echo PHP_EOL."Assets install looks successful !"; - echo PHP_EOL.PHP_EOL; + echo PHP_EOL."Assets install looks successful !".PHP_EOL.PHP_EOL; } diff --git a/build/gulpfile.js b/build/gulpfile.js index 84f7cb6d4..6d7f262b3 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -1,28 +1,31 @@ -/* To build bundles... - 1. npm run uf-bundle-build - 2. npm run uf-bundle - 3. npm run uf-bundle-cleanup - - To get frontend vendor packages via bower - 1. npm run uf-assets-install - - To clean frontend vendor assets - 1. npm run uf-assets-clean -*/ -"use strict"; +'use strict'; + +// Load environment variables +require('dotenv').config({path: '../app/.env'}); + +/** + * Global dependencies + */ const gulp = require('gulp'); +const fs = require('fs-extra'); const del = require('del'); -const fs = require('fs'); -const shell = require('shelljs'); const plugins = require('gulp-load-plugins')(); +// Set up logging +let doILog = (process.env.UF_MODE == 'dev'); +let logger = (message) => { + if (doILog) { + console.log(message); + } +}; + const sprinklesDir = '../app/sprinkles'; // The Sprinkle load order from sprinkles.json const sprinkles = ['core'].concat(require(`${sprinklesDir}/sprinkles.json`)['base']); // The directory where the bundle task should place compiled assets. -// The names of assets in bundle.result.json will be specified relative to this path. +// The names of assets in bundle.result.json will be located relative to this path. const publicAssetsDir = '../public/assets/'; // name of the bundle file @@ -31,43 +34,117 @@ const bundleFile = 'bundle.config.json'; // Compiled bundle config file const bundleConfigFile = `./${bundleFile}`; -// Destination directory for vendor assets -const vendorAssetsDir = './assets/vendor'; - /** * Vendor asset task */ +gulp.task('assets-install', () => { + 'use strict'; -// Gulp task to install vendor packages via bower -gulp.task('bower-install', () => { - "use strict"; - shell.cd(`${sprinklesDir}`); - sprinkles.forEach((sprinkle) => { - if (fs.existsSync(`${sprinkle}/bower.json`)) { - console.log(`bower.json found in '${sprinkle}' Sprinkle, installing assets.`); - shell.cd(`${sprinkle}`); - shell.exec(`bower install --config.directory=${vendorAssetsDir}`); - shell.cd(`../`); + let mergePkg = require('@userfrosting/merge-package-dependencies'); + + // See if there are any yarn packages. + let yarnPaths = []; + for (let sprinkle of sprinkles) { + if (fs.existsSync(`../app/sprinkles/${sprinkle}/package.json`)) { + yarnPaths.push(`../app/sprinkles/${sprinkle}/package.json`); } - }); + } + if (yarnPaths.length > 0) { + // Yes there are! + + // Delete old package.json + del.sync('../app/assets/package.json', { force: true }); + + // Generate package.json + let yarnTemplate = {// Private makes sure it isn't published, and cuts out a lot of unnecessary fields. + private: true, + flat: true + }; + logger('\nMerging packages...\n'); + mergePkg.yarn(yarnTemplate, yarnPaths, '../app/assets/', doILog); + logger('\nMerge complete.\n'); + + // Yarn automatically removes extraneous packages. - return true; + // Perform installation. + logger('Installing npm/yarn assets...'); + let childProcess = require('child_process'); + childProcess.execSync('yarn install --flat --no-lockfile --non-interactive', { + cwd: '../app/assets', + preferLocal: true,// Local over PATH. + localDir: './node_modules/.bin', + stdio: doILog ? 'inherit' : '' + }); + } + else del.sync([ + '../app/assets/package.json', + '../app/assets/node_modules/' + ], { force: true }); + + // See if there are any bower packages. + let bowerPaths = []; + for (let sprinkle of sprinkles) { + // bower + if (fs.existsSync(`../app/sprinkles/${sprinkle}/bower.json`)) { + console.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`); + bowerPaths.push(`../app/sprinkles/${sprinkle}/bower.json`); + } + } + if (bowerPaths.length > 0) { + // Yes there are! + + // Delete old bower.json + del.sync('../app/assets/bower.json', { force: true }); + + // Generate bower.json + let bowerTemplate = { + name: 'uf-vendor-assets' + }; + logger('\nMerging packages...\n'); + mergePkg.bower(bowerTemplate, bowerPaths, '../app/assets/', doILog); + logger('\nMerge complete.\n'); + + let childProcess = require('child_process'); + + // Remove extraneous packages + childProcess.execSync('bower prune', { + cwd: '../app/assets', + preferLocal: true,// Local over PATH. + localDir: './node_modules/.bin', + stdio: doILog ? 'inherit' : '' + }); + + // Perform installation + childProcess.execSync('bower install -q --allow-root', { // --allow-root stops bower from complaining about being in 'sudo'. + cwd: '../app/assets', + preferLocal: true,// Local over PATH. + localDir: './node_modules/.bin', + stdio: doILog ? 'inherit' : '' + }); + // Yarn is able to output its completion. Bower... not so much. + logger('Done.\n'); + } + else del.sync([ + '../app/assets/bower.json', + '../app/assets/bower_components/' + ], { force: true }); }); + /** * Bundling tasks */ -// Executes bundleing tasks according to bundle.config.json files in each Sprinkle, as per Sprinkle load order. +// Executes bundling tasks according to bundle.config.json files in each Sprinkle, as per Sprinkle load order. // Respects bundle collision rules. gulp.task('bundle-build', () => { - "use strict"; + 'use strict'; let copy = require('recursive-copy'); let merge = require('merge-array-object'); let cleanup = (e) => { - "use strict"; + 'use strict'; // Delete temporary directory if exists - fs.rmdirSync("./temp"); + fs.rmdirSync('./temp'); // Delete created bundle.config.json file fs.unlinkSync(bundleConfigFile); // Propagate error @@ -78,7 +155,7 @@ gulp.task('bundle-build', () => { copy: [] }; sprinkles.forEach((sprinkle) => { - "use strict"; + 'use strict'; let location = `${sprinklesDir}/${sprinkle}/`; if (fs.existsSync(`${location}${bundleFile}`)) { let currentConfig = require(`${location}${bundleFile}`); @@ -125,20 +202,29 @@ gulp.task('bundle-build', () => { // Save bundle rules to bundle.config.json fs.writeFileSync(bundleConfigFile, JSON.stringify(config)); - // Copy all assets in order of Sprinkle load order. - let sprinkleAssets = [] - sprinkles.forEach((sprinkle) => { - "use strict"; - sprinkleAssets.push(`../app/sprinkles/${sprinkle}/assets/**/*`); - }); - // Gulp v4 src respects order, until it is released, use this alternative. - return plugins.srcOrderedGlobs(sprinkleAssets) - .pipe(plugins.copy('../public/assets/', {prefix: 5}));// And gulp.dest doesn't give us the control needed. + // Copy vendor assets (bower, then npm) + /** @todo Should really keep the garbage files out. A filter function can be passed to the copySync settings object. */ + let paths = [ + '../app/assets/bower_components/', + '../app/assets/node_modules/' + ]; + for (let path of paths) { + if (fs.pathExistsSync(path)) fs.copySync(path, `${publicAssetsDir}vendor/`, { overwrite: true }); + } + // Copy sprinkle assets + paths = []; + for (let sprinkle of sprinkles) { + paths.push(`../app/sprinkles/${sprinkle}/assets/`); + } + for (let path of paths) { + fs.copySync(path, '../public/assets/', { overwrite: true }); + } + return; }); // Execute gulp-bundle-assets gulp.task('bundle', () => { - "use strict"; + 'use strict'; return gulp.src(bundleConfigFile) .pipe(plugins.ufBundleAssets({ base: publicAssetsDir @@ -149,33 +235,28 @@ gulp.task('bundle', () => { .pipe(gulp.dest(publicAssetsDir)); }); + + /** * Clean up tasks */ gulp.task('public-clean', () => { - "use strict"; + 'use strict'; return del(publicAssetsDir, { force: true }); }); // Clean up temporary bundling files gulp.task('bundle-clean', () => { - "use strict"; + 'use strict'; return del(bundleConfigFile, { force: true }); }); -// Deletes assets fetched by bower-install -gulp.task('bower-clean', () => { - "use strict"; - return del(`${sprinklesDir}/*/assets/vendor`, { force: true }); +// Deletes assets fetched by assets-install +gulp.task('assets-clean', () => { + 'use strict'; + return del(['../app/assets/bower_components/', '../app/assets/node_modules/', '../app/assets/bower.json', '../app/assets/package.json'], { force: true }); }); // Deletes all generated, or acquired files. -gulp.task('clean', () => { - "use strict"; - del(publicAssetsDir, { force: true}); - del(bundleConfigFile, { force: true }); - del(`${sprinklesDir}/*/assets/vendor`, { force: true }); - - return true; -}) \ No newline at end of file +gulp.task('clean', ['public-clean', 'bundle-clean', 'assets-clean'], () => { }); \ No newline at end of file diff --git a/build/package-lock.json b/build/package-lock.json new file mode 100644 index 000000000..7d20b25e0 --- /dev/null +++ b/build/package-lock.json @@ -0,0 +1,4533 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@userfrosting/merge-package-dependencies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.1.0.tgz", + "integrity": "sha512-xgJ95NM2uhDWIzXMb6AjxIU9tJaclE5HhQEOArqSGQ34p1JqtuMzLNdESW+5vzqrenJvoToqp1a5wV4Oym1f4g==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "fs-extra": "4.0.2", + "lodash": "4.17.4", + "node-exceptions": "2.0.2", + "package-json-validator": "0.6.2", + "semver": "5.4.1", + "semver-intersect": "1.1.2" + } + }, + "accord": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/accord/-/accord-0.23.0.tgz", + "integrity": "sha1-JGjHjlZBLbqTEdOD+4c0UNKGfK8=", + "dev": true, + "requires": { + "convert-source-map": "1.5.0", + "fobject": "0.0.4", + "glob": "7.0.3", + "indx": "0.2.3", + "lodash": "4.11.2", + "resolve": "1.5.0", + "semver": "5.4.1", + "uglify-js": "2.8.29", + "when": "3.7.8" + }, + "dependencies": { + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "glob": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz", + "integrity": "sha1-CqI1kxpKlqwT1g/6wvuHe9btT1g=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "lodash": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.11.2.tgz", + "integrity": "sha1-1rQzixEKWOIdrlzrz9u/0rxM2zs=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-slice": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", + "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true, + "optional": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true, + "optional": true + }, + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "bluebird": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.3.5.tgz", + "integrity": "sha1-XudH8ce9lnZYtoOTZDCu51OVWjQ=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "bower": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.2.tgz", + "integrity": "sha1-rfU1KcjUrwLvJPuNU0HBQZ0z4vc=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "bufferstreams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", + "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "dev": true, + "requires": { + "commander": "2.8.1", + "source-map": "0.4.4" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "optional": true + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "dev": true + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-with-sourcemaps": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", + "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1" + } + }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "deap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.0.tgz", + "integrity": "sha1-sUi/gkMKJ2mbdIOgPra2dYW/yIg=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.3" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "detect-file": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "dev": true, + "requires": { + "fs-exists-sync": "0.1.0" + } + }, + "dotenv": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", + "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", + "dev": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "emitter-mixin": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/emitter-mixin/-/emitter-mixin-0.0.3.tgz", + "integrity": "sha1-WUjLKG8uSO3DslGnz8H3iDOW1lw=", + "dev": true + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "errno": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "dev": true, + "requires": { + "prr": "0.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "findup-sync": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "dev": true, + "requires": { + "detect-file": "0.1.0", + "is-glob": "2.0.1", + "micromatch": "2.3.11", + "resolve-dir": "0.1.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.1" + }, + "dependencies": { + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "fobject": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fobject/-/fobject-0.0.4.tgz", + "integrity": "sha1-g5nmuRBdLrjm353MQRI6FxaIrf4=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "semver": "5.4.1", + "when": "3.7.8" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "optional": true + }, + "fork-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "get-imports": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-imports/-/get-imports-1.0.0.tgz", + "integrity": "sha1-R8C07piTUWQsVJdxk79Pyqv1N48=", + "dev": true, + "requires": { + "array-uniq": "1.0.3", + "import-regex": "1.1.0" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true, + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.4", + "is-windows": "0.2.0", + "which": "1.3.0" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.0.4", + "liftoff": "2.3.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "gulp-clean-css": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-2.0.7.tgz", + "integrity": "sha1-2Go9haeQvsg+Pdbd+wPWWmKPm6A=", + "dev": true, + "requires": { + "clean-css": "3.4.28", + "gulp-util": "3.0.8", + "object-assign": "4.1.1", + "readable-stream": "2.3.3", + "vinyl-bufferstream": "1.0.1", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "gulp-coffee": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/gulp-coffee/-/gulp-coffee-2.3.2.tgz", + "integrity": "sha1-6FQTyVpvdpXqFg+1kMxXjz29pbE=", + "dev": true, + "requires": { + "coffee-script": "1.12.7", + "gulp-util": "3.0.8", + "merge": "1.2.0", + "through2": "0.6.5", + "vinyl-sourcemaps-apply": "0.1.4" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.1.4.tgz", + "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", + "dev": true, + "requires": { + "source-map": "0.1.43" + } + } + } + }, + "gulp-concat": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.5.2.tgz", + "integrity": "sha1-1kQ3LNwrPNtCGoqUHI104h2BXxQ=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.4", + "gulp-util": "3.0.8", + "through2": "0.6.5" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulp-concat-css": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-concat-css/-/gulp-concat-css-2.3.0.tgz", + "integrity": "sha1-TBWGEhqEEf9LLcRPz6TcdA6P4bY=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "lodash.defaults": "3.1.2", + "parse-import": "2.0.0", + "rework": "1.0.1", + "rework-import": "2.1.0", + "rework-plugin-url": "1.1.0", + "through2": "1.1.1" + }, + "dependencies": { + "through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "xtend": "4.0.1" + } + } + } + }, + "gulp-if": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.1.tgz", + "integrity": "sha1-VfPt+Czs389gNapdBoaXmqsNrCg=", + "dev": true, + "requires": { + "gulp-match": "1.0.3", + "ternary-stream": "2.0.1", + "through2": "2.0.3" + } + }, + "gulp-less": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/gulp-less/-/gulp-less-3.1.0.tgz", + "integrity": "sha1-xUwu4BTr5uE1v8sBadtN25NQbeY=", + "dev": true, + "requires": { + "accord": "0.23.0", + "gulp-util": "3.0.8", + "less": "2.7.3", + "object-assign": "4.1.1", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "gulp-load-plugins": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/gulp-load-plugins/-/gulp-load-plugins-1.5.0.tgz", + "integrity": "sha1-TEGffldk2aDjMGG6uWGPgbc9QXE=", + "dev": true, + "requires": { + "array-unique": "0.2.1", + "fancy-log": "1.3.0", + "findup-sync": "0.4.3", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "micromatch": "2.3.11", + "resolve": "1.5.0" + } + }, + "gulp-match": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", + "dev": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "gulp-order": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gulp-order/-/gulp-order-1.1.1.tgz", + "integrity": "sha1-C47wgzI1vtZfHvvHnGrtl7HbQek=", + "dev": true, + "requires": { + "minimatch": "0.2.14", + "through": "2.3.8" + }, + "dependencies": { + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "gulp-rev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gulp-rev/-/gulp-rev-4.0.0.tgz", + "integrity": "sha1-Zj2RhOdyJHsvJcSk5XE4h0LlXuk=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "object-assign": "2.1.1", + "rev-hash": "1.0.0", + "rev-path": "1.0.0", + "through2": "0.6.5", + "vinyl-file": "1.3.0" + }, + "dependencies": { + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulp-sourcemaps": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.5.2.tgz", + "integrity": "sha1-eW9v9pWklCFfPT1mqnrIU9fnNRE=", + "dev": true, + "requires": { + "convert-source-map": "1.5.0", + "graceful-fs": "3.0.11", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "gulp-streamify": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/gulp-streamify/-/gulp-streamify-0.0.5.tgz", + "integrity": "sha1-aF0gUSVSrFdlYktBMbSx7K3wDsE=", + "dev": true, + "requires": { + "gulp-util": "2.2.20", + "plexer": "0.0.2", + "readable-stream": "1.1.14" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "gulp-util": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", + "dev": true, + "requires": { + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "lodash._reinterpolate": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", + "dev": true + }, + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" + } + }, + "lodash.escape": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", + "dev": true, + "requires": { + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" + } + }, + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + }, + "lodash.template": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", + "dev": true, + "requires": { + "lodash._escapestringchar": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.defaults": "2.4.1", + "lodash.escape": "2.4.1", + "lodash.keys": "2.4.1", + "lodash.templatesettings": "2.4.1", + "lodash.values": "2.4.1" + } + }, + "lodash.templatesettings": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", + "dev": true, + "requires": { + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" + } + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "dev": true + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true, + "requires": { + "clone-stats": "0.0.1" + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-uf-bundle-assets": { + "version": "2.27.2", + "resolved": "https://registry.npmjs.org/gulp-uf-bundle-assets/-/gulp-uf-bundle-assets-2.27.2.tgz", + "integrity": "sha1-uET3POm9hOU5nV+rDeBcODXVyPg=", + "dev": true, + "requires": { + "bluebird": "3.3.5", + "duplexer2": "0.0.2", + "graceful-fs": "4.1.4", + "gulp": "3.9.1", + "gulp-clean-css": "2.0.7", + "gulp-coffee": "2.3.2", + "gulp-concat": "2.5.2", + "gulp-concat-css": "2.3.0", + "gulp-if": "2.0.1", + "gulp-less": "3.1.0", + "gulp-order": "1.1.1", + "gulp-rev": "4.0.0", + "gulp-sourcemaps": "1.5.2", + "gulp-streamify": "0.0.5", + "gulp-uglify": "1.5.3", + "gulp-util": "3.0.7", + "lazypipe": "0.2.3", + "lodash": "3.9.3", + "map-stream": "0.0.6", + "merge-stream": "0.1.7", + "mkdirp": "0.5.1", + "pretty-hrtime": "1.0.2", + "readable-stream": "2.0.0", + "through2": "2.0.1", + "vinyl": "1.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "graceful-fs": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz", + "integrity": "sha1-7widKIDwM7ARgjzlyPrnmNp3Xb0=", + "dev": true + }, + "gulp-util": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", + "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "1.0.12", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.1", + "vinyl": "0.5.3" + }, + "dependencies": { + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "lodash": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.9.3.tgz", + "integrity": "sha1-AVnoaDL+/8bWHYUrEqlTuZSWvTI=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz", + "integrity": "sha1-cMqW9NBiikQ7kYdY95QWqae8n6g=", + "dev": true + }, + "readable-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.0.tgz", + "integrity": "sha1-q24pLYrjku+IgVExBVTnB4/LOMo=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz", + "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=", + "dev": true, + "requires": { + "readable-stream": "2.0.0", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.1.1.tgz", + "integrity": "sha1-eUCIfu8JOB6zYmrEwPmrU9S35FA=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-uglify": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.3.tgz", + "integrity": "sha1-YKALOXWrpBhkQqSUl56d+j8T0NY=", + "dev": true, + "requires": { + "deap": "1.0.0", + "fancy-log": "1.3.0", + "gulp-util": "3.0.8", + "isobject": "2.1.0", + "through2": "2.0.3", + "uglify-js": "2.6.2", + "uglify-save-license": "0.4.1", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "uglify-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.2.tgz", + "integrity": "sha1-9QvoikLNOWpiUdxSqzcvccwS/vA=", + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "import-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/import-regex/-/import-regex-1.1.0.tgz", + "integrity": "sha1-pVxS5McFx2XKIQ6SQqBrvMiqf2Y=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indx": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", + "integrity": "sha1-Fdz1bunPZcAjTFE8J/vVgOcPvFA=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "interpret": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", + "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", + "dev": true + }, + "ip-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", + "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", + "dev": true + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "dev": true, + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "dev": true, + "requires": { + "is-unc-path": "0.1.2" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true, + "optional": true + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true, + "optional": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true, + "optional": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "junk": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.3.tgz", + "integrity": "sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazypipe": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/lazypipe/-/lazypipe-0.2.3.tgz", + "integrity": "sha1-RUtKvmW4+MP4ivI10AmLXdXcbk4=", + "dev": true, + "requires": { + "stream-combiner": "0.2.2" + } + }, + "less": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", + "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", + "dev": true, + "requires": { + "errno": "0.1.4", + "graceful-fs": "4.1.11", + "image-size": "0.5.5", + "mime": "1.4.1", + "mkdirp": "0.5.1", + "promise": "7.3.1", + "request": "2.81.0", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + } + } + }, + "liftoff": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "0.4.3", + "fined": "1.1.0", + "flagged-respawn": "0.3.2", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.mapvalues": "4.6.0", + "rechoir": "0.6.2", + "resolve": "1.5.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._createassigner": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", + "dev": true, + "requires": { + "lodash._bindcallback": "3.0.1", + "lodash._isiterateecall": "3.0.9", + "lodash.restparam": "3.6.1" + } + }, + "lodash._escapehtmlchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1" + } + }, + "lodash._escapestringchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._htmlescapes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", + "dev": true + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._reunescapedhtml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash._shimkeys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash.assign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", + "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._createassigner": "3.1.1", + "lodash.keys": "3.1.2" + } + }, + "lodash.defaults": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", + "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=", + "dev": true, + "requires": { + "lodash.assign": "3.2.0", + "lodash.restparam": "3.6.1" + } + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lodash.values": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", + "dev": true, + "requires": { + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-stream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.6.tgz", + "integrity": "sha1-0u9OuBGihkTHqJiZhcacL91JaCc=", + "dev": true + }, + "maximatch": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", + "integrity": "sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "merge": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", + "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", + "dev": true + }, + "merge-array-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/merge-array-object/-/merge-array-object-1.0.5.tgz", + "integrity": "sha1-uBfILEGnzgCr9u2CHNscbVM7bRk=", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "merge-stream": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-0.1.7.tgz", + "integrity": "sha1-Md664T+XN7oX97T74zwWV0yG/Hk=", + "dev": true, + "requires": { + "through2": "0.6.5" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true, + "optional": true + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "modify-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz", + "integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "natives": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", + "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "dev": true + }, + "node-exceptions": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-2.0.2.tgz", + "integrity": "sha512-nILccFLvnaOBoKZZtWfZipn/hlThZOT6UJOLX6SA3yLMYPcvLTIF26PXx73sPnAg45p05iYFYw2jvayNHz4rDA==", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.0.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "package-json-validator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.2.tgz", + "integrity": "sha512-B4eikrIIhxheXKkIW7GR6Se4mtqegZ/x8jUDh6hHW4jYBz9HFXUejpPEUAsuplxpDtVdPsXT3ZMRTH1HizJV1Q==", + "dev": true, + "requires": { + "optimist": "0.6.1" + } + }, + "parse-filepath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", + "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "dev": true, + "requires": { + "is-absolute": "0.2.6", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-import": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-import/-/parse-import-2.0.0.tgz", + "integrity": "sha1-KyR0Aw4AirmNt2xLy/TbWucwb18=", + "dev": true, + "requires": { + "get-imports": "1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true, + "optional": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "plexer": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/plexer/-/plexer-0.0.2.tgz", + "integrity": "sha1-Ij1YAGKKBkagCX0wq1doZqLzeE4=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "dev": true, + "requires": { + "asap": "2.0.6" + } + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true, + "optional": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.5.0" + } + }, + "recursive-copy": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/recursive-copy/-/recursive-copy-2.0.7.tgz", + "integrity": "sha1-JNuFxxKdj63uQC5UAM/PDLYPyjw=", + "dev": true, + "requires": { + "del": "2.2.2", + "emitter-mixin": "0.0.3", + "errno": "0.1.4", + "graceful-fs": "4.1.11", + "junk": "1.0.3", + "maximatch": "0.1.0", + "mkdirp": "0.5.1", + "pify": "2.3.0", + "promise": "7.3.1", + "slash": "1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true, + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "rev-hash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rev-hash/-/rev-hash-1.0.0.tgz", + "integrity": "sha1-lpk5Weqb+xxZsTrfAqwuNLs3NgM=", + "dev": true + }, + "rev-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rev-path/-/rev-path-1.0.0.tgz", + "integrity": "sha1-1My0NqwzcMRgcXXOiOr8XGXF1lM=", + "dev": true, + "requires": { + "modify-filename": "1.1.0" + } + }, + "rework": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", + "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", + "dev": true, + "requires": { + "convert-source-map": "0.3.5", + "css": "2.2.1" + } + }, + "rework-import": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rework-import/-/rework-import-2.1.0.tgz", + "integrity": "sha1-wm7StTFZrHvi7GDaIj74lgPB7x8=", + "dev": true, + "requires": { + "css": "2.2.1", + "globby": "2.1.0", + "parse-import": "2.0.0", + "url-regex": "3.2.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globby": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-2.1.0.tgz", + "integrity": "sha1-npGSvNM/Srak+JTl5+qLcTITxII=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "async": "1.5.2", + "glob": "5.0.15", + "object-assign": "3.0.0" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "rework-plugin-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/rework-plugin-function/-/rework-plugin-function-1.0.2.tgz", + "integrity": "sha1-Es5G+1sptdk1FGaD9rmM9J0jc7k=", + "dev": true, + "requires": { + "rework-visit": "1.0.0" + } + }, + "rework-plugin-url": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/rework-plugin-url/-/rework-plugin-url-1.1.0.tgz", + "integrity": "sha1-q1PosQV7nV7MHIJz/32xhgg3XEU=", + "dev": true, + "requires": { + "rework-plugin-function": "1.0.2" + } + }, + "rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", + "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "semver-intersect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.1.2.tgz", + "integrity": "sha1-sLKLV1Ggf/3QAuXsYGyS1XbMtWE=", + "dev": true, + "requires": { + "semver": "5.4.1" + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "optional": true, + "requires": { + "hoek": "2.16.3" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "through": "2.3.8" + } + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "ternary-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "fork-stream": "0.0.4", + "merge-stream": "1.0.1", + "through2": "2.0.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", + "dev": true + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url-regex": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", + "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", + "dev": true, + "requires": { + "ip-regex": "1.0.3" + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-bufferstream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", + "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=", + "dev": true, + "requires": { + "bufferstreams": "1.0.1" + } + }, + "vinyl-file": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-1.3.0.tgz", + "integrity": "sha1-qgVjTTqGe6kUR77bs0r8sm9E9uc=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "vinyl": "1.2.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + }, + "yarn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.3.2.tgz", + "integrity": "sha1-WTl2JYG1tN3NNBjA9r5C3zruGV8=", + "dev": true + } + } +} diff --git a/build/package.json b/build/package.json index 9a8f542c8..6cfae3c9b 100755 --- a/build/package.json +++ b/build/package.json @@ -1,32 +1,24 @@ { - "name": "@userfrosting/userfrosting", - "version": "4.0.0", - "description": "Build tool for UF 4.0", - "main": "index.js", - "repository": { - "type": "git", - "url": "https://github.com/userfrosting/userfrosting" - }, - "author": "Alex Weissman", - "license": "MIT", + "private": true, "devDependencies": { + "@userfrosting/merge-package-dependencies": "^1.1.0", + "bower": "^1.8.0", + "del": "^2.2.2", + "dotenv": "^4.0.0", + "fs-extra": "^4.0.0", "gulp": "^3.9.1", - "gulp-uf-bundle-assets": "^2.27.2", "gulp-load-plugins": "^1.4.0", + "gulp-uf-bundle-assets": "^2.27.2", "merge-array-object": "^1.0.3", "recursive-copy": "^2.0.5", - "del": "^2.2.2", - "shelljs": "^0.7.6", - "bower": "^1.8.0", - "gulp-src-ordered-globs": "^1.0.3", - "gulp-copy": "^1.0.0" + "yarn": "^1.3.2" }, "scripts": { "uf-bundle-build": "gulp bundle-build", "uf-bundle": "gulp bundle", + "uf-assets-install": "gulp assets-install", "uf-bundle-clean": "gulp bundle-clean", - "uf-assets-install": "gulp bower-install", - "uf-assets-clean": "gulp bower-clean", + "uf-assets-clean": "gulp assets-clean", "uf-public-clean": "gulp public-clean", "uf-clean": "gulp clean" } From cd4ca7980cd397f677e908ac0eb93abe4a28c544 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Wed, 13 Dec 2017 11:49:32 +1100 Subject: [PATCH 005/237] Merged 4.0, and ported for NPM frontend as necessary. --- .gitignore | 4 + CHANGELOG.md | 10 + README.md | 2 +- app/defines.php | 7 + app/sprinkles/account/bower.json | 24 - app/sprinkles/core/asset-bundles.json | 2 +- app/sprinkles/core/bower.json | 45 - app/sprinkles/core/composer.json | 15 +- app/sprinkles/core/config/default.php | 1 + app/sprinkles/core/package.json | 24 + app/sprinkles/core/routes/routes.php | 2 +- .../core/src/Controller/CoreController.php | 21 - .../src/ServicesProvider/ServicesProvider.php | 87 +- app/sprinkles/core/src/Twig/CoreExtension.php | 3 +- app/sprinkles/core/src/Util/AssetLoader.php | 113 + .../core/src/Util/RawAssetBundles.php | 123 + app/system/Bakery/Command/BuildAssets.php | 93 +- app/system/ServicesProvider.php | 2 + build/gulpfile.js | 204 +- build/package-lock.json | 4533 +++++++++++++++++ build/package.json | 28 +- 21 files changed, 5098 insertions(+), 245 deletions(-) delete mode 100644 app/sprinkles/account/bower.json delete mode 100644 app/sprinkles/core/bower.json create mode 100644 app/sprinkles/core/package.json create mode 100644 app/sprinkles/core/src/Util/AssetLoader.php create mode 100644 app/sprinkles/core/src/Util/RawAssetBundles.php create mode 100644 build/package-lock.json diff --git a/.gitignore b/.gitignore index ee30f1eee..61266a064 100644 --- a/.gitignore +++ b/.gitignore @@ -59,4 +59,8 @@ public/css/min/* # Ignore personal config files (v0.3.x) app/config-userfrosting.php +# Physical database storage for containers (?) app/database/userfrosting.db + +# Ignore vendor assets +app/assets/* diff --git a/CHANGELOG.md b/CHANGELOG.md index d0af8c2d1..1efe6aa8e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -148,6 +148,16 @@ - Use YAML as default format for request schema (#690) See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x documentation) for complete list of changes and breaking changes. +## v4.0.25-Alpha +- Support npm for frontend vendor assets, and deprecation of bower (#737) +- Duplicate frontend vendor assets are no longer downloaded (#727) +- Detect incompatibilites between frontend vendor assets (related to #727) +- Improved reliability of generated base URL, especially when using docker +- Fixed syntax error in Portugese translations +- Minimise verbosity of assets build scripts when not in 'dev' mode +- Fix to stop bower complaining about sudo when using docker +- The `assetLoader` service has been deprecated, and may be removed in the future. +- **Potential breaking change:** Some packages like `Handlebars` are organised differently at npm. If referencing vendor assets introduced by UF, make sure they are still correct. ## v4.0.24-Alpha - Fixes to nginx config file, and add location block for LE acme challenge diff --git a/README.md b/README.md index 92dbda83b..5a89a863f 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Louis's a civil engineer in Montréal, Québec who also has a passion for coding ### Jordan Mele -Jordan's a developer at Mayvin Training and a student studying Computer Science at the University of Wollongong. His passion is creating software-based solutions to overcomplicated problems, without taking control away from the user. He's also Australian. +Jordan's a former developer of Mayvin Training and a student studying Computer Science at the University of Wollongong, Australia. His passion is creating software-based solutions to overcomplicated problems, while keeping the user in control. ### Sarah Baghdadi diff --git a/app/defines.php b/app/defines.php index 1db821937..c787fad41 100755 --- a/app/defines.php +++ b/app/defines.php @@ -18,6 +18,7 @@ // The directory containing APP_DIR. Usually, this will contain the entire website. define('UserFrosting\ROOT_DIR', realpath(__DIR__ . '/..')); +// Directory names define('UserFrosting\APP_DIR_NAME', basename(__DIR__)); define('UserFrosting\BUILD_DIR_NAME', 'build'); define('UserFrosting\CACHE_DIR_NAME', 'cache'); @@ -46,3 +47,9 @@ define('UserFrosting\SRC_DIR_NAME', 'src'); define('UserFrosting\TEMPLATE_DIR_NAME', 'templates'); define('UserFrosting\FACTORY_DIR_NAME', 'factories'); +define('UserFrosting\PUBLIC_DIR_NAME', 'public'); + +// Full path to frontend vendor asset directories +define('UserFrosting\ASSET_DIR', APP_DIR_NAME . DS . ASSET_DIR_NAME); +define('UserFrosting\NPM_ASSET_DIR', ASSET_DIR . DS . 'node_modules'); +define('UserFrosting\BOWER_ASSET_DIR', ASSET_DIR . DS . 'bower_components'); diff --git a/app/sprinkles/account/bower.json b/app/sprinkles/account/bower.json deleted file mode 100644 index a801f6798..000000000 --- a/app/sprinkles/account/bower.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "core-assets", - "version": "0.0.1", - "homepage": "https://github.com/userfrosting", - "authors": [ - "ssnukala" - ], - "moduleType": [ - "node" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "assets/vendor", - "examples", - "demo-resources", - "demo", - "test", - "tests" - ], - "dependencies": {} -} \ No newline at end of file diff --git a/app/sprinkles/core/asset-bundles.json b/app/sprinkles/core/asset-bundles.json index 31b899573..5dfeac792 100644 --- a/app/sprinkles/core/asset-bundles.json +++ b/app/sprinkles/core/asset-bundles.json @@ -3,7 +3,7 @@ "js/main": { "scripts": [ "vendor/bootstrap/dist/js/bootstrap.js", - "vendor/handlebars/handlebars.js", + "vendor/handlebars/dist/handlebars.js", "vendor/jquery-validation/dist/jquery.validate.js", "vendor/jquery-validation/dist/additional-methods.js", "vendor/jquery-slimscroll/jquery.slimscroll.js", diff --git a/app/sprinkles/core/bower.json b/app/sprinkles/core/bower.json deleted file mode 100644 index 2cdeea183..000000000 --- a/app/sprinkles/core/bower.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "name": "core-assets", - "version": "0.0.1", - "homepage": "https://github.com/userfrosting", - "authors": [ - "ssnukala" - ], - "moduleType": [ - "node" - ], - "license": "MIT", - "ignore": [ - "**/.*", - "node_modules", - "bower_components", - "assets/vendor", - "examples", - "demo-resources", - "demo", - "test", - "tests" - ], - "dependencies": { - "bootstrap": "^3.3.6", - "clipboard": "1.5.16", - "font-awesome": "4.7.0", - "handlebars": "3.0.3", - "jquery": ">= 2.2.4", - "jquery-validation": "~1.14.0", - "select2": "4.0.4", - "tablesorter": "jquery.tablesorter#2.28", - "moment": "2.17.1", - "speakingurl": "11.0.0", - "icheck": "^1.0.1", - "jquery-slimscroll": "~1.3.8", - "fastclick": "^1.0.6", - "ionicons": "^2.0.1", - "urijs": "1.18.4" - }, - "resolutions": { - "jquery": ">= 2.2.4", - "bootstrap": "3.x", - "jquery-validation": "~1.14.0" - } -} diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index f94c48648..52d39c901 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -9,6 +9,19 @@ { "name": "Alexander Weissman", "homepage": "https://alexanderweissman.com" + }, + { + "name": "Louis Charette" + }, + { + "name": "Jordan Mele", + "email": "SiliconSoldier@outlook.com.au" + }, + { + "name": "Mike Jacobs" + }, + { + "name": "Srinivas Nukala" } ], "require": { @@ -27,7 +40,7 @@ "slim/twig-view": "^1.2", "symfony/http-foundation": "*", "twig/twig": "^1.18", - "userfrosting/assets": "~4.1.0", + "userfrosting/assets": ">=5", "userfrosting/config": "~4.1.0", "userfrosting/cache": "~4.1.0", "userfrosting/fortress": "~4.1.1", diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 505d5688b..245c5db6e 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -159,6 +159,7 @@ ], // URLs 'uri' => [ + // 'base' settings are no longer used to generate the uri frequently used in Twig (site.uri.public). This is due to Slim doing a better job of figuring this out on its own. This key has been kept to ensure backwards compatibility. 'base' => [ 'host' => isset($_SERVER['SERVER_NAME']) ? trim($_SERVER['SERVER_NAME'], '/') : 'localhost', 'scheme' => empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https', diff --git a/app/sprinkles/core/package.json b/app/sprinkles/core/package.json new file mode 100644 index 000000000..1235215a5 --- /dev/null +++ b/app/sprinkles/core/package.json @@ -0,0 +1,24 @@ +{ + "private": true, + "dependencies": { + "bootstrap": "^3.3.6", + "clipboard": "^1.5.16", + "font-awesome": "^4.7.0", + "handlebars": "^3.0.3", + "jquery": ">=2.2.4", + "jquery-ui": "^1.12.0", + "jquery-validation": "~1.14.0", + "select2": "^4.0.4", + "tablesorter": "^2.28.5", + "moment": "^2.17.1", + "speakingurl": "^11.0.0", + "icheck": "^1.0.1", + "jquery-slimscroll": "~1.3.8", + "fastclick": "^1.0.6", + "ionicons": "^2.0.1", + "urijs": "^1.18.4" + }, + "resolutions": { + "optimist": "0.6.1" + } +} diff --git a/app/sprinkles/core/routes/routes.php b/app/sprinkles/core/routes/routes.php index 3598b7ea7..a4bfc42d4 100755 --- a/app/sprinkles/core/routes/routes.php +++ b/app/sprinkles/core/routes/routes.php @@ -21,4 +21,4 @@ $app->get('/privacy', 'UserFrosting\Sprinkle\Core\Controller\CoreController:pagePrivacy'); -$app->get('/' . $config['assets.raw.path'] . '/{url:.+}', 'UserFrosting\Sprinkle\Core\Controller\CoreController:getAsset'); +$app->get('/' . $config['assets.raw.path'] . '/{url:.+}', 'UserFrosting\Assets\ServeAsset\SlimServeAsset:serveAsset'); diff --git a/app/sprinkles/core/src/Controller/CoreController.php b/app/sprinkles/core/src/Controller/CoreController.php index 0dd816537..bc1556be4 100644 --- a/app/sprinkles/core/src/Controller/CoreController.php +++ b/app/sprinkles/core/src/Controller/CoreController.php @@ -71,25 +71,4 @@ public function jsonAlerts($request, $response, $args) { return $response->withJson($this->ci->alerts->getAndClearMessages()); } - - /** - * Handle all requests for raw assets. - * Request type: GET - */ - public function getAsset($request, $response, $args) - { - // By starting this service, we ensure that the timezone gets set. - $config = $this->ci->config; - - $assetLoader = $this->ci->assetLoader; - - if (!$assetLoader->loadAsset($args['url'])) { - throw new NotFoundException($request, $response); - } - - return $response - ->withHeader('Content-Type', $assetLoader->getType()) - ->withHeader('Content-Length', $assetLoader->getLength()) - ->write($assetLoader->getContent()); - } } diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 0fb02b551..352ee0dac 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -29,15 +29,15 @@ use Slim\Views\TwigExtension; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use UserFrosting\Assets\AssetBundleSchema; -use UserFrosting\Assets\AssetLoader; -use UserFrosting\Assets\AssetManager; -use UserFrosting\Assets\UrlBuilder\AssetUrlBuilder; -use UserFrosting\Assets\UrlBuilder\CompiledAssetUrlBuilder; use UserFrosting\Cache\TaggableFileStore; use UserFrosting\Cache\MemcachedStore; use UserFrosting\Cache\RedisStore; use UserFrosting\Config\ConfigPathBuilder; use UserFrosting\I18n\LocalePathBuilder; +use UserFrosting\Assets\Assets; +use UserFrosting\Assets\PathTransformer\PrefixTransformer; +use UserFrosting\Assets\AssetBundles\GulpBundleAssetsCompiledBundles as CompiledAssetBundles; +use UserFrosting\Sprinkle\Core\Util\RawAssetBundles; use UserFrosting\I18n\MessageTranslator; use UserFrosting\Session\Session; use UserFrosting\Sprinkle\Core\Error\ExceptionHandlerManager; @@ -52,6 +52,7 @@ use UserFrosting\Sprinkle\Core\Twig\CoreExtension; use UserFrosting\Sprinkle\Core\Util\CheckEnvironment; use UserFrosting\Sprinkle\Core\Util\ClassMapper; +use UserFrosting\Sprinkle\Core\Util\AssetLoader; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\NotFoundException; use UserFrosting\Support\Repository\Loader\ArrayFileLoader; @@ -90,17 +91,18 @@ public function register(ContainerInterface $container) }; /** - * Asset loader service. - * + * Asset loader service + * * Loads assets from a specified relative location. * Assets are Javascript, CSS, image, and other files used by your site. + * + * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. */ $container['assetLoader'] = function ($c) { $basePath = \UserFrosting\SPRINKLES_DIR; $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; - $al = new AssetLoader($basePath, $pattern); - return $al; + return new AssetLoader($basePath, $pattern); }; /** @@ -112,38 +114,56 @@ public function register(ContainerInterface $container) $container['assets'] = function ($c) { $config = $c->config; $locator = $c->locator; + + // Hacky way to clean up locator paths. + $locatorPaths = []; + foreach ($locator->getPaths('assets') as $pathSet) { + foreach ($pathSet as $path) { + $locatorPaths[] = $path; + } + } // Load asset schema if ($config['assets.use_raw']) { $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; - $removePrefix = \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME; - $aub = new AssetUrlBuilder($locator, $baseUrl, $removePrefix, 'assets'); + + $sprinkles = $c->sprinkleManager->getSprinkleNames(); - $as = new AssetBundleSchema($aub); + $prefixTransformer = new PrefixTransformer(); + $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); + $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); - // Load Sprinkle assets - $sprinkles = $c->sprinkleManager->getSprinkleNames(); + foreach ($sprinkles as $sprinkle) { + $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); + } + $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); + + // Load raw asset bundles for each Sprinkle. - // TODO: move this out into PathBuilder and Loader classes in userfrosting/assets - // This would also allow us to define and load bundles in themes - $bundleSchemas = array_reverse($locator->findResources('sprinkles://' . $config['assets.raw.schema'], true, true)); + // Retrieve locations of raw asset bundle schemas that exist. + $bundleSchemas = $locator->findResources('sprinkles://' . $config['assets.raw.schema']); - foreach ($bundleSchemas as $schema) { - if (file_exists($schema)) { - $as->loadRawSchemaFile($schema); + // Load asset bundle schemas that exist. + if (array_key_exists(0, $bundleSchemas)) { + $bundles = new RawAssetBundles(array_shift($bundleSchemas)); + + foreach ($bundleSchemas as $bundleSchema) { + $bundles->extend($bundleSchema); } + + // Add bundles to asset manager. + $assets->addAssetBundles($bundles); } } else { $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; - $aub = new CompiledAssetUrlBuilder($baseUrl); + $assets = new Assets($locator, 'assets', $baseUrl); + $assets->overrideBasePath($locator->getBase() . '/public/assets'); - $as = new AssetBundleSchema($aub); - $as->loadCompiledSchemaFile($locator->findResource("build://" . $config['assets.compiled.schema'], true, true)); + // Load compiled asset bundle. + $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); } - $am = new AssetManager($aub, $as); - - return $am; + return $assets; }; /** @@ -216,17 +236,10 @@ public function register(ContainerInterface $container) // Construct base url from components, if not explicitly specified if (!isset($config['site.uri.public'])) { - $base_uri = $config['site.uri.base']; - - $public = new Uri( - $base_uri['scheme'], - $base_uri['host'], - $base_uri['port'], - $base_uri['path'] - ); + $uri = $c->request->getUri(); // Slim\Http\Uri likes to add trailing slashes when the path is empty, so this fixes that. - $config['site.uri.public'] = trim($public, '/'); + $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); } // Hacky fix to prevent sessions from being hit too much: ignore CSRF middleware for requests for raw assets ;-) @@ -238,6 +251,12 @@ public function register(ContainerInterface $container) $config->set('csrf.blacklist', $csrfBlacklist); + // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) + if (!$config['assets.use_raw']) { + $c->locator->resetScheme('assets'); + $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); + } + return $config; }; diff --git a/app/sprinkles/core/src/Twig/CoreExtension.php b/app/sprinkles/core/src/Twig/CoreExtension.php index 6a89d1297..f7d8f699b 100755 --- a/app/sprinkles/core/src/Twig/CoreExtension.php +++ b/app/sprinkles/core/src/Twig/CoreExtension.php @@ -9,6 +9,7 @@ use Interop\Container\ContainerInterface; use UserFrosting\Sprinkle\Core\Util\Util; +use UserFrosting\Assets\AssetsTemplatePlugin; /** * Extends Twig functionality for the Core sprinkle. @@ -118,7 +119,7 @@ public function getGlobals() return [ 'site' => $site, - 'assets' => $this->services->assets + 'assets' => new AssetsTemplatePlugin($this->services->assets) ]; } } diff --git a/app/sprinkles/core/src/Util/AssetLoader.php b/app/sprinkles/core/src/Util/AssetLoader.php new file mode 100644 index 000000000..be76fd021 --- /dev/null +++ b/app/sprinkles/core/src/Util/AssetLoader.php @@ -0,0 +1,113 @@ +basePath = rtrim($basePath, "/\\") . '/'; + + $this->pattern = $pattern; + + $this->fullPath = ''; + } + + /** + * Compute the full filesystem path for the specified relative path (usually extracted from a URL). + * + * Also checks to make sure that the file actually exists. + * @param string $relativePath + * @return bool True if the file exists, false otherwise + */ + public function loadAsset($relativePath) + { + // 1. Remove any query string + $relativePath = preg_replace('/\?.*/', '', $relativePath); + + // 2. Normalize path, to prevent directory traversal + $relativePath = Util::normalizePath($relativePath); + + // 3. Check that the beginning of the path matches the allowed paths pattern + if (!preg_match($this->pattern, $relativePath)) { + return false; + } + + // 4. Build full path to file + $this->fullPath = $this->basePath . $relativePath; + + // Return false if file does not exist + if (!file_exists($this->fullPath)) { + return false; + } + + return true; + } + + /** + * Get the raw contents of the currently targeted file. + * + * @return string + */ + public function getContent() + { + return file_get_contents($this->fullPath); + } + + /** + * Get the length in bytes of the currently targeted file. + * + * @return int + */ + public function getLength() + { + return filesize($this->fullPath); + } + + /** + * Get the best-guess MIME type of the currently targeted file, based on the file extension. + * + * @return string + */ + public function getType() + { + return MimeType::detectByFilename($this->fullPath); + } +} \ No newline at end of file diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php new file mode 100644 index 000000000..cf978225d --- /dev/null +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -0,0 +1,123 @@ +readSchema($filePath); + + // Process bundles + if (isset($bundlesFile->bundle)) { + foreach ($bundlesFile->bundle as $bundleName => $bundle) { + // Get collision setting. + $collisionRule = (isset($bundle->options->sprinkle->onCollision) ?: 'replace'); + + // Handle CSS bundle if specified. + if (isset($bundle->styles)) { + // Attempt to add CSS bundle + try { + $standardisedBundle = $this->standardiseBundle($bundle->styles); + if (!array_key_exists($bundleName, $this->cssBundles)) { + $this->cssBundles[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { + case 'replace': + // Replaces the existing bundle. + $this->cssBundles[$bundleName] = $standardisedBundle; + break; + case 'merge': + // Merge with existing bundle. + foreach ($standardisedBundle as $assetPath) { + if (!in_array($assetPath, $this->cssBundles[$bundleName])) { + $this->cssBundles[$bundleName][] = $assetPath; + } + } + break; + case 'ignore': + break; + case 'error': + throw new \ErrorException("The bundle '$bundleName' is already defined."); + break; + default: + throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); + break; + } + } + } + catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing styles property for '$bundleName' for file '$filePath'", 0, $e); + } + } + + // Handle JS bundle if specified. + if (isset($bundle->scripts)) { + // Attempt to add JS bundle + try { + $standardisedBundle = $this->standardiseBundle($bundle->scripts); + if (!array_key_exists($bundleName, $this->jsBundles)) { + $this->jsBundles[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { + case 'replace': + // Replaces the existing bundle. + $this->jsBundles[$bundleName] = $standardisedBundle; + break; + case 'merge': + // Merge with existing bundle. + foreach ($standardisedBundle as $assetPath) { + if (!in_array($assetPath, $this->jsBundles[$bundleName])) { + $this->jsBundles[$bundleName][] = $assetPath; + } + } + break; + case 'ignore': + break; + case 'error': + throw new \ErrorException("The bundle '$bundleName' is already defined."); + break; + default: + throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); + break; + } + } + } + catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing scripts property for '$bundleName' for file '$filePath'", 0, $e); + } + } + } + } + } +} \ No newline at end of file diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/system/Bakery/Command/BuildAssets.php index 055fa4378..3143ab1c8 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/system/Bakery/Command/BuildAssets.php @@ -63,11 +63,8 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->buildAssets(); } - // Test the result - $this->checkAssets(); - // If all went well and there's no fatal errors, we are successful - $this->io->success("Assets install looks successful"); + $this->io->success("Assets install looks successful, check output for specifics"); } /** @@ -84,8 +81,14 @@ protected function npmInstall() // Temporarily change the working directory so we can install npm dependencies $wd = getcwd(); chdir($this->buildPath); - passthru("npm install"); + $exitCode = 0; + passthru("npm install", $exitCode); chdir($wd); + + if ($exitCode !== 0) { + $this->io->error("npm dependency installation has failed"); + exit(1); + } } /** @@ -96,9 +99,22 @@ protected function npmInstall() */ protected function assetsInstall() { - $this->io->section("Installing assets bundles"); + $this->io->section("Installing frontend vendor assets"); $this->io->writeln("> npm run uf-assets-install"); - passthru("npm run uf-assets-install --prefix " . $this->buildPath); + + // Temporarily change the working directory (more reliable than --prefix npm switch) + $wd = getcwd(); + chdir($this->buildPath); + $exitCode = 0; + passthru("npm run uf-assets-install", $exitCode); + chdir($wd); + + if ($exitCode !== 0) { + $this->io->error("assets installation has failed"); + exit(1); + } + + return $exitCode; } /** @@ -111,42 +127,36 @@ protected function buildAssets() { $this->io->section("Building assets for production"); - $this->io->writeln("> npm run uf-bundle-build"); - passthru("npm run uf-bundle-build --prefix " . $this->buildPath); + // Temporarily change the working directory (more reliable than --prefix npm switch) + $wd = getcwd(); + chdir($this->buildPath); - $this->io->writeln("> npm run uf-bundle"); - passthru("npm run uf-bundle --prefix " . $this->buildPath); + $exitCode = 0; - $this->io->writeln("> npm run uf-bundle-clean"); - passthru("npm run uf-bundle-clean --prefix " . $this->buildPath); - } - - /** - * Check that the assets where installed in the core sprinkles - * - * @access protected - * @return void - */ - protected function checkAssets() - { - $this->io->section("Testing assets installation"); - - // Get path and vendor files - $vendorPath = \UserFrosting\SPRINKLES_DIR . "/core/assets/vendor/*"; - $coreVendorFiles = glob($vendorPath); + $this->io->writeln("> npm run uf-bundle-build"); + passthru("npm run uf-bundle-build", $exitCode); - if (!$coreVendorFiles){ - $this->io->error("Assets installation seems to have failed. Directory `$vendorPath` is empty, but it shouldn't be. Check the above log for any errors."); + if ($exitCode !== 0) { + $this->io->error("bundling preparation has failed"); exit(1); } - // Check that `bundle.result.json` is present in production mode - $config = $this->ci->config; - $resultFile = \UserFrosting\ROOT_DIR . \UserFrosting\DS . \UserFrosting\BUILD_DIR_NAME . \UserFrosting\DS . $config['assets.compiled.schema']; - if ($this->isProduction() && !file_exists($resultFile)) { - $this->io->error("Assets building seems to have failed. File `$resultFile` not found. This file is required for production envrionement. Check the above log for any errors."); + $this->io->writeln("> npm run uf-bundle"); + passthru("npm run uf-bundle"); + + if ($exitCode !== 0) { + $this->io->error("bundling has failed"); exit(1); } + + if ($exitCode !== 0) $this->io->warning("bundling may have failed, check output"); + + $this->io->writeln("> npm run uf-bundle-clean"); + passthru("npm run uf-bundle-clean"); + + if ($exitCode !== 0) $this->io->warning("bundling cleanup has failed, which while unusual shouldn't cause any problems"); + + chdir($wd); } /** @@ -160,7 +170,18 @@ protected function clean() { $this->io->section("Cleaning cached data"); $this->io->writeln("> npm run uf-clean"); - passthru("npm run uf-clean --prefix " . $this->buildPath); + + // Temporarily change the working directory (more reliable than --prefix npm switch) + $wd = getcwd(); + chdir($this->buildPath); + $exitCode = 0; + passthru("npm run uf-clean", $exitCode); + chdir($wd); + + if ($exitCode !== 0) { + $this->io->error("Failed to clean cached data"); + exit(1); + } } /** diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 6286bc0c7..7bd1c5f32 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -49,6 +49,8 @@ public function register(ContainerInterface $container) $locator->addPath('log', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\LOG_DIR_NAME); $locator->addPath('cache', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\CACHE_DIR_NAME); $locator->addPath('session', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\SESSION_DIR_NAME); + $locator->addPath('assets', 'vendor', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME . '/' . 'bower_components'); + $locator->addPath('assets', 'vendor', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME . '/' . 'node_modules'); // Use locator to initialize streams ReadOnlyStream::setLocator($locator); diff --git a/build/gulpfile.js b/build/gulpfile.js index 832f7de02..b55851f2b 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -1,30 +1,32 @@ -/* To build bundles... - 1. npm run uf-bundle-build - 2. npm run uf-bundle - 3. npm run uf-bundle-clean - - To get frontend vendor packages via bower - 1. npm run uf-assets-install - - To clean frontend vendor assets - 1. npm run uf-assets-clean -*/ -"use strict"; +'use strict'; + +// Load environment variables +require('dotenv').config({path: '../app/.env'}); + +/** + * Global dependencies + */ const gulp = require('gulp'); +const fs = require('fs-extra'); const del = require('del'); -const fs = require('fs'); -const shell = require('shelljs'); const plugins = require('gulp-load-plugins')(); -const sprinklesDir = '../app/sprinkles/'; +// Set up logging +let doILog = (process.env.UF_MODE == 'dev'); +let logger = (message) => { + if (doILog) { + console.log(message); + } +}; +const sprinklesDir = '../app/sprinkles'; const sprinklesSchemaPath = '../app/sprinkles.json'; // The Sprinkle load order from sprinkles.json -const sprinkles = ['core'].concat(require(`${sprinklesSchemaPath}`)['base']); +const sprinkles = require(`${sprinklesSchemaPath}`)['base']; -// The directory where the bundle task should place compiled assets. -// The names of assets in bundle.result.json will be specified relative to this path. +// The directory where the bundle task should place compiled assets. +// The names of assets in bundle.result.json will be located relative to this path. const publicAssetsDir = '../public/assets/'; // name of the bundle file @@ -33,43 +35,117 @@ const bundleFile = 'asset-bundles.json'; // Compiled bundle config file const bundleConfigFile = `./${bundleFile}`; -// Destination directory for vendor assets -const vendorAssetsDir = './assets/vendor'; - /** * Vendor asset task */ +gulp.task('assets-install', () => { + 'use strict'; -// Gulp task to install vendor packages via bower -gulp.task('bower-install', () => { - "use strict"; - shell.cd(`${sprinklesDir}`); - sprinkles.forEach((sprinkle) => { - if (fs.existsSync(`${sprinkle}/bower.json`)) { - console.log(`bower.json found in '${sprinkle}' Sprinkle, installing assets.`); - shell.cd(`${sprinkle}`); - shell.exec(`bower install --config.directory=${vendorAssetsDir}`); - shell.cd(`../`); + let mergePkg = require('@userfrosting/merge-package-dependencies'); + + // See if there are any yarn packages. + let yarnPaths = []; + for (let sprinkle of sprinkles) { + if (fs.existsSync(`../app/sprinkles/${sprinkle}/package.json`)) { + yarnPaths.push(`../app/sprinkles/${sprinkle}/package.json`); } - }); + } + if (yarnPaths.length > 0) { + // Yes there are! + + // Delete old package.json + del.sync('../app/assets/package.json', { force: true }); + + // Generate package.json + let yarnTemplate = {// Private makes sure it isn't published, and cuts out a lot of unnecessary fields. + private: true, + flat: true + }; + logger('\nMerging packages...\n'); + mergePkg.yarn(yarnTemplate, yarnPaths, '../app/assets/', doILog); + logger('\nMerge complete.\n'); + + // Yarn automatically removes extraneous packages. + + // Perform installation. + logger('Installing npm/yarn assets...'); + let childProcess = require('child_process'); + childProcess.execSync('yarn install --flat --no-lockfile --non-interactive', { + cwd: '../app/assets', + preferLocal: true,// Local over PATH. + localDir: './node_modules/.bin', + stdio: doILog ? 'inherit' : '' + }); + } + else del.sync([ + '../app/assets/package.json', + '../app/assets/node_modules/' + ], { force: true }); - return true; + // See if there are any bower packages. + let bowerPaths = []; + for (let sprinkle of sprinkles) { + // bower + if (fs.existsSync(`../app/sprinkles/${sprinkle}/bower.json`)) { + console.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`); + bowerPaths.push(`../app/sprinkles/${sprinkle}/bower.json`); + } + } + if (bowerPaths.length > 0) { + // Yes there are! + + // Delete old bower.json + del.sync('../app/assets/bower.json', { force: true }); + + // Generate bower.json + let bowerTemplate = { + name: 'uf-vendor-assets' + }; + logger('\nMerging packages...\n'); + mergePkg.bower(bowerTemplate, bowerPaths, '../app/assets/', doILog); + logger('\nMerge complete.\n'); + + let childProcess = require('child_process'); + + // Remove extraneous packages + childProcess.execSync('bower prune', { + cwd: '../app/assets', + preferLocal: true,// Local over PATH. + localDir: './node_modules/.bin', + stdio: doILog ? 'inherit' : '' + }); + + // Perform installation + childProcess.execSync('bower install -q --allow-root', { // --allow-root stops bower from complaining about being in 'sudo'. + cwd: '../app/assets', + preferLocal: true,// Local over PATH. + localDir: './node_modules/.bin', + stdio: doILog ? 'inherit' : '' + }); + // Yarn is able to output its completion. Bower... not so much. + logger('Done.\n'); + } + else del.sync([ + '../app/assets/bower.json', + '../app/assets/bower_components/' + ], { force: true }); }); + /** * Bundling tasks */ -// Executes bundleing tasks according to bundle.config.json files in each Sprinkle, as per Sprinkle load order. +// Executes bundling tasks according to bundle.config.json files in each Sprinkle, as per Sprinkle load order. // Respects bundle collision rules. gulp.task('bundle-build', () => { - "use strict"; + 'use strict'; let copy = require('recursive-copy'); let merge = require('merge-array-object'); let cleanup = (e) => { - "use strict"; + 'use strict'; // Delete temporary directory if exists - fs.rmdirSync("./temp"); + fs.rmdirSync('./temp'); // Delete created bundle.config.json file fs.unlinkSync(bundleConfigFile); // Propagate error @@ -80,7 +156,7 @@ gulp.task('bundle-build', () => { copy: [] }; sprinkles.forEach((sprinkle) => { - "use strict"; + 'use strict'; let location = `${sprinklesDir}/${sprinkle}/`; if (fs.existsSync(`${location}${bundleFile}`)) { let currentConfig = require(`${location}${bundleFile}`); @@ -127,20 +203,29 @@ gulp.task('bundle-build', () => { // Save bundle rules to bundle.config.json fs.writeFileSync(bundleConfigFile, JSON.stringify(config)); - // Copy all assets in order of Sprinkle load order. - let sprinkleAssets = [] - sprinkles.forEach((sprinkle) => { - "use strict"; - sprinkleAssets.push(`../app/sprinkles/${sprinkle}/assets/**/*`); - }); - // Gulp v4 src respects order, until it is released, use this alternative. - return plugins.srcOrderedGlobs(sprinkleAssets) - .pipe(plugins.copy('../public/assets/', {prefix: 5}));// And gulp.dest doesn't give us the control needed. + // Copy vendor assets (bower, then npm) + /** @todo Should really keep the garbage files out. A filter function can be passed to the copySync settings object. */ + let paths = [ + '../app/assets/bower_components/', + '../app/assets/node_modules/' + ]; + for (let path of paths) { + if (fs.pathExistsSync(path)) fs.copySync(path, `${publicAssetsDir}vendor/`, { overwrite: true }); + } + // Copy sprinkle assets + paths = []; + for (let sprinkle of sprinkles) { + paths.push(`../app/sprinkles/${sprinkle}/assets/`); + } + for (let path of paths) { + fs.copySync(path, '../public/assets/', { overwrite: true }); + } + return; }); // Execute gulp-bundle-assets gulp.task('bundle', () => { - "use strict"; + 'use strict'; return gulp.src(bundleConfigFile) .pipe(plugins.ufBundleAssets({ base: publicAssetsDir @@ -151,33 +236,28 @@ gulp.task('bundle', () => { .pipe(gulp.dest(publicAssetsDir)); }); + + /** * Clean up tasks */ gulp.task('public-clean', () => { - "use strict"; + 'use strict'; return del(publicAssetsDir, { force: true }); }); // Clean up temporary bundling files gulp.task('bundle-clean', () => { - "use strict"; + 'use strict'; return del(bundleConfigFile, { force: true }); }); -// Deletes assets fetched by bower-install -gulp.task('bower-clean', () => { - "use strict"; - return del(`${sprinklesDir}/*/assets/vendor`, { force: true }); +// Deletes assets fetched by assets-install +gulp.task('assets-clean', () => { + 'use strict'; + return del(['../app/assets/bower_components/', '../app/assets/node_modules/', '../app/assets/bower.json', '../app/assets/package.json'], { force: true }); }); // Deletes all generated, or acquired files. -gulp.task('clean', () => { - "use strict"; - del(publicAssetsDir, { force: true}); - del(bundleConfigFile, { force: true }); - del(`${sprinklesDir}/*/assets/vendor`, { force: true }); - - return true; -}) \ No newline at end of file +gulp.task('clean', ['public-clean', 'bundle-clean', 'assets-clean'], () => { }); \ No newline at end of file diff --git a/build/package-lock.json b/build/package-lock.json new file mode 100644 index 000000000..7d20b25e0 --- /dev/null +++ b/build/package-lock.json @@ -0,0 +1,4533 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@userfrosting/merge-package-dependencies": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.1.0.tgz", + "integrity": "sha512-xgJ95NM2uhDWIzXMb6AjxIU9tJaclE5HhQEOArqSGQ34p1JqtuMzLNdESW+5vzqrenJvoToqp1a5wV4Oym1f4g==", + "dev": true, + "requires": { + "chalk": "2.3.0", + "fs-extra": "4.0.2", + "lodash": "4.17.4", + "node-exceptions": "2.0.2", + "package-json-validator": "0.6.2", + "semver": "5.4.1", + "semver-intersect": "1.1.2" + } + }, + "accord": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/accord/-/accord-0.23.0.tgz", + "integrity": "sha1-JGjHjlZBLbqTEdOD+4c0UNKGfK8=", + "dev": true, + "requires": { + "convert-source-map": "1.5.0", + "fobject": "0.0.4", + "glob": "7.0.3", + "indx": "0.2.3", + "lodash": "4.11.2", + "resolve": "1.5.0", + "semver": "5.4.1", + "uglify-js": "2.8.29", + "when": "3.7.8" + }, + "dependencies": { + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "glob": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz", + "integrity": "sha1-CqI1kxpKlqwT1g/6wvuHe9btT1g=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "lodash": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.11.2.tgz", + "integrity": "sha1-1rQzixEKWOIdrlzrz9u/0rxM2zs=", + "dev": true + } + } + }, + "ajv": { + "version": "4.11.8", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", + "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "dev": true, + "optional": true, + "requires": { + "co": "4.6.0", + "json-stable-stringify": "1.0.1" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "dev": true, + "requires": { + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.1" + } + }, + "archy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", + "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", + "dev": true + }, + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "1.1.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", + "dev": true + }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, + "array-slice": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", + "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "1.0.3" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "dev": true + }, + "asn1": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", + "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", + "dev": true, + "optional": true + }, + "assert-plus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", + "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", + "dev": true, + "optional": true + }, + "async": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true, + "optional": true + }, + "atob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", + "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "dev": true + }, + "aws-sign2": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", + "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", + "dev": true, + "optional": true + }, + "aws4": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", + "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", + "dev": true, + "optional": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", + "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "dev": true, + "optional": true, + "requires": { + "tweetnacl": "0.14.5" + } + }, + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true + }, + "bluebird": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.3.5.tgz", + "integrity": "sha1-XudH8ce9lnZYtoOTZDCu51OVWjQ=", + "dev": true + }, + "boom": { + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", + "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "dev": true, + "requires": { + "hoek": "2.16.3" + } + }, + "bower": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.2.tgz", + "integrity": "sha1-rfU1KcjUrwLvJPuNU0HBQZ0z4vc=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true, + "requires": { + "balanced-match": "1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" + } + }, + "bufferstreams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", + "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + }, + "dependencies": { + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "dev": true + } + } + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true, + "optional": true + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "dev": true, + "requires": { + "align-text": "0.1.4", + "lazy-cache": "1.0.4" + } + }, + "chalk": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", + "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.5.0" + } + }, + "clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "dev": true, + "requires": { + "commander": "2.8.1", + "source-map": "0.4.4" + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "dev": true, + "requires": { + "center-align": "0.1.3", + "right-align": "0.1.3", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "dev": true + } + } + }, + "clone": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", + "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "dev": true, + "optional": true + }, + "coffee-script": { + "version": "1.12.7", + "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", + "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", + "dev": true + }, + "color-convert": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", + "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "combined-stream": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", + "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", + "dev": true, + "requires": { + "delayed-stream": "1.0.0" + } + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": "1.0.1" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-with-sourcemaps": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", + "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "convert-source-map": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cryptiles": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", + "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1" + } + }, + "css": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", + "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "source-map": "0.1.43", + "source-map-resolve": "0.3.1", + "urix": "0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + } + } + }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "deap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.0.tgz", + "integrity": "sha1-sUi/gkMKJ2mbdIOgPra2dYW/yIg=", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "requires": { + "clone": "1.0.3" + } + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "5.0.0", + "is-path-cwd": "1.0.0", + "is-path-in-cwd": "1.0.0", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "rimraf": "2.6.2" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "deprecated": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", + "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "dev": true + }, + "detect-file": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", + "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "dev": true, + "requires": { + "fs-exists-sync": "0.1.0" + } + }, + "dotenv": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", + "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", + "dev": true + }, + "duplexer": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", + "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "dev": true + }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "duplexify": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", + "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "dev": true, + "requires": { + "end-of-stream": "1.4.0", + "inherits": "2.0.3", + "readable-stream": "2.3.3", + "stream-shift": "1.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", + "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "dev": true, + "requires": { + "once": "1.4.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "ecc-jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", + "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "dev": true, + "optional": true, + "requires": { + "jsbn": "0.1.1" + } + }, + "emitter-mixin": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/emitter-mixin/-/emitter-mixin-0.0.3.tgz", + "integrity": "sha1-WUjLKG8uSO3DslGnz8H3iDOW1lw=", + "dev": true + }, + "end-of-stream": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", + "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "dev": true, + "requires": { + "once": "1.3.3" + }, + "dependencies": { + "once": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", + "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + } + } + }, + "errno": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", + "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "dev": true, + "requires": { + "prr": "0.0.0" + } + }, + "error-ex": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", + "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "dev": true, + "requires": { + "is-arrayish": "0.2.1" + } + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "0.1.1" + } + }, + "expand-range": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", + "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "dev": true, + "requires": { + "fill-range": "2.2.3" + } + }, + "expand-tilde": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", + "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "extend": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", + "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", + "dev": true + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fancy-log": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", + "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "time-stamp": "1.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "filename-regex": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", + "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", + "dev": true + }, + "fill-range": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", + "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "dev": true, + "requires": { + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" + } + }, + "find-index": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", + "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", + "dev": true + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "dev": true, + "requires": { + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" + } + }, + "findup-sync": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", + "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", + "dev": true, + "requires": { + "detect-file": "0.1.0", + "is-glob": "2.0.1", + "micromatch": "2.3.11", + "resolve-dir": "0.1.1" + } + }, + "fined": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", + "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", + "dev": true, + "requires": { + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.1" + }, + "dependencies": { + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1" + } + } + } + }, + "first-chunk-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", + "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", + "dev": true + }, + "flagged-respawn": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", + "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "dev": true + }, + "fobject": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fobject/-/fobject-0.0.4.tgz", + "integrity": "sha1-g5nmuRBdLrjm353MQRI6FxaIrf4=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "semver": "5.4.1", + "when": "3.7.8" + } + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "for-own": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", + "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "optional": true + }, + "fork-stream": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", + "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", + "dev": true + }, + "form-data": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", + "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "dev": true, + "optional": true, + "requires": { + "asynckit": "0.4.0", + "combined-stream": "1.0.5", + "mime-types": "2.1.17" + } + }, + "fs-exists-sync": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", + "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", + "dev": true + }, + "fs-extra": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "gaze": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", + "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", + "dev": true, + "requires": { + "globule": "0.1.0" + } + }, + "get-imports": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-imports/-/get-imports-1.0.0.tgz", + "integrity": "sha1-R8C07piTUWQsVJdxk79Pyqv1N48=", + "dev": true, + "requires": { + "array-uniq": "1.0.3", + "import-regex": "1.1.0" + } + }, + "get-stdin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "glob-base": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", + "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", + "dev": true, + "requires": { + "glob-parent": "2.0.0", + "is-glob": "2.0.1" + } + }, + "glob-parent": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", + "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", + "dev": true, + "requires": { + "is-glob": "2.0.1" + } + }, + "glob-stream": { + "version": "3.1.18", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", + "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", + "dev": true, + "requires": { + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" + }, + "dependencies": { + "glob": { + "version": "4.5.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", + "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" + } + }, + "minimatch": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", + "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "glob-watcher": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", + "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", + "dev": true, + "requires": { + "gaze": "0.5.2" + } + }, + "glob2base": { + "version": "0.0.12", + "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", + "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", + "dev": true, + "requires": { + "find-index": "0.1.1" + } + }, + "global-modules": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", + "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", + "dev": true, + "requires": { + "global-prefix": "0.1.5", + "is-windows": "0.2.0" + } + }, + "global-prefix": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", + "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", + "dev": true, + "requires": { + "homedir-polyfill": "1.0.1", + "ini": "1.3.4", + "is-windows": "0.2.0", + "which": "1.3.0" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "globule": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", + "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", + "dev": true, + "requires": { + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" + }, + "dependencies": { + "glob": { + "version": "3.1.21", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", + "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", + "dev": true, + "requires": { + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" + } + }, + "graceful-fs": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", + "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "dev": true + }, + "inherits": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", + "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "dev": true + }, + "lodash": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", + "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "dev": true + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, + "gulp": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", + "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", + "dev": true, + "requires": { + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.0.4", + "liftoff": "2.3.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "semver": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", + "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "gulp-clean-css": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-2.0.7.tgz", + "integrity": "sha1-2Go9haeQvsg+Pdbd+wPWWmKPm6A=", + "dev": true, + "requires": { + "clean-css": "3.4.28", + "gulp-util": "3.0.8", + "object-assign": "4.1.1", + "readable-stream": "2.3.3", + "vinyl-bufferstream": "1.0.1", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "gulp-coffee": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/gulp-coffee/-/gulp-coffee-2.3.2.tgz", + "integrity": "sha1-6FQTyVpvdpXqFg+1kMxXjz29pbE=", + "dev": true, + "requires": { + "coffee-script": "1.12.7", + "gulp-util": "3.0.8", + "merge": "1.2.0", + "through2": "0.6.5", + "vinyl-sourcemaps-apply": "0.1.4" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.1.4.tgz", + "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", + "dev": true, + "requires": { + "source-map": "0.1.43" + } + } + } + }, + "gulp-concat": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.5.2.tgz", + "integrity": "sha1-1kQ3LNwrPNtCGoqUHI104h2BXxQ=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "1.0.4", + "gulp-util": "3.0.8", + "through2": "0.6.5" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulp-concat-css": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/gulp-concat-css/-/gulp-concat-css-2.3.0.tgz", + "integrity": "sha1-TBWGEhqEEf9LLcRPz6TcdA6P4bY=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "lodash.defaults": "3.1.2", + "parse-import": "2.0.0", + "rework": "1.0.1", + "rework-import": "2.1.0", + "rework-plugin-url": "1.1.0", + "through2": "1.1.1" + }, + "dependencies": { + "through2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + "dev": true, + "requires": { + "readable-stream": "1.1.14", + "xtend": "4.0.1" + } + } + } + }, + "gulp-if": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.1.tgz", + "integrity": "sha1-VfPt+Czs389gNapdBoaXmqsNrCg=", + "dev": true, + "requires": { + "gulp-match": "1.0.3", + "ternary-stream": "2.0.1", + "through2": "2.0.3" + } + }, + "gulp-less": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/gulp-less/-/gulp-less-3.1.0.tgz", + "integrity": "sha1-xUwu4BTr5uE1v8sBadtN25NQbeY=", + "dev": true, + "requires": { + "accord": "0.23.0", + "gulp-util": "3.0.8", + "less": "2.7.3", + "object-assign": "4.1.1", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + } + }, + "gulp-load-plugins": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/gulp-load-plugins/-/gulp-load-plugins-1.5.0.tgz", + "integrity": "sha1-TEGffldk2aDjMGG6uWGPgbc9QXE=", + "dev": true, + "requires": { + "array-unique": "0.2.1", + "fancy-log": "1.3.0", + "findup-sync": "0.4.3", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "micromatch": "2.3.11", + "resolve": "1.5.0" + } + }, + "gulp-match": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", + "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", + "dev": true, + "requires": { + "minimatch": "3.0.4" + } + }, + "gulp-order": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/gulp-order/-/gulp-order-1.1.1.tgz", + "integrity": "sha1-C47wgzI1vtZfHvvHnGrtl7HbQek=", + "dev": true, + "requires": { + "minimatch": "0.2.14", + "through": "2.3.8" + }, + "dependencies": { + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2.7.3", + "sigmund": "1.0.1" + } + } + } + }, + "gulp-rev": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gulp-rev/-/gulp-rev-4.0.0.tgz", + "integrity": "sha1-Zj2RhOdyJHsvJcSk5XE4h0LlXuk=", + "dev": true, + "requires": { + "gulp-util": "3.0.8", + "object-assign": "2.1.1", + "rev-hash": "1.0.0", + "rev-path": "1.0.0", + "through2": "0.6.5", + "vinyl-file": "1.3.0" + }, + "dependencies": { + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "gulp-sourcemaps": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.5.2.tgz", + "integrity": "sha1-eW9v9pWklCFfPT1mqnrIU9fnNRE=", + "dev": true, + "requires": { + "convert-source-map": "1.5.0", + "graceful-fs": "3.0.11", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "convert-source-map": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", + "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", + "dev": true + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "gulp-streamify": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/gulp-streamify/-/gulp-streamify-0.0.5.tgz", + "integrity": "sha1-aF0gUSVSrFdlYktBMbSx7K3wDsE=", + "dev": true, + "requires": { + "gulp-util": "2.2.20", + "plexer": "0.0.2", + "readable-stream": "1.1.14" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "gulp-util": { + "version": "2.2.20", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", + "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", + "dev": true, + "requires": { + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "lodash._reinterpolate": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", + "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", + "dev": true + }, + "lodash.defaults": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", + "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" + } + }, + "lodash.escape": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", + "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", + "dev": true, + "requires": { + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" + } + }, + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + }, + "lodash.template": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", + "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", + "dev": true, + "requires": { + "lodash._escapestringchar": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.defaults": "2.4.1", + "lodash.escape": "2.4.1", + "lodash.keys": "2.4.1", + "lodash.templatesettings": "2.4.1", + "lodash.values": "2.4.1" + } + }, + "lodash.templatesettings": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", + "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", + "dev": true, + "requires": { + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" + } + }, + "minimist": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", + "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", + "dev": true + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "3.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + } + } + }, + "vinyl": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", + "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "dev": true, + "requires": { + "clone-stats": "0.0.1" + } + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + } + } + }, + "gulp-uf-bundle-assets": { + "version": "2.27.2", + "resolved": "https://registry.npmjs.org/gulp-uf-bundle-assets/-/gulp-uf-bundle-assets-2.27.2.tgz", + "integrity": "sha1-uET3POm9hOU5nV+rDeBcODXVyPg=", + "dev": true, + "requires": { + "bluebird": "3.3.5", + "duplexer2": "0.0.2", + "graceful-fs": "4.1.4", + "gulp": "3.9.1", + "gulp-clean-css": "2.0.7", + "gulp-coffee": "2.3.2", + "gulp-concat": "2.5.2", + "gulp-concat-css": "2.3.0", + "gulp-if": "2.0.1", + "gulp-less": "3.1.0", + "gulp-order": "1.1.1", + "gulp-rev": "4.0.0", + "gulp-sourcemaps": "1.5.2", + "gulp-streamify": "0.0.5", + "gulp-uglify": "1.5.3", + "gulp-util": "3.0.7", + "lazypipe": "0.2.3", + "lodash": "3.9.3", + "map-stream": "0.0.6", + "merge-stream": "0.1.7", + "mkdirp": "0.5.1", + "pretty-hrtime": "1.0.2", + "readable-stream": "2.0.0", + "through2": "2.0.1", + "vinyl": "1.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "dateformat": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", + "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "dev": true, + "requires": { + "get-stdin": "4.0.1", + "meow": "3.7.0" + } + }, + "graceful-fs": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz", + "integrity": "sha1-7widKIDwM7ARgjzlyPrnmNp3Xb0=", + "dev": true + }, + "gulp-util": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", + "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "1.0.12", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.1", + "vinyl": "0.5.3" + }, + "dependencies": { + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "lodash": { + "version": "3.9.3", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.9.3.tgz", + "integrity": "sha1-AVnoaDL+/8bWHYUrEqlTuZSWvTI=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz", + "integrity": "sha1-cMqW9NBiikQ7kYdY95QWqae8n6g=", + "dev": true + }, + "readable-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.0.tgz", + "integrity": "sha1-q24pLYrjku+IgVExBVTnB4/LOMo=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "process-nextick-args": "1.0.7", + "string_decoder": "0.10.31", + "util-deprecate": "1.0.2" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "through2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz", + "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=", + "dev": true, + "requires": { + "readable-stream": "2.0.0", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.1.1.tgz", + "integrity": "sha1-eUCIfu8JOB6zYmrEwPmrU9S35FA=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "gulp-uglify": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.3.tgz", + "integrity": "sha1-YKALOXWrpBhkQqSUl56d+j8T0NY=", + "dev": true, + "requires": { + "deap": "1.0.0", + "fancy-log": "1.3.0", + "gulp-util": "3.0.8", + "isobject": "2.1.0", + "through2": "2.0.3", + "uglify-js": "2.6.2", + "uglify-save-license": "0.4.1", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "uglify-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.2.tgz", + "integrity": "sha1-9QvoikLNOWpiUdxSqzcvccwS/vA=", + "dev": true, + "requires": { + "async": "0.2.10", + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + } + } + } + }, + "gulp-util": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", + "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.0", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", + "replace-ext": "0.0.1", + "through2": "2.0.3", + "vinyl": "0.5.3" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "gulplog": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", + "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", + "dev": true, + "requires": { + "glogg": "1.0.0" + } + }, + "har-schema": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", + "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", + "dev": true, + "optional": true + }, + "har-validator": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", + "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", + "dev": true, + "optional": true, + "requires": { + "ajv": "4.11.8", + "har-schema": "1.0.5" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "has-gulplog": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", + "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", + "dev": true, + "requires": { + "sparkles": "1.0.0" + } + }, + "hawk": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", + "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "dev": true, + "optional": true, + "requires": { + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" + } + }, + "hoek": { + "version": "2.16.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "dev": true, + "requires": { + "parse-passwd": "1.0.0" + } + }, + "hosted-git-info": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", + "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "dev": true + }, + "http-signature": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", + "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.13.1" + } + }, + "image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", + "dev": true, + "optional": true + }, + "import-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/import-regex/-/import-regex-1.1.0.tgz", + "integrity": "sha1-pVxS5McFx2XKIQ6SQqBrvMiqf2Y=", + "dev": true + }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, + "indx": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", + "integrity": "sha1-Fdz1bunPZcAjTFE8J/vVgOcPvFA=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "1.4.0", + "wrappy": "1.0.2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "ini": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", + "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", + "dev": true + }, + "interpret": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", + "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", + "dev": true + }, + "ip-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", + "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", + "dev": true + }, + "is-absolute": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", + "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "dev": true, + "requires": { + "is-relative": "0.2.1", + "is-windows": "0.2.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "dev": true, + "requires": { + "builtin-modules": "1.1.1" + } + }, + "is-dotfile": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", + "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", + "dev": true + }, + "is-equal-shallow": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", + "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "dev": true, + "requires": { + "is-primitive": "2.0.0" + } + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-finite": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", + "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "1.0.0" + } + }, + "is-number": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", + "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", + "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "dev": true, + "requires": { + "is-path-inside": "1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", + "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "dev": true, + "requires": { + "path-is-inside": "1.0.2" + } + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "is-posix-bracket": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", + "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", + "dev": true + }, + "is-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", + "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", + "dev": true + }, + "is-relative": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", + "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "dev": true, + "requires": { + "is-unc-path": "0.1.2" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true, + "optional": true + }, + "is-unc-path": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", + "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "dev": true, + "requires": { + "unc-path-regex": "0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", + "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "dev": true + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + } + } + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true, + "optional": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true, + "optional": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true, + "optional": true + }, + "json-stable-stringify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", + "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", + "dev": true, + "optional": true, + "requires": { + "jsonify": "0.0.0" + } + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true, + "optional": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11" + } + }, + "jsonify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", + "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true, + "optional": true + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "junk": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.3.tgz", + "integrity": "sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", + "dev": true + }, + "lazypipe": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/lazypipe/-/lazypipe-0.2.3.tgz", + "integrity": "sha1-RUtKvmW4+MP4ivI10AmLXdXcbk4=", + "dev": true, + "requires": { + "stream-combiner": "0.2.2" + } + }, + "less": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", + "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", + "dev": true, + "requires": { + "errno": "0.1.4", + "graceful-fs": "4.1.11", + "image-size": "0.5.5", + "mime": "1.4.1", + "mkdirp": "0.5.1", + "promise": "7.3.1", + "request": "2.81.0", + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + } + } + }, + "liftoff": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", + "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", + "dev": true, + "requires": { + "extend": "3.0.1", + "findup-sync": "0.4.3", + "fined": "1.1.0", + "flagged-respawn": "0.3.2", + "lodash.isplainobject": "4.0.6", + "lodash.isstring": "4.0.1", + "lodash.mapvalues": "4.6.0", + "rechoir": "0.6.2", + "resolve": "1.5.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "lodash": { + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true + }, + "lodash._baseassign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", + "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash.keys": "3.1.2" + } + }, + "lodash._basecopy": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", + "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", + "dev": true + }, + "lodash._basetostring": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", + "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", + "dev": true + }, + "lodash._basevalues": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", + "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", + "dev": true + }, + "lodash._bindcallback": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", + "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", + "dev": true + }, + "lodash._createassigner": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", + "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", + "dev": true, + "requires": { + "lodash._bindcallback": "3.0.1", + "lodash._isiterateecall": "3.0.9", + "lodash.restparam": "3.6.1" + } + }, + "lodash._escapehtmlchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", + "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1" + } + }, + "lodash._escapestringchar": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", + "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", + "dev": true + }, + "lodash._getnative": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", + "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", + "dev": true + }, + "lodash._htmlescapes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", + "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", + "dev": true + }, + "lodash._isiterateecall": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", + "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", + "dev": true + }, + "lodash._isnative": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", + "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", + "dev": true + }, + "lodash._objecttypes": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", + "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", + "dev": true + }, + "lodash._reescape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", + "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", + "dev": true + }, + "lodash._reevaluate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", + "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash._reunescapedhtml": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", + "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", + "dev": true, + "requires": { + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "lodash._root": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", + "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", + "dev": true + }, + "lodash._shimkeys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", + "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash.assign": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", + "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", + "dev": true, + "requires": { + "lodash._baseassign": "3.2.0", + "lodash._createassigner": "3.1.1", + "lodash.keys": "3.1.2" + } + }, + "lodash.defaults": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", + "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=", + "dev": true, + "requires": { + "lodash.assign": "3.2.0", + "lodash.restparam": "3.6.1" + } + }, + "lodash.escape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", + "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", + "dev": true, + "requires": { + "lodash._root": "3.0.1" + } + }, + "lodash.isarguments": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", + "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", + "dev": true + }, + "lodash.isarray": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", + "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", + "dev": true + }, + "lodash.isobject": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", + "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", + "dev": true, + "requires": { + "lodash._objecttypes": "2.4.1" + } + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", + "dev": true + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", + "dev": true + }, + "lodash.keys": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", + "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", + "dev": true, + "requires": { + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" + } + }, + "lodash.mapvalues": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", + "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", + "dev": true + }, + "lodash.restparam": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", + "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", + "dev": true + }, + "lodash.template": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", + "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", + "dev": true, + "requires": { + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" + } + }, + "lodash.templatesettings": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", + "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", + "dev": true, + "requires": { + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" + } + }, + "lodash.values": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", + "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", + "dev": true, + "requires": { + "lodash.keys": "2.4.1" + }, + "dependencies": { + "lodash.keys": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", + "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", + "dev": true, + "requires": { + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" + } + } + } + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", + "dev": true + }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, + "map-stream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.6.tgz", + "integrity": "sha1-0u9OuBGihkTHqJiZhcacL91JaCc=", + "dev": true + }, + "maximatch": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", + "integrity": "sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" + } + }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "merge": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", + "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", + "dev": true + }, + "merge-array-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/merge-array-object/-/merge-array-object-1.0.5.tgz", + "integrity": "sha1-uBfILEGnzgCr9u2CHNscbVM7bRk=", + "dev": true, + "requires": { + "lodash": "4.17.4" + } + }, + "merge-stream": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-0.1.7.tgz", + "integrity": "sha1-Md664T+XN7oX97T74zwWV0yG/Hk=", + "dev": true, + "requires": { + "through2": "0.6.5" + }, + "dependencies": { + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + } + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" + } + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", + "dev": true, + "optional": true + }, + "mime-db": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", + "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", + "dev": true + }, + "mime-types": { + "version": "2.1.17", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", + "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", + "dev": true, + "requires": { + "mime-db": "1.30.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "dev": true, + "requires": { + "brace-expansion": "1.1.8" + } + }, + "minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", + "dev": true + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "dev": true, + "requires": { + "minimist": "0.0.8" + }, + "dependencies": { + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + } + } + }, + "modify-filename": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz", + "integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=", + "dev": true + }, + "multipipe": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", + "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", + "dev": true, + "requires": { + "duplexer2": "0.0.2" + } + }, + "natives": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", + "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "dev": true + }, + "node-exceptions": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-2.0.2.tgz", + "integrity": "sha512-nILccFLvnaOBoKZZtWfZipn/hlThZOT6UJOLX6SA3yLMYPcvLTIF26PXx73sPnAg45p05iYFYw2jvayNHz4rDA==", + "dev": true + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "dev": true, + "requires": { + "hosted-git-info": "2.5.0", + "is-builtin-module": "1.0.0", + "semver": "5.4.1", + "validate-npm-package-license": "3.0.1" + } + }, + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "1.1.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", + "dev": true + }, + "oauth-sign": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", + "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", + "dev": true, + "optional": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "dev": true, + "requires": { + "array-each": "1.0.1", + "array-slice": "1.0.0", + "for-own": "1.0.0", + "isobject": "3.0.1" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "1.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.omit": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", + "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "dev": true, + "requires": { + "for-own": "0.1.5", + "is-extendable": "0.1.1" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "3.0.1" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1.0.2" + } + }, + "optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", + "dev": true, + "requires": { + "minimist": "0.0.10", + "wordwrap": "0.0.3" + } + }, + "orchestrator": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", + "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "dev": true, + "requires": { + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.0" + } + }, + "ordered-read-streams": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", + "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", + "dev": true + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "dev": true + }, + "package-json-validator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.2.tgz", + "integrity": "sha512-B4eikrIIhxheXKkIW7GR6Se4mtqegZ/x8jUDh6hHW4jYBz9HFXUejpPEUAsuplxpDtVdPsXT3ZMRTH1HizJV1Q==", + "dev": true, + "requires": { + "optimist": "0.6.1" + } + }, + "parse-filepath": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", + "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", + "dev": true, + "requires": { + "is-absolute": "0.2.6", + "map-cache": "0.2.2", + "path-root": "0.1.1" + } + }, + "parse-glob": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", + "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "dev": true, + "requires": { + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" + } + }, + "parse-import": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/parse-import/-/parse-import-2.0.0.tgz", + "integrity": "sha1-KyR0Aw4AirmNt2xLy/TbWucwb18=", + "dev": true, + "requires": { + "get-imports": "1.0.0" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "dev": true, + "requires": { + "error-ex": "1.3.1" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "dev": true, + "requires": { + "pinkie-promise": "2.0.1" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "dev": true, + "requires": { + "path-root-regex": "0.1.2" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", + "dev": true + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "performance-now": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", + "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", + "dev": true, + "optional": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "2.0.4" + } + }, + "plexer": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/plexer/-/plexer-0.0.2.tgz", + "integrity": "sha1-Ij1YAGKKBkagCX0wq1doZqLzeE4=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + } + }, + "preserve": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", + "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "dev": true + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, + "process-nextick-args": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", + "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", + "dev": true + }, + "promise": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", + "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "dev": true, + "requires": { + "asap": "2.0.6" + } + }, + "prr": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", + "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", + "dev": true + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true, + "optional": true + }, + "qs": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", + "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "dev": true, + "optional": true + }, + "randomatic": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", + "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "dev": true, + "requires": { + "is-number": "3.0.0", + "kind-of": "4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "3.2.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "1.1.6" + } + } + } + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "dev": true, + "requires": { + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "dev": true, + "requires": { + "find-up": "1.1.2", + "read-pkg": "1.1.0" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "rechoir": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", + "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", + "dev": true, + "requires": { + "resolve": "1.5.0" + } + }, + "recursive-copy": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/recursive-copy/-/recursive-copy-2.0.7.tgz", + "integrity": "sha1-JNuFxxKdj63uQC5UAM/PDLYPyjw=", + "dev": true, + "requires": { + "del": "2.2.2", + "emitter-mixin": "0.0.3", + "errno": "0.1.4", + "graceful-fs": "4.1.11", + "junk": "1.0.3", + "maximatch": "0.1.0", + "mkdirp": "0.5.1", + "pify": "2.3.0", + "promise": "7.3.1", + "slash": "1.0.0" + } + }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, + "regex-cache": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", + "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "dev": true, + "requires": { + "is-equal-shallow": "0.1.3" + } + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "repeat-element": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "repeating": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", + "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", + "dev": true, + "requires": { + "is-finite": "1.0.2" + } + }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, + "request": { + "version": "2.81.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", + "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "dev": true, + "optional": true, + "requires": { + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.5", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.17", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.3", + "tunnel-agent": "0.6.0", + "uuid": "3.1.0" + } + }, + "resolve": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", + "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", + "dev": true, + "requires": { + "path-parse": "1.0.5" + } + }, + "resolve-dir": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", + "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "dev": true, + "requires": { + "expand-tilde": "1.2.2", + "global-modules": "0.2.3" + } + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "rev-hash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rev-hash/-/rev-hash-1.0.0.tgz", + "integrity": "sha1-lpk5Weqb+xxZsTrfAqwuNLs3NgM=", + "dev": true + }, + "rev-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rev-path/-/rev-path-1.0.0.tgz", + "integrity": "sha1-1My0NqwzcMRgcXXOiOr8XGXF1lM=", + "dev": true, + "requires": { + "modify-filename": "1.1.0" + } + }, + "rework": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", + "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", + "dev": true, + "requires": { + "convert-source-map": "0.3.5", + "css": "2.2.1" + } + }, + "rework-import": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/rework-import/-/rework-import-2.1.0.tgz", + "integrity": "sha1-wm7StTFZrHvi7GDaIj74lgPB7x8=", + "dev": true, + "requires": { + "css": "2.2.1", + "globby": "2.1.0", + "parse-import": "2.0.0", + "url-regex": "3.2.0" + }, + "dependencies": { + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globby": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-2.1.0.tgz", + "integrity": "sha1-npGSvNM/Srak+JTl5+qLcTITxII=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "async": "1.5.2", + "glob": "5.0.15", + "object-assign": "3.0.0" + } + }, + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + } + } + }, + "rework-plugin-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/rework-plugin-function/-/rework-plugin-function-1.0.2.tgz", + "integrity": "sha1-Es5G+1sptdk1FGaD9rmM9J0jc7k=", + "dev": true, + "requires": { + "rework-visit": "1.0.0" + } + }, + "rework-plugin-url": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/rework-plugin-url/-/rework-plugin-url-1.1.0.tgz", + "integrity": "sha1-q1PosQV7nV7MHIJz/32xhgg3XEU=", + "dev": true, + "requires": { + "rework-plugin-function": "1.0.2" + } + }, + "rework-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", + "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", + "dev": true + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "dev": true, + "requires": { + "align-text": "0.1.4" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "dev": true, + "requires": { + "glob": "7.1.2" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", + "dev": true + }, + "semver-intersect": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.1.2.tgz", + "integrity": "sha1-sLKLV1Ggf/3QAuXsYGyS1XbMtWE=", + "dev": true, + "requires": { + "semver": "5.4.1" + } + }, + "sequencify": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", + "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "dev": true + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", + "dev": true + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + }, + "sntp": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", + "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "dev": true, + "optional": true, + "requires": { + "hoek": "2.16.3" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "source-map-resolve": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", + "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "dev": true, + "requires": { + "atob": "1.1.3", + "resolve-url": "0.2.1", + "source-map-url": "0.3.0", + "urix": "0.1.0" + } + }, + "source-map-url": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", + "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "dev": true + }, + "sparkles": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", + "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", + "dev": true + }, + "spdx-correct": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", + "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "dev": true, + "requires": { + "spdx-license-ids": "1.2.2" + } + }, + "spdx-expression-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", + "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "dev": true + }, + "spdx-license-ids": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", + "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "dev": true + }, + "sshpk": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", + "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "dev": true, + "optional": true, + "requires": { + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "through": "2.3.8" + } + }, + "stream-consume": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", + "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "dev": true + }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "stringstream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", + "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "dev": true, + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "2.1.1" + } + }, + "strip-bom": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", + "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "1.0.0", + "strip-bom": "2.0.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + } + } + }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, + "supports-color": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", + "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + }, + "ternary-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", + "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "dev": true, + "requires": { + "duplexify": "3.5.1", + "fork-stream": "0.0.4", + "merge-stream": "1.0.1", + "through2": "2.0.3" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "merge-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", + "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", + "dev": true, + "requires": { + "readable-stream": "2.3.3" + } + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "dev": true, + "requires": { + "readable-stream": "2.3.3", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", + "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "1.0.7", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" + } + }, + "string_decoder": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", + "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "dev": true, + "requires": { + "safe-buffer": "5.1.1" + } + } + } + }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "dev": true, + "requires": { + "os-homedir": "1.0.2" + } + }, + "time-stamp": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", + "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", + "dev": true + }, + "tough-cookie": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "dev": true, + "optional": true, + "requires": { + "punycode": "1.4.1" + } + }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "5.1.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true, + "optional": true + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "dev": true, + "requires": { + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "uglify-save-license": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", + "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", + "dev": true + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "dev": true + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", + "dev": true + }, + "unique-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", + "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "dev": true + }, + "universalify": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", + "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "dev": true + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url-regex": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", + "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", + "dev": true, + "requires": { + "ip-regex": "1.0.3" + } + }, + "user-home": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", + "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "dev": true + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "uuid": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", + "dev": true, + "optional": true + }, + "v8flags": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", + "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "dev": true, + "requires": { + "user-home": "1.1.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", + "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "dev": true, + "requires": { + "spdx-correct": "1.0.2", + "spdx-expression-parse": "1.0.4" + } + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "optional": true, + "requires": { + "assert-plus": "1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "1.3.0" + }, + "dependencies": { + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "optional": true + } + } + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-bufferstream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", + "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=", + "dev": true, + "requires": { + "bufferstreams": "1.0.1" + } + }, + "vinyl-file": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-1.3.0.tgz", + "integrity": "sha1-qgVjTTqGe6kUR77bs0r8sm9E9uc=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "strip-bom": "2.0.0", + "strip-bom-stream": "1.0.0", + "vinyl": "1.2.0" + }, + "dependencies": { + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "1.0.3", + "clone-stats": "0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "vinyl-fs": { + "version": "0.3.14", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", + "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", + "dev": true, + "requires": { + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "graceful-fs": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", + "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "dev": true, + "requires": { + "natives": "1.1.0" + } + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "0.2.0", + "clone-stats": "0.0.1" + } + } + } + }, + "vinyl-sourcemaps-apply": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", + "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", + "dev": true, + "requires": { + "source-map": "0.5.7" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + } + } + }, + "when": { + "version": "3.7.8", + "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", + "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", + "dev": true + }, + "which": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "dev": true, + "requires": { + "isexe": "2.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "dev": true + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "dev": true, + "requires": { + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", + "window-size": "0.1.0" + } + }, + "yarn": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.3.2.tgz", + "integrity": "sha1-WTl2JYG1tN3NNBjA9r5C3zruGV8=", + "dev": true + } + } +} diff --git a/build/package.json b/build/package.json index c00a2090f..6cfae3c9b 100755 --- a/build/package.json +++ b/build/package.json @@ -1,32 +1,24 @@ { - "name": "@userfrosting/userfrosting", - "version": "4.1.0", - "description": "Build tool for UF 4.1", - "main": "index.js", - "repository": { - "type": "git", - "url": "https://github.com/userfrosting/userfrosting" - }, - "author": "Alex Weissman", - "license": "MIT", + "private": true, "devDependencies": { + "@userfrosting/merge-package-dependencies": "^1.1.0", + "bower": "^1.8.0", + "del": "^2.2.2", + "dotenv": "^4.0.0", + "fs-extra": "^4.0.0", "gulp": "^3.9.1", - "gulp-uf-bundle-assets": "^2.27.2", "gulp-load-plugins": "^1.4.0", + "gulp-uf-bundle-assets": "^2.27.2", "merge-array-object": "^1.0.3", "recursive-copy": "^2.0.5", - "del": "^2.2.2", - "shelljs": "^0.7.6", - "bower": "^1.8.0", - "gulp-src-ordered-globs": "^1.0.3", - "gulp-copy": "^1.0.0" + "yarn": "^1.3.2" }, "scripts": { "uf-bundle-build": "gulp bundle-build", "uf-bundle": "gulp bundle", + "uf-assets-install": "gulp assets-install", "uf-bundle-clean": "gulp bundle-clean", - "uf-assets-install": "gulp bower-install", - "uf-assets-clean": "gulp bower-clean", + "uf-assets-clean": "gulp assets-clean", "uf-public-clean": "gulp public-clean", "uf-clean": "gulp clean" } From 3f1be6a19faa4d981cd83704fa02d5c5602b06eb Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Wed, 13 Dec 2017 12:03:24 +1100 Subject: [PATCH 006/237] Complete internal docs for `RawAssetBundles` --- app/sprinkles/core/src/Util/RawAssetBundles.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index cf978225d..0ed207774 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -20,10 +20,9 @@ class RawAssetBundles extends GulpBundleAssetsRawBundles { /** - * Undocumented function + * Extends the currently loaded bundles with another bundle schema. * - * @param [type] $filePath - * @return void + * @param string * * @throws FileNotFoundException if file cannot be found. * @throws JsonException if file cannot be parsed as JSON. From b061f3b1681784178ee480a90f903901bda76074 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Wed, 13 Dec 2017 20:03:21 +1100 Subject: [PATCH 007/237] Merged bundle file should be `bundle.config.json` not `asset-bundles.json` --- build/gulpfile.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index b55851f2b..63cef174f 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -30,10 +30,10 @@ const sprinkles = require(`${sprinklesSchemaPath}`)['base']; const publicAssetsDir = '../public/assets/'; // name of the bundle file -const bundleFile = 'asset-bundles.json'; +const sprinkleBundleFile = 'asset-bundles.json'; -// Compiled bundle config file -const bundleConfigFile = `./${bundleFile}`; +// Merged bundle config file with relative dir +const bundleConfigFile = './bundle.config.json'; /** * Vendor asset task @@ -158,8 +158,9 @@ gulp.task('bundle-build', () => { sprinkles.forEach((sprinkle) => { 'use strict'; let location = `${sprinklesDir}/${sprinkle}/`; - if (fs.existsSync(`${location}${bundleFile}`)) { - let currentConfig = require(`${location}${bundleFile}`); + if (fs.existsSync(`${location}${sprinkleBundleFile}`)) { + // Require shouldn't be used here. + let currentConfig = require(`${location}${sprinkleBundleFile}`); // Add bundles to config, respecting collision rules. for (let bundleName in currentConfig.bundle) { // If bundle already defined, handle as per collision rules. From ed594f4e01c790ead96f571da12aee1cdc51e254 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Thu, 14 Dec 2017 15:48:49 +1100 Subject: [PATCH 008/237] Respect `Accept-Language` header when not logged in (partially resolves #718) --- app/sprinkles/core/config/default.php | 3 +- .../src/ServicesProvider/ServicesProvider.php | 32 ++++++++++++++++++- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 245c5db6e..279fee83b 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -149,7 +149,8 @@ 'it_IT' => 'Italiano', 'th_TH' => 'ภาษาไทย' ], - // This can be a comma-separated list, to load multiple fallback locales + // This can be a comma-separated list, to load multiple fallback locales. + // Supported browser requested languages always have first preference. 'default' => 'en_US' ], 'title' => 'UserFrosting', diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 352ee0dac..a7164f3e6 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -420,15 +420,45 @@ public function register(ContainerInterface $container) */ $container['localePathBuilder'] = function ($c) { $config = $c->config; + $request = $c->request; // Make sure the locale config is a valid string if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { throw new \UnexpectedValueException('The locale config is not a valid string.'); } - // Load the base locale file(s) as specified in the configuration + // Get default locales as specified in configurations. $locales = explode(',', $config['site.locales.default']); + // Add supported browser preferred locales. + if ($request->hasHeader('Accept-Language')) { + $allowedLocales = []; + foreach (explode(',', $request->getHeaderLine('Accept-Language')) as $index => $browserLocale) { + // Split to access q + $parts = explode(';', $browserLocale) ?: []; + + // Ensure locale valid, and available + if (array_key_exists(0, $parts) && array_key_exists($parts[0], $config['site.locales.available'])) { + // Determine preference level, and add to $allowedLocales + if (array_key_exists(1, $parts)) { + $parts[1] = str_replace('q=', '', $parts[1]); + $parts[1] = is_numeric($parts[1]) ?: 0; + } else { + $parts[1] = 1; + } + // Add to list, and format for UF's i18n. + $allowedLocales[str_replace('-', '_', $parts[0])] = $parts[1]; + } + } + + // Sort, extract keys, and merge with $locales + asort($allowedLocales, SORT_NUMERIC); + $locales = array_merge($locales, array_keys($allowedLocales)); + + // Remove duplicates, while maintaining fallback order + $locales = array_reverse(array_unique(array_reverse($locales))); + } + return new LocalePathBuilder($c->locator, 'locale://', $locales); }; From 2d1323bd7b33d9f8d1c89e96d32b7869f581adc7 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Thu, 14 Dec 2017 18:05:34 +1100 Subject: [PATCH 009/237] Resolves #718 - Fixed issue where language preference wasn't properly applied due to a bad type check. - Added locales field to register page. --- .../account/schema/requests/register.yaml | 156 +- .../src/Controller/AccountController.php | 2399 +++++++++-------- .../templates/pages/register.html.twig | 221 +- .../src/ServicesProvider/ServicesProvider.php | 1334 ++++----- 4 files changed, 2071 insertions(+), 2039 deletions(-) diff --git a/app/sprinkles/account/schema/requests/register.yaml b/app/sprinkles/account/schema/requests/register.yaml index 75dae592a..7faf72654 100644 --- a/app/sprinkles/account/schema/requests/register.yaml +++ b/app/sprinkles/account/schema/requests/register.yaml @@ -1,75 +1,81 @@ ---- -user_name: - validators: - length: - label: "&USERNAME" - min: 1 - max: 50 - message: VALIDATE.LENGTH_RANGE - no_leading_whitespace: - label: "&USERNAME" - message: VALIDATE.NO_LEAD_WS - no_trailing_whitespace: - label: "&USERNAME" - message: VALIDATE.NO_TRAIL_WS - required: - label: "&USERNAME" - message: VALIDATE.REQUIRED - username: - label: "&USERNAME" - message: VALIDATE.USERNAME -first_name: - validators: - length: - label: "&FIRST_NAME" - min: 1 - max: 20 - message: VALIDATE.LENGTH_RANGE - required: - label: "&FIRST_NAME" - message: VALIDATE.REQUIRED -last_name: - validators: - length: - label: "&LAST_NAME" - min: 1 - max: 30 - message: VALIDATE.LENGTH_RANGE -email: - validators: - required: - label: "&EMAIL" - message: VALIDATE.REQUIRED - length: - label: "&EMAIL" - min: 1 - max: 150 - message: VALIDATE.LENGTH_RANGE - email: - message: VALIDATE.INVALID_EMAIL -password: - validators: - required: - label: "&PASSWORD" - message: VALIDATE.REQUIRED - length: - label: "&PASSWORD" - min: 12 - max: 100 - message: VALIDATE.LENGTH_RANGE -passwordc: - validators: - required: - label: "&PASSWORD.CONFIRM" - message: VALIDATE.REQUIRED - matches: - field: password - label: "&PASSWORD.CONFIRM" - message: VALIDATE.PASSWORD_MISMATCH - length: - label: "&PASSWORD.CONFIRM" - min: 12 - max: 100 - message: VALIDATE.LENGTH_RANGE -captcha: - validators: +--- +user_name: + validators: + length: + label: "&USERNAME" + min: 1 + max: 50 + message: VALIDATE.LENGTH_RANGE + no_leading_whitespace: + label: "&USERNAME" + message: VALIDATE.NO_LEAD_WS + no_trailing_whitespace: + label: "&USERNAME" + message: VALIDATE.NO_TRAIL_WS + required: + label: "&USERNAME" + message: VALIDATE.REQUIRED + username: + label: "&USERNAME" + message: VALIDATE.USERNAME +first_name: + validators: + length: + label: "&FIRST_NAME" + min: 1 + max: 20 + message: VALIDATE.LENGTH_RANGE + required: + label: "&FIRST_NAME" + message: VALIDATE.REQUIRED +last_name: + validators: + length: + label: "&LAST_NAME" + min: 1 + max: 30 + message: VALIDATE.LENGTH_RANGE +email: + validators: + required: + label: "&EMAIL" + message: VALIDATE.REQUIRED + length: + label: "&EMAIL" + min: 1 + max: 150 + message: VALIDATE.LENGTH_RANGE + email: + message: VALIDATE.INVALID_EMAIL +password: + validators: + required: + label: "&PASSWORD" + message: VALIDATE.REQUIRED + length: + label: "&PASSWORD" + min: 12 + max: 100 + message: VALIDATE.LENGTH_RANGE +passwordc: + validators: + required: + label: "&PASSWORD.CONFIRM" + message: VALIDATE.REQUIRED + matches: + field: password + label: "&PASSWORD.CONFIRM" + message: VALIDATE.PASSWORD_MISMATCH + length: + label: "&PASSWORD.CONFIRM" + min: 12 + max: 100 + message: VALIDATE.LENGTH_RANGE +locale: + validators: + required: + label: "&LOCALE" + domain: server + message: VALIDATE.REQUIRED +captcha: + validators: diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 1a6c85cbd..b4ad6ac7d 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -1,1195 +1,1204 @@ -ci->alerts; - - // GET parameters - $params = $request->getQueryParams(); - - // Load request schema - $schema = new RequestSchema('schema://requests/check-username.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - // TODO: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException - $e = new BadRequestException('Missing or malformed request data!'); - foreach ($validator->errors() as $idx => $field) { - foreach($field as $eidx => $error) { - $e->addUserMessage($error); - } - } - throw $e; - } - - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - $delay = $throttler->getDelay('check_username_request'); - - // Throttle requests - if ($delay > 0) { - return $response->withStatus(429); - } - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var UserFrosting\I18n\MessageTranslator $translator */ - $translator = $this->ci->translator; - - // Log throttleable event - $throttler->logEvent('check_username_request'); - - if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) { - $message = $translator->translate('USERNAME.NOT_AVAILABLE', $data); - return $response->write($message)->withStatus(200); - } else { - return $response->write('true')->withStatus(200); - } - } - - /** - * Processes a request to cancel a password reset request. - * - * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves. - * Processes the request from the password reset link, checking that: - * 1. The provided token is associated with an existing user account, who has a pending password reset request. - * Request type: GET - */ - public function denyResetPassword($request, $response, $args) - { - // GET parameters - $params = $request->getQueryParams(); - - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - $loginPage = $this->ci->router->pathFor('login'); - - // Load validation rules - $schema = new RequestSchema('schema://requests/deny-password.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Since this is a GET request, we need to redirect on failure - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel - return $response->withRedirect($loginPage, 400); - } - - $passwordReset = $this->ci->repoPasswordReset->cancel($data['token']); - - if (!$passwordReset) { - $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID'); - return $response->withRedirect($loginPage, 400); - } - - $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_CANNED'); - return $response->withRedirect($loginPage); - } - - /** - * Processes a request to email a forgotten password reset link to the user. - * - * Processes the request from the form on the "forgot password" page, checking that: - * 1. The rate limit for this type of request is being observed. - * 2. The provided email address belongs to a registered account; - * 3. The submitted data is valid. - * Note that we have removed the requirement that a password reset request not already be in progress. - * This is because we need to allow users to re-request a reset, even if they lose the first reset email. - * This route is "public access". - * Request type: POST - * @todo require additional user information - * @todo prevent password reset requests for root account? - */ - public function forgotPassword($request, $response, $args) - { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - // Get POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/forgot-password.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } - - // Throttle requests - - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - - $throttleData = [ - 'email' => $data['email'] - ]; - $delay = $throttler->getDelay('password_reset_request', $throttleData); - - if ($delay > 0) { - $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); - return $response->withStatus(429); - } - - // All checks passed! log events/activities, update user, and send email - // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $throttler, $throttleData, $config) { - - // Log throttleable event - $throttler->logEvent('password_reset_request', $throttleData); - - // Load the user, by email address - $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first(); - - // Check that the email exists. - // If there is no user with that email address, we should still pretend like we succeeded, to prevent account enumeration - if ($user) { - // Try to generate a new password reset request. - // Use timeout for "reset password" - $passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']); - - // Create and send email - $message = new TwigMailMessage($this->ci->view, 'mail/password-reset.html.twig'); - $message->from($config['address_book.admin']) - ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) - ->addParams([ - 'user' => $user, - 'token' => $passwordReset->getToken(), - 'request_date' => Carbon::now()->format('Y-m-d H:i:s') - ]); - - $this->ci->mailer->send($message); - } - }); - - // TODO: create delay to prevent timing-based attacks - - $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', ['email' => $data['email']]); - return $response->withStatus(200); - } - - /** - * Returns a modal containing account terms of service. - * - * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages. - * Request type: GET - */ - public function getModalAccountTos($request, $response, $args) - { - return $this->ci->view->render($response, 'modals/tos.html.twig'); - } - - /** - * Generate a random captcha, store it to the session, and return the captcha image. - * - * Request type: GET - */ - public function imageCaptcha($request, $response, $args) - { - $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']); - $captcha->generateRandomCode(); - - return $response->withStatus(200) - ->withHeader('Content-Type', 'image/png;base64') - ->write($captcha->getImage()); - } - - /** - * Processes an account login request. - * - * Processes the request from the form on the login page, checking that: - * 1. The user is not already logged in. - * 2. The rate limit for this type of request is being observed. - * 3. Email login is enabled, if an email address was used. - * 4. The user account exists. - * 5. The user account is enabled and verified. - * 6. The user entered a valid username/email and password. - * This route, by definition, is "public access". - * Request type: POST - */ - public function login($request, $response, $args) - { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ - $currentUser = $this->ci->currentUser; - - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Return 200 success if user is already logged in - if ($authenticator->check()) { - $ms->addMessageTranslated('warning', 'LOGIN.ALREADY_COMPLETE'); - return $response->withStatus(200); - } - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - // Get POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/login.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } - - // Determine whether we are trying to log in with an email address or a username - $isEmail = filter_var($data['user_name'], FILTER_VALIDATE_EMAIL); - - // Throttle requests - - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - - $userIdentifier = $data['user_name']; - - $throttleData = [ - 'user_identifier' => $userIdentifier - ]; - - $delay = $throttler->getDelay('sign_in_attempt', $throttleData); - if ($delay > 0) { - $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', [ - 'delay' => $delay - ]); - return $response->withStatus(429); - } - - // Log throttleable event - $throttler->logEvent('sign_in_attempt', $throttleData); - - // If credential is an email address, but email login is not enabled, raise an error. - // Note that we do this after logging throttle event, so this error counts towards throttling limit. - if ($isEmail && !$config['site.login.enable_email']) { - $ms->addMessageTranslated('danger', 'USER_OR_PASS_INVALID'); - return $response->withStatus(403); - } - - // Try to authenticate the user. Authenticator will throw an exception on failure. - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - $currentUser = $authenticator->attempt(($isEmail ? 'email' : 'user_name'), $userIdentifier, $data['password'], $data['rememberme']); - - $ms->addMessageTranslated('success', 'WELCOME', $currentUser->export()); - - // Set redirect, if relevant - $redirectOnLogin = $this->ci->get('redirect.onLogin'); - - return $redirectOnLogin($request, $response, $args); - } - - /** - * Log the user out completely, including destroying any "remember me" token. - * - * Request type: GET - */ - public function logout(Request $request, Response $response, $args) - { - // Destroy the session - $this->ci->authenticator->logout(); - - // Return to home page - $config = $this->ci->config; - return $response->withStatus(302)->withHeader('Location', $config['site.uri.public']); - } - - /** - * Render the "forgot password" page. - * - * This creates a simple form to allow users who forgot their password to have a time-limited password reset link emailed to them. - * By default, this is a "public page" (does not require authentication). - * Request type: GET - */ - public function pageForgotPassword($request, $response, $args) - { - // Load validation rules - $schema = new RequestSchema('schema://requests/forgot-password.yaml'); - $validator = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/forgot-password.html.twig', [ - 'page' => [ - 'validators' => [ - 'forgot_password' => $validator->rules('json', false) - ] - ] - ]); - } - - - /** - * Render the account registration page for UserFrosting. - * - * This allows new (non-authenticated) users to create a new account for themselves on your website (if enabled). - * By definition, this is a "public page" (does not require authentication). - * Request type: GET - */ - public function pageRegister($request, $response, $args) - { - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - if (!$config['site.registration.enabled']) { - throw new NotFoundException($request, $response); - } - - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Redirect if user is already logged in - if ($authenticator->check()) { - $redirect = $this->ci->get('redirect.onAlreadyLoggedIn'); - - return $redirect($request, $response, $args); - } - - // Load validation rules - $schema = new RequestSchema('schema://requests/register.yaml'); - $validatorRegister = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/register.html.twig', [ - 'page' => [ - 'validators' => [ - 'register' => $validatorRegister->rules('json', false) - ] - ] - ]); - } - - /** - * Render the "resend verification email" page. - * - * This is a form that allows users who lost their account verification link to have the link resent to their email address. - * By default, this is a "public page" (does not require authentication). - * Request type: GET - */ - public function pageResendVerification($request, $response, $args) - { - // Load validation rules - $schema = new RequestSchema('schema://requests/resend-verification.yaml'); - $validator = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/resend-verification.html.twig', [ - 'page' => [ - 'validators' => [ - 'resend_verification' => $validator->rules('json', false) - ] - ] - ]); - } - - /** - * Reset password page. - * - * Renders the new password page for password reset requests. - * Request type: GET - */ - public function pageResetPassword($request, $response, $args) - { - // Insert the user's secret token from the link into the password reset form - $params = $request->getQueryParams(); - - // Load validation rules - note this uses the same schema as "set password" - $schema = new RequestSchema('schema://requests/set-password.yaml'); - $validator = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/reset-password.html.twig', [ - 'page' => [ - 'validators' => [ - 'set_password' => $validator->rules('json', false) - ] - ], - 'token' => isset($params['token']) ? $params['token'] : '', - ]); - } - - /** - * Render the "set password" page. - * - * Renders the page where new users who have had accounts created for them by another user, can set their password. - * By default, this is a "public page" (does not require authentication). - * Request type: GET - */ - public function pageSetPassword($request, $response, $args) - { - // Insert the user's secret token from the link into the password set form - $params = $request->getQueryParams(); - - // Load validation rules - $schema = new RequestSchema('schema://requests/set-password.yaml'); - $validator = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/set-password.html.twig', [ - 'page' => [ - 'validators' => [ - 'set_password' => $validator->rules('json', false) - ] - ], - 'token' => isset($params['token']) ? $params['token'] : '', - ]); - } - - /** - * Account settings page. - * - * Provides a form for users to modify various properties of their account, such as name, email, locale, etc. - * Any fields that the user does not have permission to modify will be automatically disabled. - * This page requires authentication. - * Request type: GET - */ - public function pageSettings($request, $response, $args) - { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ - $authorizer = $this->ci->authorizer; - - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ - $currentUser = $this->ci->currentUser; - - // Access-controlled page - if (!$authorizer->checkAccess($currentUser, 'uri_account_settings')) { - throw new ForbiddenException(); - } - - // Load validation rules - $schema = new RequestSchema('schema://requests/account-settings.yaml'); - $validatorAccountSettings = new JqueryValidationAdapter($schema, $this->ci->translator); - - $schema = new RequestSchema('schema://requests/profile-settings.yaml'); - $validatorProfileSettings = new JqueryValidationAdapter($schema, $this->ci->translator); - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - // Get a list of all locales - $locales = $config->getDefined('site.locales.available'); - - return $this->ci->view->render($response, 'pages/account-settings.html.twig', [ - 'locales' => $locales, - 'page' => [ - 'validators' => [ - 'account_settings' => $validatorAccountSettings->rules('json', false), - 'profile_settings' => $validatorProfileSettings->rules('json', false) - ], - 'visibility' => ($authorizer->checkAccess($currentUser, 'update_account_settings') ? '' : 'disabled') - ] - ]); - } - - /** - * Render the account sign-in page for UserFrosting. - * - * This allows existing users to sign in. - * By definition, this is a "public page" (does not require authentication). - * Request type: GET - */ - public function pageSignIn($request, $response, $args) - { - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Redirect if user is already logged in - if ($authenticator->check()) { - $redirect = $this->ci->get('redirect.onAlreadyLoggedIn'); - - return $redirect($request, $response, $args); - } - - // Load validation rules - $schema = new RequestSchema('schema://requests/login.yaml'); - $validatorLogin = new JqueryValidationAdapter($schema, $this->ci->translator); - - return $this->ci->view->render($response, 'pages/sign-in.html.twig', [ - 'page' => [ - 'validators' => [ - 'login' => $validatorLogin->rules('json', false) - ] - ] - ]); - } - - /** - * Processes a request to update a user's profile information. - * - * Processes the request from the user profile settings form, checking that: - * 1. They have the necessary permissions to update the posted field(s); - * 2. The submitted data is valid. - * This route requires authentication. - * Request type: POST - */ - public function profile($request, $response, $args) - { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ - $authorizer = $this->ci->authorizer; - - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ - $currentUser = $this->ci->currentUser; - - // Access control for entire resource - check that the current user has permission to modify themselves - // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. - if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { - $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); - return $response->withStatus(403); - } - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - // POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/profile-settings.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - $error = false; - - // Validate, and halt on validation errors. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - $error = true; - } - - // Check that locale is valid - $locales = $config->getDefined('site.locales.available'); - if (!array_key_exists($data['locale'], $locales)) { - $ms->addMessageTranslated('danger', 'LOCALE.INVALID', $data); - $error = true; - } - - if ($error) { - return $response->withStatus(400); - } - - // Looks good, let's update with new values! - // Note that only fields listed in `profile-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB - $currentUser->fill($data); - - $currentUser->save(); - - // Create activity record - $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their profile settings.", [ - 'type' => 'update_profile_settings' - ]); - - $ms->addMessageTranslated('success', 'PROFILE.UPDATED'); - return $response->withStatus(200); - } - - /** - * Processes an new account registration request. - * - * This is throttled to prevent account enumeration, since it needs to divulge when a username/email has been used. - * Processes the request from the form on the registration page, checking that: - * 1. The honeypot was not modified; - * 2. The master account has already been created (during installation); - * 3. Account registration is enabled; - * 4. The user is not already logged in; - * 5. Valid information was entered; - * 6. The captcha, if enabled, is correct; - * 7. The username and email are not already taken. - * Automatically sends an activation link upon success, if account activation is enabled. - * This route is "public access". - * Request type: POST - * Returns the User Object for the user record that was created. - */ - public function register(Request $request, Response $response, $args) - { - /** @var MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - // Get POST parameters: user_name, first_name, last_name, email, password, passwordc, captcha, spiderbro, csrf_token - $params = $request->getParsedBody(); - - // Check the honeypot. 'spiderbro' is not a real field, it is hidden on the main page and must be submitted with its default value for this to be processed. - if (!isset($params['spiderbro']) || $params['spiderbro'] != 'http://') { - throw new SpammyRequestException('Possible spam received:' . print_r($params, true)); - } - - // Security measure: do not allow registering new users until the master account has been created. - if (!$classMapper->staticMethod('user', 'find', $config['reserved_user_ids.master'])) { - $ms->addMessageTranslated('danger', 'ACCOUNT.MASTER_NOT_EXISTS'); - return $response->withStatus(403); - } - - // Check if registration is currently enabled - if (!$config['site.registration.enabled']) { - $ms->addMessageTranslated('danger', 'REGISTRATION.DISABLED'); - return $response->withStatus(403); - } - - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Prevent the user from registering if he/she is already logged in - if ($authenticator->check()) { - $ms->addMessageTranslated('danger', 'REGISTRATION.LOGOUT'); - return $response->withStatus(403); - } - - // Load the request schema - $schema = new RequestSchema('schema://requests/register.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - $error = false; - - // Validate request data - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - $error = true; - } - - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - $delay = $throttler->getDelay('registration_attempt'); - - // Throttle requests - if ($delay > 0) { - return $response->withStatus(429); - } - - // Check if username or email already exists - if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) { - $ms->addMessageTranslated('danger', 'USERNAME.IN_USE', $data); - $error = true; - } - - if ($classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) { - $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data); - $error = true; - } - - // Check captcha, if required - if ($config['site.registration.captcha']) { - $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']); - if (!$data['captcha'] || !$captcha->verifyCode($data['captcha'])) { - $ms->addMessageTranslated('danger', 'CAPTCHA.FAIL'); - $error = true; - } - } - - if ($error) { - return $response->withStatus(400); - } - - // Remove captcha, password confirmation from object data after validation - unset($data['captcha']); - unset($data['passwordc']); - - if ($config['site.registration.require_email_verification']) { - $data['flag_verified'] = false; - } else { - $data['flag_verified'] = true; - } - - // Load default group - $groupSlug = $config['site.registration.user_defaults.group']; - $defaultGroup = $classMapper->staticMethod('group', 'where', 'slug', $groupSlug)->first(); - - if (!$defaultGroup) { - $e = new HttpException("Account registration is not working because the default group '$groupSlug' does not exist."); - $e->addUserMessage('ACCOUNT.REGISTRATION_BROKEN'); - throw $e; - } - - // Set default group - $data['group_id'] = $defaultGroup->id; - - // Set default locale - $data['locale'] = $config['site.registration.user_defaults.locale']; - - // Hash password - $data['password'] = Password::hash($data['password']); - - // All checks passed! log events/activities, create user, and send verification email (if required) - // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $ms, $config, $throttler) { - // Log throttleable event - $throttler->logEvent('registration_attempt'); - - // Create the user - $user = $classMapper->createInstance('user', $data); - - // Store new user to database - $user->save(); - - // Create activity record - $this->ci->userActivityLogger->info("User {$user->user_name} registered for a new account.", [ - 'type' => 'sign_up', - 'user_id' => $user->id - ]); - - // Load default roles - $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs'); - $defaultRoles = $classMapper->staticMethod('role', 'whereIn', 'slug', $defaultRoleSlugs)->get(); - $defaultRoleIds = $defaultRoles->pluck('id')->all(); - - // Attach default roles - $user->roles()->attach($defaultRoleIds); - - // Verification email - if ($config['site.registration.require_email_verification']) { - // Try to generate a new verification request - $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']); - - // Create and send verification email - $message = new TwigMailMessage($this->ci->view, 'mail/verify-account.html.twig'); - - $message->from($config['address_book.admin']) - ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) - ->addParams([ - 'user' => $user, - 'token' => $verification->getToken() - ]); - - $this->ci->mailer->send($message); - - $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE2', $user->toArray()); - } else { - // No verification required - $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE1'); - } - }); - - return $response->withStatus(200); - } - - /** - * Processes a request to resend the verification email for a new user account. - * - * Processes the request from the resend verification email form, checking that: - * 1. The rate limit on this type of request is observed; - * 2. The provided email is associated with an existing user account; - * 3. The user account is not already verified; - * 4. The submitted data is valid. - * This route is "public access". - * Request type: POST - */ - public function resendVerification($request, $response, $args) - { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - // Get POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/resend-verification.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } - - // Throttle requests - - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ - $throttler = $this->ci->throttler; - - $throttleData = [ - 'email' => $data['email'] - ]; - $delay = $throttler->getDelay('verification_request', $throttleData); - - if ($delay > 0) { - $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); - return $response->withStatus(429); - } - - // All checks passed! log events/activities, create user, and send verification email (if required) - // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $throttler, $throttleData, $config) { - // Log throttleable event - $throttler->logEvent('verification_request', $throttleData); - - // Load the user, by email address - $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first(); - - // Check that the user exists and is not already verified. - // If there is no user with that email address, or the user exists and is already verified, - // we pretend like we succeeded to prevent account enumeration - if ($user && $user->flag_verified != '1') { - // We're good to go - record user activity and send the email - $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']); - - // Create and send verification email - $message = new TwigMailMessage($this->ci->view, 'mail/resend-verification.html.twig'); - - $message->from($config['address_book.admin']) - ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) - ->addParams([ - 'user' => $user, - 'token' => $verification->getToken() - ]); - - $this->ci->mailer->send($message); - } - }); - - $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.NEW_LINK_SENT', ['email' => $data['email']]); - return $response->withStatus(200); - } - - /** - * Processes a request to set the password for a new or current user. - * - * Processes the request from the password create/reset form, which should have the secret token embedded in it, checking that: - * 1. The provided secret token is associated with an existing user account; - * 2. The user has a password set/reset request in progress; - * 3. The token has not expired; - * 4. The submitted data (new password) is valid. - * This route is "public access". - * Request type: POST - */ - public function setPassword(Request $request, Response $response, $args) - { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - // Get POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/set-password.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - return $response->withStatus(400); - } - - $forgotPasswordPage = $this->ci->router->pathFor('forgot-password'); - - // Ok, try to complete the request with the specified token and new password - $passwordReset = $this->ci->repoPasswordReset->complete($data['token'], [ - 'password' => $data['password'] - ]); - - if (!$passwordReset) { - $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID', ['url' => $forgotPasswordPage]); - return $response->withStatus(400); - } - - $ms->addMessageTranslated('success', 'PASSWORD.UPDATED'); - - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $this->ci->authenticator; - - // Log out any existing user, and create a new session - if ($authenticator->check()) { - $authenticator->logout(); - } - - // Auto-login the user (without "remember me") - $user = $passwordReset->user; - $authenticator->login($user); - - $ms->addMessageTranslated('success', 'WELCOME', $user->export()); - return $response->withStatus(200); - } - - /** - * Processes a request to update a user's account information. - * - * Processes the request from the user account settings form, checking that: - * 1. The user correctly input their current password; - * 2. They have the necessary permissions to update the posted field(s); - * 3. The submitted data is valid. - * This route requires authentication. - * Request type: POST - */ - public function settings($request, $response, $args) - { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ - $authorizer = $this->ci->authorizer; - - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ - $currentUser = $this->ci->currentUser; - - // Access control for entire resource - check that the current user has permission to modify themselves - // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. - if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { - $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); - return $response->withStatus(403); - } - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - // POST parameters - $params = $request->getParsedBody(); - - // Load the request schema - $schema = new RequestSchema('schema://requests/account-settings.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - $error = false; - - // Validate, and halt on validation errors. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - $error = true; - } - - // Confirm current password - if (!isset($data['passwordcheck']) || !Password::verify($data['passwordcheck'], $currentUser->password)) { - $ms->addMessageTranslated('danger', 'PASSWORD.INVALID'); - $error = true; - } - - // Remove password check, password confirmation from object data after validation - unset($data['passwordcheck']); - unset($data['passwordc']); - - // If new email was submitted, check that the email address is not in use - if (isset($data['email']) && $data['email'] != $currentUser->email && $classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) { - $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data); - $error = true; - } - - if ($error) { - return $response->withStatus(400); - } - - // Hash new password, if specified - if (isset($data['password']) && !empty($data['password'])) { - $data['password'] = Password::hash($data['password']); - } else { - // Do not pass to model if no password is specified - unset($data['password']); - } - - // Looks good, let's update with new values! - // Note that only fields listed in `account-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB - $currentUser->fill($data); - - $currentUser->save(); - - // Create activity record - $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their account settings.", [ - 'type' => 'update_account_settings' - ]); - - $ms->addMessageTranslated('success', 'ACCOUNT.SETTINGS.UPDATED'); - return $response->withStatus(200); - } - - /** - * Suggest an available username for a specified first/last name. - * - * This route is "public access". - * Request type: GET - * @todo Can this route be abused for account enumeration? If so we should throttle it as well. - */ - public function suggestUsername($request, $response, $args) - { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - $suggestion = AccountUtil::randomUniqueUsername($classMapper, 50, 10); - - // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content. - // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating). - return $response->withJson([ - 'user_name' => $suggestion - ], 200, JSON_PRETTY_PRINT); - } - - /** - * Processes an new email verification request. - * - * Processes the request from the email verification link that was emailed to the user, checking that: - * 1. The token provided matches a user in the database; - * 2. The user account is not already verified; - * This route is "public access". - * Request type: GET - */ - public function verify($request, $response, $args) - { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ - $ms = $this->ci->alerts; - - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ - $classMapper = $this->ci->classMapper; - - /** @var UserFrosting\Config\Config $config */ - $config = $this->ci->config; - - $loginPage = $this->ci->router->pathFor('login'); - - // GET parameters - $params = $request->getQueryParams(); - - // Load request schema - $schema = new RequestSchema('schema://requests/account-verify.yaml'); - - // Whitelist and set parameter defaults - $transformer = new RequestDataTransformer($schema); - $data = $transformer->transform($params); - - // Validate, and halt on validation errors. This is a GET request, so we redirect on validation error. - $validator = new ServerSideValidator($schema, $this->ci->translator); - if (!$validator->validate($data)) { - $ms->addValidationErrors($validator); - // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel - return $response->withRedirect($loginPage, 400); - } - - $verification = $this->ci->repoVerification->complete($data['token']); - - if (!$verification) { - $ms->addMessageTranslated('danger', 'ACCOUNT.VERIFICATION.TOKEN_NOT_FOUND'); - return $response->withRedirect($loginPage, 400); - } - - $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.COMPLETE'); - - // Forward to login page - return $response->withRedirect($loginPage); - } -} +ci->alerts; + + // GET parameters + $params = $request->getQueryParams(); + + // Load request schema + $schema = new RequestSchema('schema://requests/check-username.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + // Validate, and halt on validation errors. + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + // TODO: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException + $e = new BadRequestException('Missing or malformed request data!'); + foreach ($validator->errors() as $idx => $field) { + foreach($field as $eidx => $error) { + $e->addUserMessage($error); + } + } + throw $e; + } + + /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + $throttler = $this->ci->throttler; + $delay = $throttler->getDelay('check_username_request'); + + // Throttle requests + if ($delay > 0) { + return $response->withStatus(429); + } + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + /** @var UserFrosting\I18n\MessageTranslator $translator */ + $translator = $this->ci->translator; + + // Log throttleable event + $throttler->logEvent('check_username_request'); + + if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) { + $message = $translator->translate('USERNAME.NOT_AVAILABLE', $data); + return $response->write($message)->withStatus(200); + } else { + return $response->write('true')->withStatus(200); + } + } + + /** + * Processes a request to cancel a password reset request. + * + * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves. + * Processes the request from the password reset link, checking that: + * 1. The provided token is associated with an existing user account, who has a pending password reset request. + * Request type: GET + */ + public function denyResetPassword($request, $response, $args) + { + // GET parameters + $params = $request->getQueryParams(); + + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + $loginPage = $this->ci->router->pathFor('login'); + + // Load validation rules + $schema = new RequestSchema('schema://requests/deny-password.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + // Validate, and halt on validation errors. Since this is a GET request, we need to redirect on failure + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel + return $response->withRedirect($loginPage, 400); + } + + $passwordReset = $this->ci->repoPasswordReset->cancel($data['token']); + + if (!$passwordReset) { + $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID'); + return $response->withRedirect($loginPage, 400); + } + + $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_CANNED'); + return $response->withRedirect($loginPage); + } + + /** + * Processes a request to email a forgotten password reset link to the user. + * + * Processes the request from the form on the "forgot password" page, checking that: + * 1. The rate limit for this type of request is being observed. + * 2. The provided email address belongs to a registered account; + * 3. The submitted data is valid. + * Note that we have removed the requirement that a password reset request not already be in progress. + * This is because we need to allow users to re-request a reset, even if they lose the first reset email. + * This route is "public access". + * Request type: POST + * @todo require additional user information + * @todo prevent password reset requests for root account? + */ + public function forgotPassword($request, $response, $args) + { + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + // Get POST parameters + $params = $request->getParsedBody(); + + // Load the request schema + $schema = new RequestSchema('schema://requests/forgot-password.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + return $response->withStatus(400); + } + + // Throttle requests + + /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + $throttler = $this->ci->throttler; + + $throttleData = [ + 'email' => $data['email'] + ]; + $delay = $throttler->getDelay('password_reset_request', $throttleData); + + if ($delay > 0) { + $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); + return $response->withStatus(429); + } + + // All checks passed! log events/activities, update user, and send email + // Begin transaction - DB will be rolled back if an exception occurs + Capsule::transaction( function() use ($classMapper, $data, $throttler, $throttleData, $config) { + + // Log throttleable event + $throttler->logEvent('password_reset_request', $throttleData); + + // Load the user, by email address + $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first(); + + // Check that the email exists. + // If there is no user with that email address, we should still pretend like we succeeded, to prevent account enumeration + if ($user) { + // Try to generate a new password reset request. + // Use timeout for "reset password" + $passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']); + + // Create and send email + $message = new TwigMailMessage($this->ci->view, 'mail/password-reset.html.twig'); + $message->from($config['address_book.admin']) + ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) + ->addParams([ + 'user' => $user, + 'token' => $passwordReset->getToken(), + 'request_date' => Carbon::now()->format('Y-m-d H:i:s') + ]); + + $this->ci->mailer->send($message); + } + }); + + // TODO: create delay to prevent timing-based attacks + + $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', ['email' => $data['email']]); + return $response->withStatus(200); + } + + /** + * Returns a modal containing account terms of service. + * + * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages. + * Request type: GET + */ + public function getModalAccountTos($request, $response, $args) + { + return $this->ci->view->render($response, 'modals/tos.html.twig'); + } + + /** + * Generate a random captcha, store it to the session, and return the captcha image. + * + * Request type: GET + */ + public function imageCaptcha($request, $response, $args) + { + $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']); + $captcha->generateRandomCode(); + + return $response->withStatus(200) + ->withHeader('Content-Type', 'image/png;base64') + ->write($captcha->getImage()); + } + + /** + * Processes an account login request. + * + * Processes the request from the form on the login page, checking that: + * 1. The user is not already logged in. + * 2. The rate limit for this type of request is being observed. + * 3. Email login is enabled, if an email address was used. + * 4. The user account exists. + * 5. The user account is enabled and verified. + * 6. The user entered a valid username/email and password. + * This route, by definition, is "public access". + * Request type: POST + */ + public function login($request, $response, $args) + { + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + $currentUser = $this->ci->currentUser; + + /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + $authenticator = $this->ci->authenticator; + + // Return 200 success if user is already logged in + if ($authenticator->check()) { + $ms->addMessageTranslated('warning', 'LOGIN.ALREADY_COMPLETE'); + return $response->withStatus(200); + } + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + // Get POST parameters + $params = $request->getParsedBody(); + + // Load the request schema + $schema = new RequestSchema('schema://requests/login.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + return $response->withStatus(400); + } + + // Determine whether we are trying to log in with an email address or a username + $isEmail = filter_var($data['user_name'], FILTER_VALIDATE_EMAIL); + + // Throttle requests + + /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + $throttler = $this->ci->throttler; + + $userIdentifier = $data['user_name']; + + $throttleData = [ + 'user_identifier' => $userIdentifier + ]; + + $delay = $throttler->getDelay('sign_in_attempt', $throttleData); + if ($delay > 0) { + $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', [ + 'delay' => $delay + ]); + return $response->withStatus(429); + } + + // Log throttleable event + $throttler->logEvent('sign_in_attempt', $throttleData); + + // If credential is an email address, but email login is not enabled, raise an error. + // Note that we do this after logging throttle event, so this error counts towards throttling limit. + if ($isEmail && !$config['site.login.enable_email']) { + $ms->addMessageTranslated('danger', 'USER_OR_PASS_INVALID'); + return $response->withStatus(403); + } + + // Try to authenticate the user. Authenticator will throw an exception on failure. + /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + $authenticator = $this->ci->authenticator; + + $currentUser = $authenticator->attempt(($isEmail ? 'email' : 'user_name'), $userIdentifier, $data['password'], $data['rememberme']); + + $ms->addMessageTranslated('success', 'WELCOME', $currentUser->export()); + + // Set redirect, if relevant + $redirectOnLogin = $this->ci->get('redirect.onLogin'); + + return $redirectOnLogin($request, $response, $args); + } + + /** + * Log the user out completely, including destroying any "remember me" token. + * + * Request type: GET + */ + public function logout(Request $request, Response $response, $args) + { + // Destroy the session + $this->ci->authenticator->logout(); + + // Return to home page + $config = $this->ci->config; + return $response->withStatus(302)->withHeader('Location', $config['site.uri.public']); + } + + /** + * Render the "forgot password" page. + * + * This creates a simple form to allow users who forgot their password to have a time-limited password reset link emailed to them. + * By default, this is a "public page" (does not require authentication). + * Request type: GET + */ + public function pageForgotPassword($request, $response, $args) + { + // Load validation rules + $schema = new RequestSchema('schema://requests/forgot-password.yaml'); + $validator = new JqueryValidationAdapter($schema, $this->ci->translator); + + return $this->ci->view->render($response, 'pages/forgot-password.html.twig', [ + 'page' => [ + 'validators' => [ + 'forgot_password' => $validator->rules('json', false) + ] + ] + ]); + } + + + /** + * Render the account registration page for UserFrosting. + * + * This allows new (non-authenticated) users to create a new account for themselves on your website (if enabled). + * By definition, this is a "public page" (does not require authentication). + * Request type: GET + */ + public function pageRegister($request, $response, $args) + { + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + /** @var UserFrosting\I18n\LocalePathBuilder */ + $localePathBuilder = $this->ci->localePathBuilder; + + if (!$config['site.registration.enabled']) { + throw new NotFoundException($request, $response); + } + + /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + $authenticator = $this->ci->authenticator; + + // Redirect if user is already logged in + if ($authenticator->check()) { + $redirect = $this->ci->get('redirect.onAlreadyLoggedIn'); + + return $redirect($request, $response, $args); + } + + // Load validation rules + $schema = new RequestSchema('schema://requests/register.yaml'); + $validatorRegister = new JqueryValidationAdapter($schema, $this->ci->translator); + + // Get locale information + $currentLocales = $localePathBuilder->getLocales(); + + return $this->ci->view->render($response, 'pages/register.html.twig', [ + 'page' => [ + 'validators' => [ + 'register' => $validatorRegister->rules('json', false) + ] + ], + 'locales' => [ + 'available' => $config['site.locales.available'], + 'current' => end($currentLocales) + ] + ]); + } + + /** + * Render the "resend verification email" page. + * + * This is a form that allows users who lost their account verification link to have the link resent to their email address. + * By default, this is a "public page" (does not require authentication). + * Request type: GET + */ + public function pageResendVerification($request, $response, $args) + { + // Load validation rules + $schema = new RequestSchema('schema://requests/resend-verification.yaml'); + $validator = new JqueryValidationAdapter($schema, $this->ci->translator); + + return $this->ci->view->render($response, 'pages/resend-verification.html.twig', [ + 'page' => [ + 'validators' => [ + 'resend_verification' => $validator->rules('json', false) + ] + ] + ]); + } + + /** + * Reset password page. + * + * Renders the new password page for password reset requests. + * Request type: GET + */ + public function pageResetPassword($request, $response, $args) + { + // Insert the user's secret token from the link into the password reset form + $params = $request->getQueryParams(); + + // Load validation rules - note this uses the same schema as "set password" + $schema = new RequestSchema('schema://requests/set-password.yaml'); + $validator = new JqueryValidationAdapter($schema, $this->ci->translator); + + return $this->ci->view->render($response, 'pages/reset-password.html.twig', [ + 'page' => [ + 'validators' => [ + 'set_password' => $validator->rules('json', false) + ] + ], + 'token' => isset($params['token']) ? $params['token'] : '', + ]); + } + + /** + * Render the "set password" page. + * + * Renders the page where new users who have had accounts created for them by another user, can set their password. + * By default, this is a "public page" (does not require authentication). + * Request type: GET + */ + public function pageSetPassword($request, $response, $args) + { + // Insert the user's secret token from the link into the password set form + $params = $request->getQueryParams(); + + // Load validation rules + $schema = new RequestSchema('schema://requests/set-password.yaml'); + $validator = new JqueryValidationAdapter($schema, $this->ci->translator); + + return $this->ci->view->render($response, 'pages/set-password.html.twig', [ + 'page' => [ + 'validators' => [ + 'set_password' => $validator->rules('json', false) + ] + ], + 'token' => isset($params['token']) ? $params['token'] : '', + ]); + } + + /** + * Account settings page. + * + * Provides a form for users to modify various properties of their account, such as name, email, locale, etc. + * Any fields that the user does not have permission to modify will be automatically disabled. + * This page requires authentication. + * Request type: GET + */ + public function pageSettings($request, $response, $args) + { + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + $currentUser = $this->ci->currentUser; + + // Access-controlled page + if (!$authorizer->checkAccess($currentUser, 'uri_account_settings')) { + throw new ForbiddenException(); + } + + // Load validation rules + $schema = new RequestSchema('schema://requests/account-settings.yaml'); + $validatorAccountSettings = new JqueryValidationAdapter($schema, $this->ci->translator); + + $schema = new RequestSchema('schema://requests/profile-settings.yaml'); + $validatorProfileSettings = new JqueryValidationAdapter($schema, $this->ci->translator); + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + // Get a list of all locales + $locales = $config->getDefined('site.locales.available'); + + return $this->ci->view->render($response, 'pages/account-settings.html.twig', [ + 'locales' => $locales, + 'page' => [ + 'validators' => [ + 'account_settings' => $validatorAccountSettings->rules('json', false), + 'profile_settings' => $validatorProfileSettings->rules('json', false) + ], + 'visibility' => ($authorizer->checkAccess($currentUser, 'update_account_settings') ? '' : 'disabled') + ] + ]); + } + + /** + * Render the account sign-in page for UserFrosting. + * + * This allows existing users to sign in. + * By definition, this is a "public page" (does not require authentication). + * Request type: GET + */ + public function pageSignIn($request, $response, $args) + { + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + $authenticator = $this->ci->authenticator; + + // Redirect if user is already logged in + if ($authenticator->check()) { + $redirect = $this->ci->get('redirect.onAlreadyLoggedIn'); + + return $redirect($request, $response, $args); + } + + // Load validation rules + $schema = new RequestSchema('schema://requests/login.yaml'); + $validatorLogin = new JqueryValidationAdapter($schema, $this->ci->translator); + + return $this->ci->view->render($response, 'pages/sign-in.html.twig', [ + 'page' => [ + 'validators' => [ + 'login' => $validatorLogin->rules('json', false) + ] + ] + ]); + } + + /** + * Processes a request to update a user's profile information. + * + * Processes the request from the user profile settings form, checking that: + * 1. They have the necessary permissions to update the posted field(s); + * 2. The submitted data is valid. + * This route requires authentication. + * Request type: POST + */ + public function profile($request, $response, $args) + { + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + $currentUser = $this->ci->currentUser; + + // Access control for entire resource - check that the current user has permission to modify themselves + // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. + if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { + $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); + return $response->withStatus(403); + } + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + // POST parameters + $params = $request->getParsedBody(); + + // Load the request schema + $schema = new RequestSchema('schema://requests/profile-settings.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + $error = false; + + // Validate, and halt on validation errors. + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + $error = true; + } + + // Check that locale is valid + $locales = $config->getDefined('site.locales.available'); + if (!array_key_exists($data['locale'], $locales)) { + $ms->addMessageTranslated('danger', 'LOCALE.INVALID', $data); + $error = true; + } + + if ($error) { + return $response->withStatus(400); + } + + // Looks good, let's update with new values! + // Note that only fields listed in `profile-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB + $currentUser->fill($data); + + $currentUser->save(); + + // Create activity record + $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their profile settings.", [ + 'type' => 'update_profile_settings' + ]); + + $ms->addMessageTranslated('success', 'PROFILE.UPDATED'); + return $response->withStatus(200); + } + + /** + * Processes an new account registration request. + * + * This is throttled to prevent account enumeration, since it needs to divulge when a username/email has been used. + * Processes the request from the form on the registration page, checking that: + * 1. The honeypot was not modified; + * 2. The master account has already been created (during installation); + * 3. Account registration is enabled; + * 4. The user is not already logged in; + * 5. Valid information was entered; + * 6. The captcha, if enabled, is correct; + * 7. The username and email are not already taken. + * Automatically sends an activation link upon success, if account activation is enabled. + * This route is "public access". + * Request type: POST + * Returns the User Object for the user record that was created. + */ + public function register(Request $request, Response $response, $args) + { + /** @var MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + // Get POST parameters: user_name, first_name, last_name, email, password, passwordc, captcha, spiderbro, csrf_token + $params = $request->getParsedBody(); + + // Check the honeypot. 'spiderbro' is not a real field, it is hidden on the main page and must be submitted with its default value for this to be processed. + if (!isset($params['spiderbro']) || $params['spiderbro'] != 'http://') { + throw new SpammyRequestException('Possible spam received:' . print_r($params, true)); + } + + // Security measure: do not allow registering new users until the master account has been created. + if (!$classMapper->staticMethod('user', 'find', $config['reserved_user_ids.master'])) { + $ms->addMessageTranslated('danger', 'ACCOUNT.MASTER_NOT_EXISTS'); + return $response->withStatus(403); + } + + // Check if registration is currently enabled + if (!$config['site.registration.enabled']) { + $ms->addMessageTranslated('danger', 'REGISTRATION.DISABLED'); + return $response->withStatus(403); + } + + /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + $authenticator = $this->ci->authenticator; + + // Prevent the user from registering if he/she is already logged in + if ($authenticator->check()) { + $ms->addMessageTranslated('danger', 'REGISTRATION.LOGOUT'); + return $response->withStatus(403); + } + + // Load the request schema + $schema = new RequestSchema('schema://requests/register.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + $error = false; + + // Validate request data + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + $error = true; + } + + /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + $throttler = $this->ci->throttler; + $delay = $throttler->getDelay('registration_attempt'); + + // Throttle requests + if ($delay > 0) { + return $response->withStatus(429); + } + + // Check if username or email already exists + if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) { + $ms->addMessageTranslated('danger', 'USERNAME.IN_USE', $data); + $error = true; + } + + if ($classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) { + $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data); + $error = true; + } + + // Check captcha, if required + if ($config['site.registration.captcha']) { + $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']); + if (!$data['captcha'] || !$captcha->verifyCode($data['captcha'])) { + $ms->addMessageTranslated('danger', 'CAPTCHA.FAIL'); + $error = true; + } + } + + if ($error) { + return $response->withStatus(400); + } + + // Remove captcha, password confirmation from object data after validation + unset($data['captcha']); + unset($data['passwordc']); + + if ($config['site.registration.require_email_verification']) { + $data['flag_verified'] = false; + } else { + $data['flag_verified'] = true; + } + + // Load default group + $groupSlug = $config['site.registration.user_defaults.group']; + $defaultGroup = $classMapper->staticMethod('group', 'where', 'slug', $groupSlug)->first(); + + if (!$defaultGroup) { + $e = new HttpException("Account registration is not working because the default group '$groupSlug' does not exist."); + $e->addUserMessage('ACCOUNT.REGISTRATION_BROKEN'); + throw $e; + } + + // Set default group + $data['group_id'] = $defaultGroup->id; + + // Set locale + $data['locale'] = $data['locale']; + + // Hash password + $data['password'] = Password::hash($data['password']); + + // All checks passed! log events/activities, create user, and send verification email (if required) + // Begin transaction - DB will be rolled back if an exception occurs + Capsule::transaction( function() use ($classMapper, $data, $ms, $config, $throttler) { + // Log throttleable event + $throttler->logEvent('registration_attempt'); + + // Create the user + $user = $classMapper->createInstance('user', $data); + + // Store new user to database + $user->save(); + + // Create activity record + $this->ci->userActivityLogger->info("User {$user->user_name} registered for a new account.", [ + 'type' => 'sign_up', + 'user_id' => $user->id + ]); + + // Load default roles + $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs'); + $defaultRoles = $classMapper->staticMethod('role', 'whereIn', 'slug', $defaultRoleSlugs)->get(); + $defaultRoleIds = $defaultRoles->pluck('id')->all(); + + // Attach default roles + $user->roles()->attach($defaultRoleIds); + + // Verification email + if ($config['site.registration.require_email_verification']) { + // Try to generate a new verification request + $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']); + + // Create and send verification email + $message = new TwigMailMessage($this->ci->view, 'mail/verify-account.html.twig'); + + $message->from($config['address_book.admin']) + ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) + ->addParams([ + 'user' => $user, + 'token' => $verification->getToken() + ]); + + $this->ci->mailer->send($message); + + $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE2', $user->toArray()); + } else { + // No verification required + $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE1'); + } + }); + + return $response->withStatus(200); + } + + /** + * Processes a request to resend the verification email for a new user account. + * + * Processes the request from the resend verification email form, checking that: + * 1. The rate limit on this type of request is observed; + * 2. The provided email is associated with an existing user account; + * 3. The user account is not already verified; + * 4. The submitted data is valid. + * This route is "public access". + * Request type: POST + */ + public function resendVerification($request, $response, $args) + { + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + // Get POST parameters + $params = $request->getParsedBody(); + + // Load the request schema + $schema = new RequestSchema('schema://requests/resend-verification.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + return $response->withStatus(400); + } + + // Throttle requests + + /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + $throttler = $this->ci->throttler; + + $throttleData = [ + 'email' => $data['email'] + ]; + $delay = $throttler->getDelay('verification_request', $throttleData); + + if ($delay > 0) { + $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); + return $response->withStatus(429); + } + + // All checks passed! log events/activities, create user, and send verification email (if required) + // Begin transaction - DB will be rolled back if an exception occurs + Capsule::transaction( function() use ($classMapper, $data, $throttler, $throttleData, $config) { + // Log throttleable event + $throttler->logEvent('verification_request', $throttleData); + + // Load the user, by email address + $user = $classMapper->staticMethod('user', 'where', 'email', $data['email'])->first(); + + // Check that the user exists and is not already verified. + // If there is no user with that email address, or the user exists and is already verified, + // we pretend like we succeeded to prevent account enumeration + if ($user && $user->flag_verified != '1') { + // We're good to go - record user activity and send the email + $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']); + + // Create and send verification email + $message = new TwigMailMessage($this->ci->view, 'mail/resend-verification.html.twig'); + + $message->from($config['address_book.admin']) + ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) + ->addParams([ + 'user' => $user, + 'token' => $verification->getToken() + ]); + + $this->ci->mailer->send($message); + } + }); + + $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.NEW_LINK_SENT', ['email' => $data['email']]); + return $response->withStatus(200); + } + + /** + * Processes a request to set the password for a new or current user. + * + * Processes the request from the password create/reset form, which should have the secret token embedded in it, checking that: + * 1. The provided secret token is associated with an existing user account; + * 2. The user has a password set/reset request in progress; + * 3. The token has not expired; + * 4. The submitted data (new password) is valid. + * This route is "public access". + * Request type: POST + */ + public function setPassword(Request $request, Response $response, $args) + { + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + // Get POST parameters + $params = $request->getParsedBody(); + + // Load the request schema + $schema = new RequestSchema('schema://requests/set-password.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + // Validate, and halt on validation errors. Failed validation attempts do not count towards throttling limit. + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + return $response->withStatus(400); + } + + $forgotPasswordPage = $this->ci->router->pathFor('forgot-password'); + + // Ok, try to complete the request with the specified token and new password + $passwordReset = $this->ci->repoPasswordReset->complete($data['token'], [ + 'password' => $data['password'] + ]); + + if (!$passwordReset) { + $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID', ['url' => $forgotPasswordPage]); + return $response->withStatus(400); + } + + $ms->addMessageTranslated('success', 'PASSWORD.UPDATED'); + + /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + $authenticator = $this->ci->authenticator; + + // Log out any existing user, and create a new session + if ($authenticator->check()) { + $authenticator->logout(); + } + + // Auto-login the user (without "remember me") + $user = $passwordReset->user; + $authenticator->login($user); + + $ms->addMessageTranslated('success', 'WELCOME', $user->export()); + return $response->withStatus(200); + } + + /** + * Processes a request to update a user's account information. + * + * Processes the request from the user account settings form, checking that: + * 1. The user correctly input their current password; + * 2. They have the necessary permissions to update the posted field(s); + * 3. The submitted data is valid. + * This route requires authentication. + * Request type: POST + */ + public function settings($request, $response, $args) + { + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + $authorizer = $this->ci->authorizer; + + /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + $currentUser = $this->ci->currentUser; + + // Access control for entire resource - check that the current user has permission to modify themselves + // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. + if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { + $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); + return $response->withStatus(403); + } + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + // POST parameters + $params = $request->getParsedBody(); + + // Load the request schema + $schema = new RequestSchema('schema://requests/account-settings.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + $error = false; + + // Validate, and halt on validation errors. + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + $error = true; + } + + // Confirm current password + if (!isset($data['passwordcheck']) || !Password::verify($data['passwordcheck'], $currentUser->password)) { + $ms->addMessageTranslated('danger', 'PASSWORD.INVALID'); + $error = true; + } + + // Remove password check, password confirmation from object data after validation + unset($data['passwordcheck']); + unset($data['passwordc']); + + // If new email was submitted, check that the email address is not in use + if (isset($data['email']) && $data['email'] != $currentUser->email && $classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) { + $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data); + $error = true; + } + + if ($error) { + return $response->withStatus(400); + } + + // Hash new password, if specified + if (isset($data['password']) && !empty($data['password'])) { + $data['password'] = Password::hash($data['password']); + } else { + // Do not pass to model if no password is specified + unset($data['password']); + } + + // Looks good, let's update with new values! + // Note that only fields listed in `account-settings.yaml` will be permitted in $data, so this prevents the user from updating all columns in the DB + $currentUser->fill($data); + + $currentUser->save(); + + // Create activity record + $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated their account settings.", [ + 'type' => 'update_account_settings' + ]); + + $ms->addMessageTranslated('success', 'ACCOUNT.SETTINGS.UPDATED'); + return $response->withStatus(200); + } + + /** + * Suggest an available username for a specified first/last name. + * + * This route is "public access". + * Request type: GET + * @todo Can this route be abused for account enumeration? If so we should throttle it as well. + */ + public function suggestUsername($request, $response, $args) + { + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + $suggestion = AccountUtil::randomUniqueUsername($classMapper, 50, 10); + + // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content. + // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating). + return $response->withJson([ + 'user_name' => $suggestion + ], 200, JSON_PRETTY_PRINT); + } + + /** + * Processes an new email verification request. + * + * Processes the request from the email verification link that was emailed to the user, checking that: + * 1. The token provided matches a user in the database; + * 2. The user account is not already verified; + * This route is "public access". + * Request type: GET + */ + public function verify($request, $response, $args) + { + /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + $ms = $this->ci->alerts; + + /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + $classMapper = $this->ci->classMapper; + + /** @var UserFrosting\Config\Config $config */ + $config = $this->ci->config; + + $loginPage = $this->ci->router->pathFor('login'); + + // GET parameters + $params = $request->getQueryParams(); + + // Load request schema + $schema = new RequestSchema('schema://requests/account-verify.yaml'); + + // Whitelist and set parameter defaults + $transformer = new RequestDataTransformer($schema); + $data = $transformer->transform($params); + + // Validate, and halt on validation errors. This is a GET request, so we redirect on validation error. + $validator = new ServerSideValidator($schema, $this->ci->translator); + if (!$validator->validate($data)) { + $ms->addValidationErrors($validator); + // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel + return $response->withRedirect($loginPage, 400); + } + + $verification = $this->ci->repoVerification->complete($data['token']); + + if (!$verification) { + $ms->addMessageTranslated('danger', 'ACCOUNT.VERIFICATION.TOKEN_NOT_FOUND'); + return $response->withRedirect($loginPage, 400); + } + + $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.COMPLETE'); + + // Forward to login page + return $response->withRedirect($loginPage); + } +} diff --git a/app/sprinkles/account/templates/pages/register.html.twig b/app/sprinkles/account/templates/pages/register.html.twig index bd155bab4..c181a870f 100644 --- a/app/sprinkles/account/templates/pages/register.html.twig +++ b/app/sprinkles/account/templates/pages/register.html.twig @@ -1,105 +1,116 @@ -{% extends "pages/abstract/base.html.twig" %} - -{# Overrides blocks in head of base template #} -{% block page_title %}{{translate('REGISTER')}}{% endblock %} - -{% block page_description %}{{translate('PAGE.LOGIN.DESCRIPTION', {'site_name': site.title })}}{% endblock %} - -{% block body_attributes %} - class="hold-transition login-page" -{% endblock %} - -{% block content %} - - -{% endblock %} - -{% block scripts_page %} - - - - - {{ assets.js('js/pages/register') | raw }} -{% endblock %} +{% extends "pages/abstract/base.html.twig" %} + +{# Overrides blocks in head of base template #} +{% block page_title %}{{translate('REGISTER')}}{% endblock %} + +{% block page_description %}{{translate('PAGE.LOGIN.DESCRIPTION', {'site_name': site.title })}}{% endblock %} + +{% block body_attributes %} + class="hold-transition login-page" +{% endblock %} + +{% block content %} + + +{% endblock %} + +{% block scripts_page %} + + + + + {{ assets.js('js/pages/register') | raw }} +{% endblock %} diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index a7164f3e6..42dc3fbf1 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -1,664 +1,670 @@ -config; - - if ($config['alert.storage'] == 'cache') { - return new CacheAlertStream($config['alert.key'], $c->translator, $c->cache, $c->config); - } elseif ($config['alert.storage'] == 'session') { - return new SessionAlertStream($config['alert.key'], $c->translator, $c->session); - } else { - throw new \Exception("Bad alert storage handler type '{$config['alert.storage']}' specified in configuration file."); - } - }; - - /** - * Asset loader service - * - * Loads assets from a specified relative location. - * Assets are Javascript, CSS, image, and other files used by your site. - * - * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. - */ - $container['assetLoader'] = function ($c) { - $basePath = \UserFrosting\SPRINKLES_DIR; - $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; - - return new AssetLoader($basePath, $pattern); - }; - - /** - * Asset manager service. - * - * Loads raw or compiled asset information from your bundle.config.json schema file. - * Assets are Javascript, CSS, image, and other files used by your site. - */ - $container['assets'] = function ($c) { - $config = $c->config; - $locator = $c->locator; - - // Hacky way to clean up locator paths. - $locatorPaths = []; - foreach ($locator->getPaths('assets') as $pathSet) { - foreach ($pathSet as $path) { - $locatorPaths[] = $path; - } - } - - // Load asset schema - if ($config['assets.use_raw']) { - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; - - $sprinkles = $c->sprinkleManager->getSprinkleNames(); - - $prefixTransformer = new PrefixTransformer(); - $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); - $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); - - foreach ($sprinkles as $sprinkle) { - $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); - } - $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); - - // Load raw asset bundles for each Sprinkle. - - // Retrieve locations of raw asset bundle schemas that exist. - $bundleSchemas = $locator->findResources('sprinkles://' . $config['assets.raw.schema']); - - // Load asset bundle schemas that exist. - if (array_key_exists(0, $bundleSchemas)) { - $bundles = new RawAssetBundles(array_shift($bundleSchemas)); - - foreach ($bundleSchemas as $bundleSchema) { - $bundles->extend($bundleSchema); - } - - // Add bundles to asset manager. - $assets->addAssetBundles($bundles); - } - } else { - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; - $assets = new Assets($locator, 'assets', $baseUrl); - $assets->overrideBasePath($locator->getBase() . '/public/assets'); - - // Load compiled asset bundle. - $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); - } - - return $assets; - }; - - /** - * Cache service. - * - * @todo Create an option somewhere to flush the cache - */ - $container['cache'] = function ($c) { - - $config = $c->config; - - if ($config['cache.driver'] == 'file') { - $path = $c->locator->findResource('cache://', true, true); - $cacheStore = new TaggableFileStore($path); - } elseif ($config['cache.driver'] == 'memcached') { - $cacheStore = new MemcachedStore($config['cache.memcached']); - } elseif ($config['cache.driver'] == 'redis') { - $cacheStore = new RedisStore($config['cache.redis']); - } else { - throw new \Exception("Bad cache store type '{$config['cache.driver']}' specified in configuration file."); - } - - $cache = $cacheStore->instance(); - return $cache->tags($config['cache.prefix']); - }; - - /** - * Middleware to check environment. - * - * @todo We should cache the results of this, the first time that it succeeds. - */ - $container['checkEnvironment'] = function ($c) { - $checkEnvironment = new CheckEnvironment($c->view, $c->locator, $c->cache); - return $checkEnvironment; - }; - - /** - * Class mapper. - * - * Creates an abstraction on top of class names to allow extending them in sprinkles. - */ - $container['classMapper'] = function ($c) { - $classMapper = new ClassMapper(); - $classMapper->setClassMapping('query_builder', 'UserFrosting\Sprinkle\Core\Database\Builder'); - $classMapper->setClassMapping('throttle', 'UserFrosting\Sprinkle\Core\Database\Models\Throttle'); - return $classMapper; - }; - - /** - * Site config service (separate from Slim settings). - * - * Will attempt to automatically determine which config file(s) to use based on the value of the UF_MODE environment variable. - */ - $container['config'] = function ($c) { - // Grab any relevant dotenv variables from the .env file - try { - $dotenv = new Dotenv(\UserFrosting\APP_DIR); - $dotenv->load(); - } catch (InvalidPathException $e) { - // Skip loading the environment config file if it doesn't exist. - } - - // Get configuration mode from environment - $mode = getenv('UF_MODE') ?: ''; - - // Construct and load config repository - $builder = new ConfigPathBuilder($c->locator, 'config://'); - $loader = new ArrayFileLoader($builder->buildPaths($mode)); - $config = new Repository($loader->load()); - - // Construct base url from components, if not explicitly specified - if (!isset($config['site.uri.public'])) { - $uri = $c->request->getUri(); - - // Slim\Http\Uri likes to add trailing slashes when the path is empty, so this fixes that. - $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); - } - - // Hacky fix to prevent sessions from being hit too much: ignore CSRF middleware for requests for raw assets ;-) - // See https://github.com/laravel/framework/issues/8172#issuecomment-99112012 for more information on why it's bad to hit Laravel sessions multiple times in rapid succession. - $csrfBlacklist = $config['csrf.blacklist']; - $csrfBlacklist['^/' . $config['assets.raw.path']] = [ - 'GET' - ]; - - $config->set('csrf.blacklist', $csrfBlacklist); - - // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) - if (!$config['assets.use_raw']) { - $c->locator->resetScheme('assets'); - $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); - } - - return $config; - }; - - /** - * Initialize CSRF guard middleware. - * - * @see https://github.com/slimphp/Slim-Csrf - */ - $container['csrf'] = function ($c) { - $csrfKey = $c->config['session.keys.csrf']; - - // Workaround so that we can pass storage into CSRF guard. - // If we tried to directly pass the indexed portion of `session` (for example, $c->session['site.csrf']), - // we would get an 'Indirect modification of overloaded element of UserFrosting\Session\Session' error. - // If we tried to assign an array and use that, PHP would only modify the local variable, and not the session. - // Since ArrayObject is an object, PHP will modify the object itself, allowing it to persist in the session. - if (!$c->session->has($csrfKey)) { - $c->session[$csrfKey] = new \ArrayObject(); - } - $csrfStorage = $c->session[$csrfKey]; - - $onFailure = function ($request, $response, $next) { - $e = new BadRequestException("The CSRF code was invalid or not provided."); - $e->addUserMessage('CSRF_MISSING'); - throw $e; - - return $next($request, $response); - }; - - return new Guard($c->config['csrf.name'], $csrfStorage, $onFailure, $c->config['csrf.storage_limit'], $c->config['csrf.strength'], $c->config['csrf.persistent_token']); - }; - - /** - * Initialize Eloquent Capsule, which provides the database layer for UF. - * - * @todo construct the individual objects rather than using the facade - */ - $container['db'] = function ($c) { - $config = $c->config; - - $capsule = new Capsule; - - foreach ($config['db'] as $name => $dbConfig) { - $capsule->addConnection($dbConfig, $name); - } - - $queryEventDispatcher = new Dispatcher(new Container); - - $capsule->setEventDispatcher($queryEventDispatcher); - - // Register as global connection - $capsule->setAsGlobal(); - - // Start Eloquent - $capsule->bootEloquent(); - - if ($config['debug.queries']) { - $logger = $c->queryLogger; - - foreach ($config['db'] as $name => $dbConfig) { - $capsule->connection($name)->enableQueryLog(); - } - - // Register listener - $queryEventDispatcher->listen(QueryExecuted::class, function ($query) use ($logger) { - $logger->debug("Query executed on database [{$query->connectionName}]:", [ - 'query' => $query->sql, - 'bindings' => $query->bindings, - 'time' => $query->time . ' ms' - ]); - }); - } - - return $capsule; - }; - - /** - * Debug logging with Monolog. - * - * Extend this service to push additional handlers onto the 'debug' log stack. - */ - $container['debugLogger'] = function ($c) { - $logger = new Logger('debug'); - - $logFile = $c->locator->findResource('log://userfrosting.log', true, true); - - $handler = new StreamHandler($logFile); - - $formatter = new MixedFormatter(null, null, true); - - $handler->setFormatter($formatter); - $logger->pushHandler($handler); - - return $logger; - }; - - /** - * Custom error-handler for recoverable errors. - */ - $container['errorHandler'] = function ($c) { - $settings = $c->settings; - - $handler = new ExceptionHandlerManager($c, $settings['displayErrorDetails']); - - // Register the base HttpExceptionHandler. - $handler->registerHandler('\UserFrosting\Support\Exception\HttpException', '\UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler'); - - // Register the NotFoundExceptionHandler. - $handler->registerHandler('\UserFrosting\Support\Exception\NotFoundException', '\UserFrosting\Sprinkle\Core\Error\Handler\NotFoundExceptionHandler'); - - // Register the PhpMailerExceptionHandler. - $handler->registerHandler('\phpmailerException', '\UserFrosting\Sprinkle\Core\Error\Handler\PhpMailerExceptionHandler'); - - return $handler; - }; - - /** - * Error logging with Monolog. - * - * Extend this service to push additional handlers onto the 'error' log stack. - */ - $container['errorLogger'] = function ($c) { - $log = new Logger('errors'); - - $logFile = $c->locator->findResource('log://userfrosting.log', true, true); - - $handler = new StreamHandler($logFile, Logger::WARNING); - - $formatter = new LineFormatter(null, null, true); - - $handler->setFormatter($formatter); - $log->pushHandler($handler); - - return $log; - }; - - /** - * Factory service with FactoryMuffin. - * - * Provide access to factories for the rapid creation of objects for the purpose of testing - */ - $container['factory'] = function ($c) { - - // Get the path of all of the sprinkle's factories - $factoriesPath = $c->locator->findResources('factories://', true, true); - - // Create a new Factory Muffin instance - $fm = new FactoryMuffin(); - - // Load all of the model definitions - $fm->loadFactories($factoriesPath); - - // Set the locale. Could be the config one, but for testing English should do - Faker::setLocale('en_EN'); - - return $fm; - }; - - /** - * Builds search paths for locales in all Sprinkles. - */ - $container['localePathBuilder'] = function ($c) { - $config = $c->config; - $request = $c->request; - - // Make sure the locale config is a valid string - if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { - throw new \UnexpectedValueException('The locale config is not a valid string.'); - } - - // Get default locales as specified in configurations. - $locales = explode(',', $config['site.locales.default']); - - // Add supported browser preferred locales. - if ($request->hasHeader('Accept-Language')) { - $allowedLocales = []; - foreach (explode(',', $request->getHeaderLine('Accept-Language')) as $index => $browserLocale) { - // Split to access q - $parts = explode(';', $browserLocale) ?: []; - - // Ensure locale valid, and available - if (array_key_exists(0, $parts) && array_key_exists($parts[0], $config['site.locales.available'])) { - // Determine preference level, and add to $allowedLocales - if (array_key_exists(1, $parts)) { - $parts[1] = str_replace('q=', '', $parts[1]); - $parts[1] = is_numeric($parts[1]) ?: 0; - } else { - $parts[1] = 1; - } - // Add to list, and format for UF's i18n. - $allowedLocales[str_replace('-', '_', $parts[0])] = $parts[1]; - } - } - - // Sort, extract keys, and merge with $locales - asort($allowedLocales, SORT_NUMERIC); - $locales = array_merge($locales, array_keys($allowedLocales)); - - // Remove duplicates, while maintaining fallback order - $locales = array_reverse(array_unique(array_reverse($locales))); - } - - return new LocalePathBuilder($c->locator, 'locale://', $locales); - }; - - /** - * Mail service. - */ - $container['mailer'] = function ($c) { - $mailer = new Mailer($c->mailLogger, $c->config['mail']); - - // Use UF debug settings to override any service-specific log settings. - if (!$c->config['debug.smtp']) { - $mailer->getPhpMailer()->SMTPDebug = 0; - } - - return $mailer; - }; - - /** - * Mail logging service. - * - * PHPMailer will use this to log SMTP activity. - * Extend this service to push additional handlers onto the 'mail' log stack. - */ - $container['mailLogger'] = function ($c) { - $log = new Logger('mail'); - - $logFile = $c->locator->findResource('log://userfrosting.log', true, true); - - $handler = new StreamHandler($logFile); - $formatter = new LineFormatter(null, null, true); - - $handler->setFormatter($formatter); - $log->pushHandler($handler); - - return $log; - }; - - /** - * Error-handler for 404 errors. Notice that we manually create a UserFrosting NotFoundException, - * and a NotFoundExceptionHandler. This lets us pass through to the UF error handling system. - */ - $container['notFoundHandler'] = function ($c) { - return function ($request, $response) use ($c) { - $exception = new NotFoundException; - $handler = new NotFoundExceptionHandler($c, $request, $response, $exception, $c->settings['displayErrorDetails']); - return $handler->handle(); - }; - }; - - /** - * Error-handler for PHP runtime errors. Notice that we just pass this through to our general-purpose - * error-handling service. - */ - $container['phpErrorHandler'] = function ($c) { - return $c->errorHandler; - }; - - /** - * Laravel query logging with Monolog. - * - * Extend this service to push additional handlers onto the 'query' log stack. - */ - $container['queryLogger'] = function ($c) { - $logger = new Logger('query'); - - $logFile = $c->locator->findResource('log://userfrosting.log', true, true); - - $handler = new StreamHandler($logFile); - - $formatter = new MixedFormatter(null, null, true); - - $handler->setFormatter($formatter); - $logger->pushHandler($handler); - - return $logger; - }; - - /** - * Override Slim's default router with the UF router. - */ - $container['router'] = function ($c) { - $routerCacheFile = false; - if (isset($c->config['settings.routerCacheFile'])) { - $routerCacheFile = $c->config['settings.routerCacheFile']; - } - - return (new Router)->setCacheFile($routerCacheFile); - }; - - /** - * Start the PHP session, with the name and parameters specified in the configuration file. - */ - $container['session'] = function ($c) { - $config = $c->config; - - // Create appropriate handler based on config - if ($config['session.handler'] == 'file') { - $fs = new FileSystem; - $handler = new FileSessionHandler($fs, $c->locator->findResource('session://'), $config['session.minutes']); - } elseif ($config['session.handler'] == 'database') { - $connection = $c->db->connection(); - // Table must exist, otherwise an exception will be thrown - $handler = new DatabaseSessionHandler($connection, $config['session.database.table'], $config['session.minutes']); - } else { - throw new \Exception("Bad session handler type '{$config['session.handler']}' specified in configuration file."); - } - - // Create, start and return a new wrapper for $_SESSION - $session = new Session($handler, $config['session']); - $session->start(); - - return $session; - }; - - /** - * Request throttler. - * - * Throttles (rate-limits) requests of a predefined type, with rules defined in site config. - */ - $container['throttler'] = function ($c) { - $throttler = new Throttler($c->classMapper); - - $config = $c->config; - - if ($config->has('throttles') && ($config['throttles'] !== null)) { - foreach ($config['throttles'] as $type => $rule) { - if ($rule) { - $throttleRule = new ThrottleRule($rule['method'], $rule['interval'], $rule['delays']); - $throttler->addThrottleRule($type, $throttleRule); - } else { - $throttler->addThrottleRule($type, null); - } - } - } - - return $throttler; - }; - - /** - * Translation service, for translating message tokens. - */ - $container['translator'] = function ($c) { - // Load the translations - $paths = $c->localePathBuilder->buildPaths(); - $loader = new ArrayFileLoader($paths); - - // Create the $translator object - $translator = new MessageTranslator($loader->load()); - - return $translator; - }; - - /** - * Set up Twig as the view, adding template paths for all sprinkles and the Slim Twig extension. - * - * Also adds the UserFrosting core Twig extension, which provides additional functions, filters, global variables, etc. - */ - $container['view'] = function ($c) { - $templatePaths = $c->locator->findResources('templates://', true, true); - - $view = new Twig($templatePaths); - - $loader = $view->getLoader(); - - $sprinkles = $c->sprinkleManager->getSprinkleNames(); - - // Add Sprinkles' templates namespaces - foreach ($sprinkles as $sprinkle) { - $path = \UserFrosting\SPRINKLES_DIR . \UserFrosting\DS . - $sprinkle . \UserFrosting\DS . - \UserFrosting\TEMPLATE_DIR_NAME . \UserFrosting\DS; - - if (is_dir($path)) { - $loader->addPath($path, $sprinkle); - } - } - - $twig = $view->getEnvironment(); - - if ($c->config['cache.twig']) { - $twig->setCache($c->locator->findResource('cache://twig', true, true)); - } - - if ($c->config['debug.twig']) { - $twig->enableDebug(); - $view->addExtension(new \Twig_Extension_Debug()); - } - - // Register the Slim extension with Twig - $slimExtension = new TwigExtension( - $c->router, - $c->request->getUri() - ); - $view->addExtension($slimExtension); - - // Register the core UF extension with Twig - $coreExtension = new CoreExtension($c); - $view->addExtension($coreExtension); - - return $view; - }; - } -} +config; + + if ($config['alert.storage'] == 'cache') { + return new CacheAlertStream($config['alert.key'], $c->translator, $c->cache, $c->config); + } elseif ($config['alert.storage'] == 'session') { + return new SessionAlertStream($config['alert.key'], $c->translator, $c->session); + } else { + throw new \Exception("Bad alert storage handler type '{$config['alert.storage']}' specified in configuration file."); + } + }; + + /** + * Asset loader service + * + * Loads assets from a specified relative location. + * Assets are Javascript, CSS, image, and other files used by your site. + * + * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. + */ + $container['assetLoader'] = function ($c) { + $basePath = \UserFrosting\SPRINKLES_DIR; + $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; + + return new AssetLoader($basePath, $pattern); + }; + + /** + * Asset manager service. + * + * Loads raw or compiled asset information from your bundle.config.json schema file. + * Assets are Javascript, CSS, image, and other files used by your site. + */ + $container['assets'] = function ($c) { + $config = $c->config; + $locator = $c->locator; + + // Hacky way to clean up locator paths. + $locatorPaths = []; + foreach ($locator->getPaths('assets') as $pathSet) { + foreach ($pathSet as $path) { + $locatorPaths[] = $path; + } + } + + // Load asset schema + if ($config['assets.use_raw']) { + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; + + $sprinkles = $c->sprinkleManager->getSprinkleNames(); + + $prefixTransformer = new PrefixTransformer(); + $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); + $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); + + foreach ($sprinkles as $sprinkle) { + $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); + } + $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); + + // Load raw asset bundles for each Sprinkle. + + // Retrieve locations of raw asset bundle schemas that exist. + $bundleSchemas = $locator->findResources('sprinkles://' . $config['assets.raw.schema']); + + // Load asset bundle schemas that exist. + if (array_key_exists(0, $bundleSchemas)) { + $bundles = new RawAssetBundles(array_shift($bundleSchemas)); + + foreach ($bundleSchemas as $bundleSchema) { + $bundles->extend($bundleSchema); + } + + // Add bundles to asset manager. + $assets->addAssetBundles($bundles); + } + } else { + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; + $assets = new Assets($locator, 'assets', $baseUrl); + $assets->overrideBasePath($locator->getBase() . '/public/assets'); + + // Load compiled asset bundle. + $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); + } + + return $assets; + }; + + /** + * Cache service. + * + * @todo Create an option somewhere to flush the cache + */ + $container['cache'] = function ($c) { + + $config = $c->config; + + if ($config['cache.driver'] == 'file') { + $path = $c->locator->findResource('cache://', true, true); + $cacheStore = new TaggableFileStore($path); + } elseif ($config['cache.driver'] == 'memcached') { + $cacheStore = new MemcachedStore($config['cache.memcached']); + } elseif ($config['cache.driver'] == 'redis') { + $cacheStore = new RedisStore($config['cache.redis']); + } else { + throw new \Exception("Bad cache store type '{$config['cache.driver']}' specified in configuration file."); + } + + $cache = $cacheStore->instance(); + return $cache->tags($config['cache.prefix']); + }; + + /** + * Middleware to check environment. + * + * @todo We should cache the results of this, the first time that it succeeds. + */ + $container['checkEnvironment'] = function ($c) { + $checkEnvironment = new CheckEnvironment($c->view, $c->locator, $c->cache); + return $checkEnvironment; + }; + + /** + * Class mapper. + * + * Creates an abstraction on top of class names to allow extending them in sprinkles. + */ + $container['classMapper'] = function ($c) { + $classMapper = new ClassMapper(); + $classMapper->setClassMapping('query_builder', 'UserFrosting\Sprinkle\Core\Database\Builder'); + $classMapper->setClassMapping('throttle', 'UserFrosting\Sprinkle\Core\Database\Models\Throttle'); + return $classMapper; + }; + + /** + * Site config service (separate from Slim settings). + * + * Will attempt to automatically determine which config file(s) to use based on the value of the UF_MODE environment variable. + */ + $container['config'] = function ($c) { + // Grab any relevant dotenv variables from the .env file + try { + $dotenv = new Dotenv(\UserFrosting\APP_DIR); + $dotenv->load(); + } catch (InvalidPathException $e) { + // Skip loading the environment config file if it doesn't exist. + } + + // Get configuration mode from environment + $mode = getenv('UF_MODE') ?: ''; + + // Construct and load config repository + $builder = new ConfigPathBuilder($c->locator, 'config://'); + $loader = new ArrayFileLoader($builder->buildPaths($mode)); + $config = new Repository($loader->load()); + + // Construct base url from components, if not explicitly specified + if (!isset($config['site.uri.public'])) { + $uri = $c->request->getUri(); + + // Slim\Http\Uri likes to add trailing slashes when the path is empty, so this fixes that. + $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); + } + + // Hacky fix to prevent sessions from being hit too much: ignore CSRF middleware for requests for raw assets ;-) + // See https://github.com/laravel/framework/issues/8172#issuecomment-99112012 for more information on why it's bad to hit Laravel sessions multiple times in rapid succession. + $csrfBlacklist = $config['csrf.blacklist']; + $csrfBlacklist['^/' . $config['assets.raw.path']] = [ + 'GET' + ]; + + $config->set('csrf.blacklist', $csrfBlacklist); + + // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) + if (!$config['assets.use_raw']) { + $c->locator->resetScheme('assets'); + $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); + } + + return $config; + }; + + /** + * Initialize CSRF guard middleware. + * + * @see https://github.com/slimphp/Slim-Csrf + */ + $container['csrf'] = function ($c) { + $csrfKey = $c->config['session.keys.csrf']; + + // Workaround so that we can pass storage into CSRF guard. + // If we tried to directly pass the indexed portion of `session` (for example, $c->session['site.csrf']), + // we would get an 'Indirect modification of overloaded element of UserFrosting\Session\Session' error. + // If we tried to assign an array and use that, PHP would only modify the local variable, and not the session. + // Since ArrayObject is an object, PHP will modify the object itself, allowing it to persist in the session. + if (!$c->session->has($csrfKey)) { + $c->session[$csrfKey] = new \ArrayObject(); + } + $csrfStorage = $c->session[$csrfKey]; + + $onFailure = function ($request, $response, $next) { + $e = new BadRequestException("The CSRF code was invalid or not provided."); + $e->addUserMessage('CSRF_MISSING'); + throw $e; + + return $next($request, $response); + }; + + return new Guard($c->config['csrf.name'], $csrfStorage, $onFailure, $c->config['csrf.storage_limit'], $c->config['csrf.strength'], $c->config['csrf.persistent_token']); + }; + + /** + * Initialize Eloquent Capsule, which provides the database layer for UF. + * + * @todo construct the individual objects rather than using the facade + */ + $container['db'] = function ($c) { + $config = $c->config; + + $capsule = new Capsule; + + foreach ($config['db'] as $name => $dbConfig) { + $capsule->addConnection($dbConfig, $name); + } + + $queryEventDispatcher = new Dispatcher(new Container); + + $capsule->setEventDispatcher($queryEventDispatcher); + + // Register as global connection + $capsule->setAsGlobal(); + + // Start Eloquent + $capsule->bootEloquent(); + + if ($config['debug.queries']) { + $logger = $c->queryLogger; + + foreach ($config['db'] as $name => $dbConfig) { + $capsule->connection($name)->enableQueryLog(); + } + + // Register listener + $queryEventDispatcher->listen(QueryExecuted::class, function ($query) use ($logger) { + $logger->debug("Query executed on database [{$query->connectionName}]:", [ + 'query' => $query->sql, + 'bindings' => $query->bindings, + 'time' => $query->time . ' ms' + ]); + }); + } + + return $capsule; + }; + + /** + * Debug logging with Monolog. + * + * Extend this service to push additional handlers onto the 'debug' log stack. + */ + $container['debugLogger'] = function ($c) { + $logger = new Logger('debug'); + + $logFile = $c->locator->findResource('log://userfrosting.log', true, true); + + $handler = new StreamHandler($logFile); + + $formatter = new MixedFormatter(null, null, true); + + $handler->setFormatter($formatter); + $logger->pushHandler($handler); + + return $logger; + }; + + /** + * Custom error-handler for recoverable errors. + */ + $container['errorHandler'] = function ($c) { + $settings = $c->settings; + + $handler = new ExceptionHandlerManager($c, $settings['displayErrorDetails']); + + // Register the base HttpExceptionHandler. + $handler->registerHandler('\UserFrosting\Support\Exception\HttpException', '\UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler'); + + // Register the NotFoundExceptionHandler. + $handler->registerHandler('\UserFrosting\Support\Exception\NotFoundException', '\UserFrosting\Sprinkle\Core\Error\Handler\NotFoundExceptionHandler'); + + // Register the PhpMailerExceptionHandler. + $handler->registerHandler('\phpmailerException', '\UserFrosting\Sprinkle\Core\Error\Handler\PhpMailerExceptionHandler'); + + return $handler; + }; + + /** + * Error logging with Monolog. + * + * Extend this service to push additional handlers onto the 'error' log stack. + */ + $container['errorLogger'] = function ($c) { + $log = new Logger('errors'); + + $logFile = $c->locator->findResource('log://userfrosting.log', true, true); + + $handler = new StreamHandler($logFile, Logger::WARNING); + + $formatter = new LineFormatter(null, null, true); + + $handler->setFormatter($formatter); + $log->pushHandler($handler); + + return $log; + }; + + /** + * Factory service with FactoryMuffin. + * + * Provide access to factories for the rapid creation of objects for the purpose of testing + */ + $container['factory'] = function ($c) { + + // Get the path of all of the sprinkle's factories + $factoriesPath = $c->locator->findResources('factories://', true, true); + + // Create a new Factory Muffin instance + $fm = new FactoryMuffin(); + + // Load all of the model definitions + $fm->loadFactories($factoriesPath); + + // Set the locale. Could be the config one, but for testing English should do + Faker::setLocale('en_EN'); + + return $fm; + }; + + /** + * Builds search paths for locales in all Sprinkles. + */ + $container['localePathBuilder'] = function ($c) { + $config = $c->config; + $request = $c->request; + + // Make sure the locale config is a valid string + if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { + throw new \UnexpectedValueException('The locale config is not a valid string.'); + } + + // Get default locales as specified in configurations. + $locales = explode(',', $config['site.locales.default']); + + // Add supported browser preferred locales. + if ($request->hasHeader('Accept-Language')) { + $allowedLocales = []; + foreach (explode(',', $request->getHeaderLine('Accept-Language')) as $index => $browserLocale) { + // Split to access q + $parts = explode(';', $browserLocale) ?: []; + + // Ensure locale valid + if (array_key_exists(0, $parts)) { + // Format for UF's i18n + $parts[0] = str_replace('-', '_', $parts[0]); + // Ensure locale available + if (array_key_exists($parts[0], $config['site.locales.available'])) { + // Determine preference level, and add to $allowedLocales + if (array_key_exists(1, $parts)) { + $parts[1] = str_replace('q=', '', $parts[1]); + // Sanitize with int cast (bad values go to 0) + $parts[1] = (int)$parts[1]; + } else { + $parts[1] = 1; + } + // Add to list, and format for UF's i18n. + $allowedLocales[$parts[0]] = $parts[1]; + } + } + } + + // Sort, extract keys, and merge with $locales + asort($allowedLocales, SORT_NUMERIC); + $locales = array_merge($locales, array_keys($allowedLocales)); + + // Remove duplicates, while maintaining fallback order + $locales = array_reverse(array_unique(array_reverse($locales), SORT_STRING)); + } + + return new LocalePathBuilder($c->locator, 'locale://', $locales); + }; + + /** + * Mail service. + */ + $container['mailer'] = function ($c) { + $mailer = new Mailer($c->mailLogger, $c->config['mail']); + + // Use UF debug settings to override any service-specific log settings. + if (!$c->config['debug.smtp']) { + $mailer->getPhpMailer()->SMTPDebug = 0; + } + + return $mailer; + }; + + /** + * Mail logging service. + * + * PHPMailer will use this to log SMTP activity. + * Extend this service to push additional handlers onto the 'mail' log stack. + */ + $container['mailLogger'] = function ($c) { + $log = new Logger('mail'); + + $logFile = $c->locator->findResource('log://userfrosting.log', true, true); + + $handler = new StreamHandler($logFile); + $formatter = new LineFormatter(null, null, true); + + $handler->setFormatter($formatter); + $log->pushHandler($handler); + + return $log; + }; + + /** + * Error-handler for 404 errors. Notice that we manually create a UserFrosting NotFoundException, + * and a NotFoundExceptionHandler. This lets us pass through to the UF error handling system. + */ + $container['notFoundHandler'] = function ($c) { + return function ($request, $response) use ($c) { + $exception = new NotFoundException; + $handler = new NotFoundExceptionHandler($c, $request, $response, $exception, $c->settings['displayErrorDetails']); + return $handler->handle(); + }; + }; + + /** + * Error-handler for PHP runtime errors. Notice that we just pass this through to our general-purpose + * error-handling service. + */ + $container['phpErrorHandler'] = function ($c) { + return $c->errorHandler; + }; + + /** + * Laravel query logging with Monolog. + * + * Extend this service to push additional handlers onto the 'query' log stack. + */ + $container['queryLogger'] = function ($c) { + $logger = new Logger('query'); + + $logFile = $c->locator->findResource('log://userfrosting.log', true, true); + + $handler = new StreamHandler($logFile); + + $formatter = new MixedFormatter(null, null, true); + + $handler->setFormatter($formatter); + $logger->pushHandler($handler); + + return $logger; + }; + + /** + * Override Slim's default router with the UF router. + */ + $container['router'] = function ($c) { + $routerCacheFile = false; + if (isset($c->config['settings.routerCacheFile'])) { + $routerCacheFile = $c->config['settings.routerCacheFile']; + } + + return (new Router)->setCacheFile($routerCacheFile); + }; + + /** + * Start the PHP session, with the name and parameters specified in the configuration file. + */ + $container['session'] = function ($c) { + $config = $c->config; + + // Create appropriate handler based on config + if ($config['session.handler'] == 'file') { + $fs = new FileSystem; + $handler = new FileSessionHandler($fs, $c->locator->findResource('session://'), $config['session.minutes']); + } elseif ($config['session.handler'] == 'database') { + $connection = $c->db->connection(); + // Table must exist, otherwise an exception will be thrown + $handler = new DatabaseSessionHandler($connection, $config['session.database.table'], $config['session.minutes']); + } else { + throw new \Exception("Bad session handler type '{$config['session.handler']}' specified in configuration file."); + } + + // Create, start and return a new wrapper for $_SESSION + $session = new Session($handler, $config['session']); + $session->start(); + + return $session; + }; + + /** + * Request throttler. + * + * Throttles (rate-limits) requests of a predefined type, with rules defined in site config. + */ + $container['throttler'] = function ($c) { + $throttler = new Throttler($c->classMapper); + + $config = $c->config; + + if ($config->has('throttles') && ($config['throttles'] !== null)) { + foreach ($config['throttles'] as $type => $rule) { + if ($rule) { + $throttleRule = new ThrottleRule($rule['method'], $rule['interval'], $rule['delays']); + $throttler->addThrottleRule($type, $throttleRule); + } else { + $throttler->addThrottleRule($type, null); + } + } + } + + return $throttler; + }; + + /** + * Translation service, for translating message tokens. + */ + $container['translator'] = function ($c) { + // Load the translations + $paths = $c->localePathBuilder->buildPaths(); + $loader = new ArrayFileLoader($paths); + + // Create the $translator object + $translator = new MessageTranslator($loader->load()); + + return $translator; + }; + + /** + * Set up Twig as the view, adding template paths for all sprinkles and the Slim Twig extension. + * + * Also adds the UserFrosting core Twig extension, which provides additional functions, filters, global variables, etc. + */ + $container['view'] = function ($c) { + $templatePaths = $c->locator->findResources('templates://', true, true); + + $view = new Twig($templatePaths); + + $loader = $view->getLoader(); + + $sprinkles = $c->sprinkleManager->getSprinkleNames(); + + // Add Sprinkles' templates namespaces + foreach ($sprinkles as $sprinkle) { + $path = \UserFrosting\SPRINKLES_DIR . \UserFrosting\DS . + $sprinkle . \UserFrosting\DS . + \UserFrosting\TEMPLATE_DIR_NAME . \UserFrosting\DS; + + if (is_dir($path)) { + $loader->addPath($path, $sprinkle); + } + } + + $twig = $view->getEnvironment(); + + if ($c->config['cache.twig']) { + $twig->setCache($c->locator->findResource('cache://twig', true, true)); + } + + if ($c->config['debug.twig']) { + $twig->enableDebug(); + $view->addExtension(new \Twig_Extension_Debug()); + } + + // Register the Slim extension with Twig + $slimExtension = new TwigExtension( + $c->router, + $c->request->getUri() + ); + $view->addExtension($slimExtension); + + // Register the core UF extension with Twig + $coreExtension = new CoreExtension($c); + $view->addExtension($coreExtension); + + return $view; + }; + } +} From 9db3c693db2820b019d47af51e57a2034ee2acf2 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Thu, 14 Dec 2017 18:50:55 +1100 Subject: [PATCH 010/237] Changelog for #718 and version bump --- CHANGELOG.md | 4 ++++ app/defines.php | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6cb11717..2fcee1f13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Change Log +## v4.1.16-alpha +- Use locale requested by browser when possible for guests (#718) +- Add locale drop down to registration page, with the currently applied locale selected (#718) + ## v4.1.15-alpha - Refactor `Password` into a instantiable `Hasher` class, service, and `Password` facade (#827) - Change default hash cost back to 10 and fix legacy hash detection issue diff --git a/app/defines.php b/app/defines.php index 3995e41b6..2abb227db 100755 --- a/app/defines.php +++ b/app/defines.php @@ -3,7 +3,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.1.15-alpha'); +define('UserFrosting\VERSION', '4.1.16-alpha'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\DEBUG_CONFIG', false); From 121d006b520b43dcede74ce588ad79c7b5c958b2 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Thu, 14 Dec 2017 20:54:33 +1100 Subject: [PATCH 011/237] Note v4.0.25-Alpha integration in changelog --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2fcee1f13..06c1ba361 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,16 @@ ## v4.1.16-alpha - Use locale requested by browser when possible for guests (#718) - Add locale drop down to registration page, with the currently applied locale selected (#718) +- Integrated improvements from v4.0.25-Alpha + - Support npm for frontend vendor assets, and deprecation of bower (#737) + - Duplicate frontend vendor assets are no longer downloaded (#727) + - Detect incompatibilites between frontend vendor assets (related to #727) + - Improved reliability of generated base URL, especially when using docker + - Fixed syntax error in Portugese translations + - Minimise verbosity of assets build scripts when not in 'dev' mode + - Fix to stop bower complaining about sudo when using docker + - The `assetLoader` service has been deprecated, and may be removed in the future. + - **Potential breaking change:** Some packages like `Handlebars` are organised differently at npm. If referencing vendor assets introduced by UF, make sure they are still correct. ## v4.1.15-alpha - Refactor `Password` into a instantiable `Hasher` class, service, and `Password` facade (#827) From 7230bf3b93e94645aada6173a424e5d682d43cc1 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 15 Dec 2017 09:44:24 +1100 Subject: [PATCH 012/237] Prevent line ending changes from being commited, and gave the Twig syntax colorer a helping hand. --- .gitattributes | 3 +++ app/sprinkles/core/templates/pages/abstract/base.html.twig | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..7b46d28e7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# Forces Git to handle line endings, preventing any changes (like from editors or tools) being commited. +# Also improves reliability of tools like Git Lens. +* text=auto \ No newline at end of file diff --git a/app/sprinkles/core/templates/pages/abstract/base.html.twig b/app/sprinkles/core/templates/pages/abstract/base.html.twig index 43e839ef5..bce88af9e 100644 --- a/app/sprinkles/core/templates/pages/abstract/base.html.twig +++ b/app/sprinkles/core/templates/pages/abstract/base.html.twig @@ -83,7 +83,7 @@ - + {{ assets.js() | raw }} {% endblock %} From 1522eea45a389e045dd19890a218f34ff7676a78 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 15 Dec 2017 15:03:08 +1100 Subject: [PATCH 013/237] Check permission dependent tables exist before calling `ufTable` in dashboard.js --- .../assets/userfrosting/js/pages/dashboard.js | 34 +++++++++++-------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/app/sprinkles/admin/assets/userfrosting/js/pages/dashboard.js b/app/sprinkles/admin/assets/userfrosting/js/pages/dashboard.js index f2b8a4f08..e1d644a57 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/pages/dashboard.js +++ b/app/sprinkles/admin/assets/userfrosting/js/pages/dashboard.js @@ -28,22 +28,28 @@ $(document).ready(function() { }); // Table of site activities - $("#widget-activities").ufTable({ - dataUrl: site.uri.public + "/api/activities", - useLoadingTransition: site.uf_table.use_loading_transition - }); + var activities = $("#widget-activities"); + if (activities.length) { + activities.ufTable({ + dataUrl: site.uri.public + "/api/activities", + useLoadingTransition: site.uf_table.use_loading_transition + }); + } // Table of users in current user's group - $("#widget-group-users").ufTable({ - dataUrl: site.uri.public + "/api/groups/g/" + page.group_slug + "/users", - useLoadingTransition: site.uf_table.use_loading_transition - }); + var groupUsers = $("#widget-group-users"); + if (groupUsers.length) { + groupUsers.ufTable({ + dataUrl: site.uri.public + "/api/groups/g/" + page.group_slug + "/users", + useLoadingTransition: site.uf_table.use_loading_transition + }); - // Bind user creation button - bindUserCreationButton($("#widget-group-users")); + // Bind user creation button + bindUserCreationButton(groupUsers); - // Bind user table buttons - $("#widget-group-users").on("pagerComplete.ufTable", function () { - bindUserButtons($(this)); - }); + // Bind user table buttons + groupUsers.on("pagerComplete.ufTable", function () { + bindUserButtons($(this)); + }); + } }); From ac5d120a45f50cf3501a570f579c34489d3ffd75 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 15 Dec 2017 17:35:36 +1100 Subject: [PATCH 014/237] Clean up code for legacy frontend assets, and fix for jQuery version range (3.2.1 is quite a jump from 2.2.4). --- app/sprinkles/core/package.json | 2 +- build/gulpfile.js | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/package.json b/app/sprinkles/core/package.json index 1cbf62e88..992922482 100644 --- a/app/sprinkles/core/package.json +++ b/app/sprinkles/core/package.json @@ -5,7 +5,7 @@ "clipboard": "^1.5.16", "font-awesome": "^4.7.0", "handlebars": "^3.0.3", - "jquery": ">=2.2.4", + "jquery": "^2.2.4", "jquery-ui": "^1.12.0", "jquery-validation": "~1.14.0", "select2": "^4.0.3", diff --git a/build/gulpfile.js b/build/gulpfile.js index 6d7f262b3..68b84b693 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -40,6 +40,14 @@ const bundleConfigFile = `./${bundleFile}`; gulp.task('assets-install', () => { 'use strict'; + // Legacy clean up + let legacyVendorAssets = '../app/sprinkles/*/assets/vendor/**'; + if (del.sync(legacyVendorAssets, { dryRun: true, force: true }).length > 0) { + logger('Frontend vendor assets are now located at "app/assets".\nStarting clean up of legacy vendor assets...'); + del.sync(legacyVendorAssets, { force: true }); + logger('Complete.') + } + let mergePkg = require('@userfrosting/merge-package-dependencies'); // See if there are any yarn packages. From f15ec32371b77a2950f4fac754b359b274d5a425 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 15 Dec 2017 17:47:03 +1100 Subject: [PATCH 015/237] Use HTTPS for placeholders and jQuery CDN to prevent mixed content blocking when site uses HTTPS. --- .../core/templates/pages/about.html.twig | 26 +++++++++---------- .../templates/pages/abstract/base.html.twig | 2 +- .../core/templates/pages/index.html.twig | 20 +++++++------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/app/sprinkles/core/templates/pages/about.html.twig b/app/sprinkles/core/templates/pages/about.html.twig index 95f9b7261..ee9c77f9d 100755 --- a/app/sprinkles/core/templates/pages/about.html.twig +++ b/app/sprinkles/core/templates/pages/about.html.twig @@ -12,7 +12,7 @@
- +

About Modern Business

@@ -30,7 +30,7 @@
- +

John Smith
Job Title @@ -49,7 +49,7 @@

- +

John Smith
Job Title @@ -68,7 +68,7 @@

- +

John Smith
Job Title @@ -87,7 +87,7 @@

- +

John Smith
Job Title @@ -106,7 +106,7 @@

- +

John Smith
Job Title @@ -125,7 +125,7 @@

- +

John Smith
Job Title @@ -151,22 +151,22 @@

- +
- +
- +
- +
- +
- +
diff --git a/app/sprinkles/core/templates/pages/abstract/base.html.twig b/app/sprinkles/core/templates/pages/abstract/base.html.twig index bce88af9e..1fdd45aa0 100644 --- a/app/sprinkles/core/templates/pages/abstract/base.html.twig +++ b/app/sprinkles/core/templates/pages/abstract/base.html.twig @@ -81,7 +81,7 @@ {# Override this block in a child layout template or page template to override site-level scripts. #} {% block scripts_site %} - + diff --git a/app/sprinkles/core/templates/pages/index.html.twig b/app/sprinkles/core/templates/pages/index.html.twig index fea1213bf..a0c0630a0 100755 --- a/app/sprinkles/core/templates/pages/index.html.twig +++ b/app/sprinkles/core/templates/pages/index.html.twig @@ -20,21 +20,21 @@
- +
From d6a042438a49c7246a0403b223ab50493c4230a0 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 15 Dec 2017 18:49:07 +1100 Subject: [PATCH 016/237] Fix for #809, light optimisations and style standardising for uf-alerts.js --- .../core/assets/userfrosting/js/uf-alerts.js | 87 ++++++++++--------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/app/sprinkles/core/assets/userfrosting/js/uf-alerts.js b/app/sprinkles/core/assets/userfrosting/js/uf-alerts.js index c74c5c1ad..06a889c6a 100644 --- a/app/sprinkles/core/assets/userfrosting/js/uf-alerts.js +++ b/app/sprinkles/core/assets/userfrosting/js/uf-alerts.js @@ -7,7 +7,7 @@ * ufAlerts can be initialized on any container element as follows: * - * $("#myDiv").ufAlerts(options); + * $('#myDiv').ufAlerts(options); * * `options` is an object containing any of the following parameters: * @param {string} url The absolute URL from which to fetch flash alerts. @@ -34,17 +34,17 @@ * @author Alexander Weissman */ ;(function($, window, document, undefined) { - "use strict"; + 'use strict'; // Define plugin name and defaults. - var pluginName = "ufAlerts", + var pluginName = 'ufAlerts', defaults = { - url : site.uri.public + "/alerts", + url : site.uri.public + '/alerts', scrollToTop : true, scrollWhenVisible : false, agglomerate : false, - alertMessageClass : "uf-alert-message", - alertTemplateId : "uf-alert-template", + alertMessageClass : 'uf-alert-message', + alertTemplateId : 'uf-alert-template', DEBUG : false }; @@ -62,7 +62,7 @@ // Plugin variables this.alerts = []; this._newAlertsPromise = $.Deferred().resolve(); - this._alertTemplateHtml = $("#" + this.settings.alertTemplateId).html(); + this._alertTemplateHtml = $('#' + this.settings.alertTemplateId).html(); this._alertTypePriorities = { danger : 3, warning: 2, @@ -70,10 +70,10 @@ info : 0 }; this._alertTypeIcon = { - danger : "fa-ban", - warning: "fa-warning", - success: "fa-check", - info : "fa-info" + danger : 'fa-ban', + warning: 'fa-warning', + success: 'fa-check', + info : 'fa-info' }; return this; @@ -89,11 +89,11 @@ this.alerts.length = 0; if (this.settings.agglomerate) { - this.element.toggleClass("alert", false) - .toggleClass("alert-info", false) - .toggleClass("alert-success", false) - .toggleClass("alert-warning", false) - .toggleClass("alert-danger", false); + this.element.toggleClass('alert', false) + .toggleClass('alert-info', false) + .toggleClass('alert-success', false) + .toggleClass('alert-warning', false) + .toggleClass('alert-danger', false); } // Clear any alert HTML @@ -106,9 +106,15 @@ */ fetch: function() { // Set a promise, so that any chained calls after fetch can wait until the messages have been retrieved - this._newAlertsPromise = $.getJSON(this.settings.url) - .done($.proxy(this._fetchSuccess, this)) - .fail($.proxy(this._fetchFailure, this)); + this._newAlertsPromise = $.ajax({ + url: this.settings.url, + cache: false + }).then( + // Success + this._fetchSuccess.bind(this), + // Failure + this._fetchFailure.bind(this) + ); return this.$element; }, @@ -117,19 +123,19 @@ */ _fetchSuccess: function(alerts) { if (alerts != null) this.alerts = $.merge(this.alerts, alerts); - this.$element.trigger("fetch." + this._name); + this.$element.trigger('fetch.' + this._name); }, /** * Failure callback for fetch */ _fetchFailure: function(response) { - this.$element.trigger("error." + this._name); - if ((typeof site !== "undefined") && site.debug.ajax && response.responseText) { + this.$element.trigger('error.' + this._name); + if ((typeof site !== 'undefined') && site.debug.ajax && response.responseText) { document.write(response.responseText); document.close(); } else { if (this.settings.DEBUG) { - console.warn("Error (" + response.status + "): " + response.responseText ); + console.warn('Error (' + response.status + '): ' + response.responseText ); } } }, @@ -138,8 +144,8 @@ */ push: function(options) { this.alerts.push({ - "type" : options[0], - "message": options[1] + type : options[0], + message: options[1] }); return this.$element; @@ -149,11 +155,11 @@ */ render: function() { // Wait for promise completion, only if promise is unresolved. - if (this._newAlertsPromise.state() == "resolved" || this._newAlertsPromise.state() == "rejected") { + if (this._newAlertsPromise.state() == 'resolved' || this._newAlertsPromise.state() == 'rejected') { this._render(); } else { - $.when(this._newAlertsPromise).then($.proxy(this._render, this)); + $.when(this._newAlertsPromise).then(this._render.bind(this)); } return this.$element; @@ -163,7 +169,7 @@ */ _render: function() { // Holds generated HTML - var alertHtml = ""; + var alertHtml = ''; // Only compile alerts if there are alerts to display if (this.alerts.length > 0) { // Prepare template @@ -172,10 +178,10 @@ // If agglomeration is enabled, set the container to the highest priority alert type if (this.settings.agglomerate) { // Holds generated agglomerated alerts - var alertMessage = "
    "; + var alertMessage = '
      '; // Determine overall alert priority - var alertContainerType = "info"; + var alertContainerType = 'info'; for (i = 0; i < this.alerts.length; i++) { if (this._alertTypePriorities[this.alerts[i].type] > this._alertTypePriorities[alertContainerType]) { alertContainerType = this.alerts[i].type; @@ -183,12 +189,12 @@ } // Compile each alert - var aggTemplate = Handlebars.compile("
    • {{ message }}
    • "); + var aggTemplate = Handlebars.compile('
    • {{ message }}
    • '); for (i = 0; i < this.alerts.length; i++) { alertMessage += aggTemplate(this.alerts[i]); } - alertMessage += "
    "; + alertMessage += '
'; // Generate complete alert HTML alertHtml = alertTemplate({ @@ -200,7 +206,7 @@ else { // Compile each alert. for (i = 0; i < this.alerts.length; i++) { - alert = this.alerts[i]; + var alert = this.alerts[i]; // Inject icon alert.icon = this._alertTypeIcon[alert.type]; @@ -214,15 +220,15 @@ this.$element.html(alertHtml); // Scroll to top of alert location is new alerts output, and auto scrolling is enabled - if (this.settings.scrollToTop && alertHtml !== "") { + if (this.settings.scrollToTop && alertHtml !== '') { // Don't scroll if already visible, unless scrollWhenVisible is true if (!this._alertsVisible() || this.settings.scrollWhenVisible) { - $("html, body").animate({ scrollTop: this.$element.offset().top }, "fast"); + $('html, body').animate({ scrollTop: this.$element.offset().top }, 'fast'); } } // Trigger render events - this.$element.trigger("render." + this._name); + this.$element.trigger('render.' + this._name); }, /** * Returns true if alerts container is completely within the viewport. @@ -243,13 +249,10 @@ // Unbind any bound events this.$element.off('.' + this._name); - // Grab jQuery wrapped element before plugin destruction - var $element = this.$element; - // Remove plugin from element this.$element.removeData(this._name); - return $element; + return this.$element; } }); @@ -272,11 +275,11 @@ return instance[methodOrOptions]( Array.prototype.slice.call(arguments, 1)); } else { - console.warn( 'Method ' + methodOrOptions + ' is private!' ); + console.warn('Method ' + methodOrOptions + ' is private!'); } } else { - console.warn( 'Method ' + methodOrOptions + ' does not exist.' ); + console.warn('Method ' + methodOrOptions + ' does not exist.'); } }; })(jQuery, window, document); \ No newline at end of file From 372713769491d330b928b55ed8e9159526977b38 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 15 Dec 2017 20:06:36 +1100 Subject: [PATCH 017/237] `preferLocal` defaults to true and `localDir` is not a valid option. :no_mouth: --- build/gulpfile.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 68b84b693..69120e676 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -79,8 +79,6 @@ gulp.task('assets-install', () => { let childProcess = require('child_process'); childProcess.execSync('yarn install --flat --no-lockfile --non-interactive', { cwd: '../app/assets', - preferLocal: true,// Local over PATH. - localDir: './node_modules/.bin', stdio: doILog ? 'inherit' : '' }); } @@ -117,16 +115,12 @@ gulp.task('assets-install', () => { // Remove extraneous packages childProcess.execSync('bower prune', { cwd: '../app/assets', - preferLocal: true,// Local over PATH. - localDir: './node_modules/.bin', stdio: doILog ? 'inherit' : '' }); // Perform installation childProcess.execSync('bower install -q --allow-root', { // --allow-root stops bower from complaining about being in 'sudo'. cwd: '../app/assets', - preferLocal: true,// Local over PATH. - localDir: './node_modules/.bin', stdio: doILog ? 'inherit' : '' }); // Yarn is able to output its completion. Bower... not so much. From c0b2cca65e3440459dbc52eb477438347fdcc888 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 15 Dec 2017 20:22:32 +1100 Subject: [PATCH 018/237] Build clean up improvements, and note about assets-install behavior. --- build/gulpfile.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 69120e676..7d6fba7c9 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -36,6 +36,7 @@ const bundleConfigFile = `./${bundleFile}`; /** * Vendor asset task + * NOTE: This task cannot be run directly from the gulp cli. Use the npm run script instead. */ gulp.task('assets-install', () => { 'use strict'; @@ -84,7 +85,7 @@ gulp.task('assets-install', () => { } else del.sync([ '../app/assets/package.json', - '../app/assets/node_modules/' + '../app/assets/node_modules/**' ], { force: true }); // See if there are any bower packages. @@ -128,7 +129,7 @@ gulp.task('assets-install', () => { } else del.sync([ '../app/assets/bower.json', - '../app/assets/bower_components/' + '../app/assets/bower_components/**' ], { force: true }); }); @@ -257,8 +258,8 @@ gulp.task('bundle-clean', () => { // Deletes assets fetched by assets-install gulp.task('assets-clean', () => { 'use strict'; - return del(['../app/assets/bower_components/', '../app/assets/node_modules/', '../app/assets/bower.json', '../app/assets/package.json'], { force: true }); + return del('../app/assets/*', { force: true }); }); // Deletes all generated, or acquired files. -gulp.task('clean', ['public-clean', 'bundle-clean', 'assets-clean'], () => { }); \ No newline at end of file +gulp.task('clean', ['public-clean', 'bundle-clean', 'assets-clean']); \ No newline at end of file From 2a4a7aa6cef9f9aa817fcd5bb7200eb8a4335719 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 16 Dec 2017 12:11:24 -0500 Subject: [PATCH 019/237] Proposed new contribution guideline Includes branch usage clarifications and Milestone organization. --- .github/CONTRIBUTING.md | 73 +++++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 10 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 99b92e005..d78dfb5a2 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -44,28 +44,76 @@ When it's time to integrate changes, our git flow more or less follows http://nv ### Branches -- `master`: The current release or release candidate. Always numbered as `major.minor.revision`, possibly with an `-alpha` or `-beta` extension as well. -- `develop`: During alpha/beta, contains major changes to a release candidate. After beta, contains breaking changes that will need to wait for the next version to be integrated. Always numbered as `major.minor.x`, possibly with an `-alpha` or `-beta` extension as well. +#### `master` +The current release or release candidate. Always numbered as `major.minor.revision`, possibly with an `-alpha`, `-beta` or `-RC` extension as well. Commits should **never** be send directly on this branch. -### Changes +#### `hotfix` +Contains the next bug fix release, typically matching the next `revision` version. Any changes not introducing a breaking change can be committed to this branch. Always numbered as `major.minor.revision`. -#### Hotfixes +When ready, changes should be merged into both **master** and **develop**. -Hotfixes should be created in a separate branch, and then merged into both **master** and **develop**. +#### `develop` +Contains breaking changes that will need to wait for the next version to be integrated. Typically matched the next `minor` version. Always numbered as `major.minor.x`. -#### Features +When ready, changes should be merged into both **master** and **hotfix**. -New features that introduce some breaking changes should be created in a separate branch. When they are ready, they can be merged into `develop`. +#### `feature-*` +New features that introduce some breaking changes or incomplete code should be committed in a separate `feature-{name}` branch. + +When ready, the branch should be **[squashed-merged](https://github.com/blog/2141-squash-your-commits)** ([guide](https://stackoverflow.com/a/5309051/445757)) into `develop` (or `hotfix` if it doesn't introduce a breaking change). ### Releases -After every release, the `master` branch (and possibly `develop`, for minor/major releases) should immediately be version-bumped. That way, new changes can be accumulated until the next release. +After every release, the `hotfix` branch (and possibly `develop`, for minor/major releases) should immediately be version-bumped. That way, new changes can be accumulated until the next release. When a new version is created, the version number need to be changed in `app/define.php`. `CHANGELOG.md` should also be updated and the associated tag should be created on Github. -#### Alpha/beta releases +#### Alpha/beta/RC releases + +During alpha/beta/RC, a release candidate always sits on the `master` branch. During the alpha/beta phase, major changes can still be integrated into `master` from `develop`. However, this should bump the revision number instead of the minor/major number. During RC, only _hotfixes_ can be merged into `master`. + +## Working together + +### Issues + +Issues are used as a todo list. Each issue represent something that needs to be fixed, added or improved. Be sure to assign issues to yourself when working on something so everyones knows this issue is taken care of. + +Issues are tagged to represent the feature or category it refers to. We also have some special tags to help organize issues. These includes: + + - [`good first issue`](https://github.com/userfrosting/UserFrosting/labels/good%20first%20issue): If this is your first time contributing to UserFrosting, look for the `good first issue` tag. It's associated with easier issues anyone can tackle. + + - [`up-for-grabs`](https://github.com/userfrosting/UserFrosting/labels/up-for-grabs): Theses issues have not yet been assigned to anybody. Look for theses when you want to start working on a new issue. + + - [`needs discussion`](https://github.com/userfrosting/UserFrosting/labels/needs%20discussion) : This issue needs to be discussed with the dev team before being implemented as more information is required, questions remain or a higher level decision needs to be made. + + - [`needs more info`](https://github.com/userfrosting/UserFrosting/labels/needs%20more%20info): More information is required from the author of the issue. + +### Milestones + +In order to keep a clear roadmap, milestones are used to track what is happening and what needs to be done. Milestones are used to classify problems by: +- Things that need to be done ASAP +- Things we are doing right now +- Things we will probably do soon +- Things we probably will not do soon -During alpha/beta, a release candidate sits on the `master` branch. Minor improvements should be treated as hotfixes, while major changes should be treated as features. In alpha/beta, major changes can still be integrated into `master` from `develop`. However, this should bump the revision number instead of the minor/major number. +**Things that need to be done ASAP**: this is the highest priority and this milestone should always be empty. Issues related to important bug fixes should be set on this milestone immediately. The milestone always refers to the next version of _revision_, also known as the next bugfix version. + +**Things we are doing right now**: this is the "main" milestone we are currently working on. Usually represents the next `minor` version, but may also represent the next major version when the focus is on the next major release. + +**Things we’ll probably do soon**: It's a "Next Tasks" milestone. These tasks will be addressed in the near future, but not close enough for the next version. Usually represents the second minor revision **and** the next major release. + +**Things we probably won’t do soon**: We refer to these issues and sometimes look through them, but they are easy to ignore and sometimes intentionally ignored. Represent issues without milestones that do not have a defined timeframe. + + +To maintain a clear history of progress on each milestone, milestones must be closed when completed and the corresponding version released. A new milestone must then be created for the next release. In addition, the milestone version must be updated when new versions are released. + +## Learn documentation + +The [Learn Documentation](https://learn.userfrosting.com) should always be updated along side code changes. + +Changes to the [learn repository](https://github.com/userfrosting/learn) should follow the same logic as the main repository, ie. any changes applied to the `hotfix` branch should be documented in the learn `hotfix` branch. This also apply to `feature-*` branches. + +Additionally, the `learn` repository can have `dev-*` for learn specific features and fixes. ## Building the API documentation @@ -74,3 +122,8 @@ To build the API documentation, install [ApiGen](http://www.apigen.org/) globall `apigen generate --source UserFrosting/app,userfrosting-assets/src,userfrosting-config/Config,userfrosting-fortress/Fortress,userfrosting-i18n/I18n,userfrosting-session/Session,userfrosting-support/Support --destination userfrosting-api --exclude *vendor*,*_meta* --template-theme "bootstrap"` from inside your dev directory. + +## Useful tools + +If you are using Atom, be sure to checkout theses useful packages : + - [Docblockr](https://atom.io/packages/docblockr) (Used to generate [documentation block](https://github.com/userfrosting/UserFrosting/blob/master/STYLE-GUIDE.md#documentation)) From f444cb95b7aeaa9ce16982aedab65f3bdd380b07 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Wed, 20 Dec 2017 18:08:48 +1100 Subject: [PATCH 020/237] Bumped version to 4.2.0 --- CHANGELOG.md | 2 +- app/defines.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06c1ba361..16afb961e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Change Log -## v4.1.16-alpha +## v4.2.0-alpha - Use locale requested by browser when possible for guests (#718) - Add locale drop down to registration page, with the currently applied locale selected (#718) - Integrated improvements from v4.0.25-Alpha diff --git a/app/defines.php b/app/defines.php index 2abb227db..0fb809245 100755 --- a/app/defines.php +++ b/app/defines.php @@ -3,7 +3,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.1.16-alpha'); +define('UserFrosting\VERSION', '4.2.0-alpha'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\DEBUG_CONFIG', false); From 15dac1974912ed274d4288ccbec7a3c8e13773a1 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Wed, 20 Dec 2017 18:34:42 +1100 Subject: [PATCH 021/237] Git mashed the cherry when picking it. --- build/gulpfile.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 72cd7646a..832f7de02 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -102,7 +102,7 @@ gulp.task('bundle-build', () => { case 'merge': // If using this collision rule, keep in mind any bundling options will also be merged. // Inspect the produced 'bundle.config.json' file in the 'build' folder to ensure options are correct. - config.bundle[bundleName] = merge(currentConfig.bundle[bundleName], config.bundle[bundleName]); + config.bundle[bundleName] = merge(config.bundle[bundleName], currentConfig.bundle[bundleName]); break; case 'ignore': // Do nothing. This simply exists to prevent falling through to error catchment. From 90b4904cfd0dac3e8355be6edd1e307b98228f09 Mon Sep 17 00:00:00 2001 From: alexweissman Date: Fri, 22 Dec 2017 22:50:25 -0500 Subject: [PATCH 022/237] bump this feature to 4.2 --- CHANGELOG.md | 4 +++- app/defines.php | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5046e5a66..f40bcd979 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,10 @@ # Change Log +## v4.2.0 +- Implement `withRaw`, `withSum`, `withAvg`, `withMin`, `withMax` (see https://github.com/laravel/framework/pull/16815) + ## v4.1.14-alpha - Fix issue with scopes being applied twice in Unique::getPaginatedQuery (https://github.com/userfrosting/extend-user/issues/2) -- Implement withRaw, withSum, withAvg, withMin, withMax (see https://github.com/laravel/framework/pull/16815) ## v4.1.13-alpha - `ufTable`: Implement `rowTemplate` for customizing how rows are rendered (#787) diff --git a/app/defines.php b/app/defines.php index b188f7eb1..1ac8841f8 100755 --- a/app/defines.php +++ b/app/defines.php @@ -3,7 +3,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.1.14-alpha'); +define('UserFrosting\VERSION', '4.2.0'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\DEBUG_CONFIG', false); From cdbc42514810de284375f82d906bd90f1d26dcdc Mon Sep 17 00:00:00 2001 From: alexweissman Date: Mon, 25 Dec 2017 15:19:36 -0500 Subject: [PATCH 023/237] refactor ufForm, expose jQuery validation and ajax options --- .../core/assets/userfrosting/js/uf-form.js | 315 ++++++++++++------ 1 file changed, 214 insertions(+), 101 deletions(-) diff --git a/app/sprinkles/core/assets/userfrosting/js/uf-form.js b/app/sprinkles/core/assets/userfrosting/js/uf-form.js index 15952ab45..313cba58e 100644 --- a/app/sprinkles/core/assets/userfrosting/js/uf-form.js +++ b/app/sprinkles/core/assets/userfrosting/js/uf-form.js @@ -28,7 +28,7 @@ * * UserFrosting https://www.userfrosting.com * @author Alexander Weissman - * + * * @todo Implement proper fallback for when `set` function isn't supported by FormData. */ ;(function($, window, document, undefined) { @@ -37,30 +37,62 @@ // Define plugin name and defaults. var pluginName = 'ufForm', defaults = { - validators: { - 'rules' : {}, - 'messages': {} - }, + DEBUG: false, + site : site, // global site variables submittingText : "", beforeSubmitCallback: null, binaryCheckboxes : true, // submit checked/unchecked checkboxes as 0/1 values keyupDelay : 0, - DEBUG: false + validator: { + rules : {}, + messages : {} + }, + // Deprecated + validators: { + rules : {}, + messages : {} + } }; // Constructor function Plugin (element, options) { this.element = element[0]; this.$element = $(this.element); + var lateDefaults = { - encType : (typeof this.$element.attr('enctype') !== 'undefined') ? this.$element.attr('enctype') : '', - msgTarget: this.$element.find('.js-form-alerts:first') + submitButton : this.$element.find('button[type=submit]'), + msgTarget : this.$element.find('.js-form-alerts:first'), + validator : { + submitHandler: $.proxy(this.defaultSubmitHandler, this), + onkeyup : $.proxy(this._onKeyUp, this) + }, + ajax : { + // Override jQuery's strict JSON parsing + converters : { + 'text json': $.proxy(this._defaultResponseParser, this) + }, + // Response type + dataType : this._debugAjax ? 'html' : 'json', + // Disable the submit button before sending the request + beforeSend : $.proxy(this.disableSubmit, this), + // enable the submit button once the request completes + complete : $.proxy(this.enableSubmit, this) + } }; + + // Legacy options + if ('validators' in options) { + options.validator = options.validators; + } + this.settings = $.extend(true, {}, defaults, lateDefaults, options); + this._defaults = $.extend(true, {}, defaults, lateDefaults); this._name = pluginName; this._debugAjax = (typeof site !== 'undefined') && site.debug.ajax; + this.submitButtonText = this.settings.submitButton ? this.settings.submitButton.html() : ''; + // Detect changes to element attributes this.$element.attrchange({ callback: function (event) { @@ -69,130 +101,202 @@ }); // Setup validator - this.validator = this.$element.validate({ - rules : this.settings.validators.rules, - messages : this.settings.validators.messages, - submitHandler: $.proxy(this._submitHandler, this), - onkeyup : $.proxy(this._onKeyUp, this) - }); + this.validator = this.$element.validate(this.settings.validator); return this; } // Functions + /** + * Set "loading" text for submit button, if it exists, and disable button + */ + Plugin.prototype.disableSubmit = function() { + var submitButton = this.settings.submitButton; + // Do nothing, if the button is already disabled + if (submitButton.prop('disabled')) { + return this; + } + + if (!submitButton) { + console.error('Submit button not found.'); + return this; + } + + this.submitButtonText = submitButton.html(); + submitButton.prop('disabled', true); + submitButton.html(this.settings.submittingText); + return this; + }; + + /** + * Restore button text and re-enable submit button + * + * @return this + */ + Plugin.prototype.enableSubmit = function() { + var submitButton = this.settings.submitButton; + + // Do nothing, if the button is already enabled + if (!submitButton.prop('disabled')) { + return this; + } + + if (!submitButton) { + console.error('Submit button not found.'); + return this; + } + + submitButton.prop('disabled', false); + submitButton.html(this.submitButtonText); + return this; + }; + /** * Handles the form submission after successful client-side validation. + * + * @param {Element} form + * @param {Event} event */ - Plugin.prototype._submitHandler = function(form, event) { + Plugin.prototype.defaultSubmitHandler = function(form, event) { // Execute any "before submit" callback if (this.settings.beforeSubmitCallback) { this.settings.beforeSubmitCallback(); } - var $form = $(form); + // Get basic request parameters. + var ajaxParams = this.prepareRequestData(form, this.settings.ajax); + + // Submit the form + this.submitForm(ajaxParams); + }; - // Set "loading" text for submit button, if it exists, and disable button - var submitButton = $form.find('button[type=submit]'); - if (submitButton) { - var submitButtonText = submitButton.html(); - submitButton.prop('disabled', true); - submitButton.html(this.settings.submittingText); + /** + * Submit the form via AJAX + * @param {object} reqParams + * @returns {Deferred} + */ + Plugin.prototype.submitForm = function(reqParams) { + return $.ajax(reqParams).then( + // Submission successful + $.proxy(this._defaultSuccess, this), + // Submission failed + $.proxy(this._defaultError, this) + ); + } + + /** + * Default handler for AJAX request success. + * + * @param {object} data + * @param {string} textStatus + * @param {jqXHR} jqXHR + * @return {jqXHR} + */ + Plugin.prototype._defaultSuccess = function(data, textStatus, jqXHR) { + this.$element.trigger('submitSuccess.ufForm', [data, textStatus, jqXHR]); + return jqXHR; + }; + + /** + * Default handler for AJAX request fail/error. + * + * @param {jqXHR} jqXHR + * @param {string} textStatus + * @param {string} errorThrown + * @return {jqXHR} + */ + Plugin.prototype._defaultError = function(jqXHR, textStatus, errorThrown) { + // Error messages + if (this._debugAjax && jqXHR.responseText) { + this.$element.trigger('submitError.ufForm', [jqXHR, textStatus, errorThrown]); + document.write(jqXHR.responseText); + document.close(); + } else { + if (this.settings.DEBUG) { + console.error(jqXHR.status + ': ' + jqXHR.responseText); + } + // Display errors on failure + // TODO: ufAlerts widget should have a 'destroy' method + if (!this.settings.msgTarget.data('ufAlerts')) { + this.settings.msgTarget.ufAlerts(); + } else { + this.settings.msgTarget.ufAlerts('clear'); + } + + this.settings.msgTarget.ufAlerts('fetch').ufAlerts('render'); + this.settings.msgTarget.on('render.ufAlerts', $.proxy(function () { + this.$element.trigger('submitError.ufForm', [jqXHR, textStatus, errorThrown]); + }, this)); } + return jqXHR; + }; - // Get basic request parameters. - var reqParams = { - converters: { - // Override jQuery's strict JSON parsing - 'text json': function(result) { - try { - // First try to use native browser parsing - if (typeof JSON === 'object' && typeof JSON.parse === 'function') { - return JSON.parse(result); - } else { - return $.parseJSON(result); - } - } catch (e) { - // statements to handle any exceptions - console.warn('Could not parse expected JSON response.'); - return {}; - } - } - }, + Plugin.prototype._defaultResponseParser = function(result) { + try { + // First try to use native browser parsing + if (typeof JSON === 'object' && typeof JSON.parse === 'function') { + return JSON.parse(result); + } else { + return $.parseJSON(result); + } + } catch (e) { + // statements to handle any exceptions + console.warn('Could not parse expected JSON response.'); + return {}; + } + }; - dataType: this._debugAjax ? 'html' : 'json', - type: this.$element.attr('method'), - url: this.$element.attr('action') + /** + * Prepares the ajax request parameters, serializing the form according to its enctype, + * and then using the serialized data as the ajax `data` parameter. + * + * @param {Element} form + * @param {object} ajaxParams + * @return {object} + */ + Plugin.prototype.prepareRequestData = function(form, ajaxParams) { + // Set ajax type and url from form method and action, if not otherwise set. + var ajaxDefaults = { + type : this.$element.attr('method'), + url : this.$element.attr('action'), + contentType : (typeof this.$element.attr('enctype') === 'undefined') ? + 'application/x-www-form-urlencoded; charset=UTF-8' : + this.$element.attr('enctype') }; + ajaxParams = $.extend(true, {}, ajaxDefaults, ajaxParams); + // Get the form encoding type from the users HTML, and chose an encoding form. - if (this.settings.encType.toLowerCase() === 'multipart/form-data') { - reqParams.data = this._multipartData($form); - // add additional params to fix jquery errors - reqParams.cache = false; - reqParams.contentType = false; - reqParams.processData = false; + if (ajaxParams.contentType.toLowerCase() === 'multipart/form-data') { + ajaxParams.data = this._multipartData(form); + // Disable caching + ajaxParams.cache = false; + // Prevent serialization of FormData object + ajaxParams.processData = false; + // Allow the browser to set the Content-Type header instead, + // so it can include the boundary value + ajaxParams.contentType = false; } else { - reqParams.data = this._urlencodeData($form); + ajaxParams.data = this._urlencodeData(form); } - // Submit the form via AJAX - $.ajax(reqParams).then( - // Submission successful - $.proxy(function(data, textStatus, jqXHR) { - // Restore button text and re-enable submit button - if (submitButton) { - submitButton.prop('disabled', false ); - submitButton.html(submitButtonText); - } - - this.$element.trigger('submitSuccess.ufForm', [data, textStatus, jqXHR]); - return jqXHR; - }, this), - // Submission failed - $.proxy(function(jqXHR, textStatus, errorThrown) { - // Restore button text and re-enable submit button - if (submitButton) { - submitButton.prop('disabled', false ); - submitButton.html(submitButtonText); - } - // Error messages - if (this._debugAjax && jqXHR.responseText) { - this.$element.trigger('submitError.ufForm', [jqXHR, textStatus, errorThrown]); - document.write(jqXHR.responseText); - document.close(); - } else { - if (this.settings.DEBUG) { - console.log('Error (' + jqXHR.status + '): ' + jqXHR.responseText ); - } - // Display errors on failure - // TODO: ufAlerts widget should have a 'destroy' method - if (!this.settings.msgTarget.data('ufAlerts')) { - this.settings.msgTarget.ufAlerts(); - } else { - this.settings.msgTarget.ufAlerts('clear'); - } - - this.settings.msgTarget.ufAlerts('fetch').ufAlerts('render'); - this.settings.msgTarget.on('render.ufAlerts', $.proxy(function () { - this.$element.trigger('submitError.ufForm', [jqXHR, textStatus, errorThrown]); - }, this)); - } - return jqXHR; - }, this) - ); + return ajaxParams; }; /** * Helper function for encoding data as urlencoded + * + * @param {Element} form + * @return {string} */ Plugin.prototype._urlencodeData = function(form) { // Serialize and post to the backend script in ajax mode var serializedData; if (this.settings.binaryCheckboxes) { - serializedData = form.find(':input').not(':checkbox').serialize(); + serializedData = $(form).find(':input').not(':checkbox').serialize(); // Get unchecked checkbox values, set them to 0 - form.find('input[type=checkbox]:enabled').each(function() { + $(form).find('input[type=checkbox]:enabled').each(function() { if ($(this).is(':checked')) { serializedData += '&' + encodeURIComponent(this.name) + '=1'; } else { @@ -201,7 +305,7 @@ }); } else { - serializedData = form.find(':input').serialize(); + serializedData = $(form).find(':input').serialize(); } return serializedData; @@ -209,15 +313,18 @@ /** * Helper function for encoding data as multipart/form-data + * + * @param {Element} form + * @return {FormData} */ Plugin.prototype._multipartData = function(form) { // Use FormData to wrap form contents. // https://developer.mozilla.org/en/docs/Web/API/FormData - var formData = new FormData(form[0]); + var formData = new FormData(form); // Serialize and post to the backend script in ajax mode if (this.settings.binaryCheckboxes) { // Get unchecked checkbox values, set them to 0. - var checkboxes = form.find('input[type=checkbox]:enabled'); + var checkboxes = $(form).find('input[type=checkbox]:enabled'); // Feature detection. Several browsers don't support `set` if (typeof formData.set !== 'function') { this.settings.msgTarget.ufAlerts('push', 'danger', "Your browser is missing a required feature. This form will still attempt to submit, but if it fails, you'll need to use Chrome for desktop or FireFox for desktop."); @@ -237,6 +344,12 @@ return formData; }; + /** + * Implements a delay for revalidating the form. + * + * @param {Element} form + * @param {Event} event + */ Plugin.prototype._onKeyUp = function(element, event) { var validator = this.validator; // See http://stackoverflow.com/questions/41363409/jquery-validate-add-delay-to-keyup-validation From 1a34e5a94414af8e8894b6e47bc718f92ad0eb96 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 11 Jan 2018 20:46:27 -0500 Subject: [PATCH 024/237] Merged `feature-migrator` in `develop` --- .gitignore | 1 + CHANGELOG.md | 45 +- app/sprinkles/account/composer.json | 5 + .../account/src/Bakery/CreateAdminUser.php | 82 ++- .../Migrations/v400/ActivitiesTable.php | 2 +- .../Database/Migrations/v400/GroupsTable.php | 2 +- .../Migrations/v400/PasswordResetsTable.php | 2 +- .../Migrations/v400/PermissionRolesTable.php | 2 +- .../Migrations/v400/PermissionsTable.php | 28 +- .../Migrations/v400/PersistencesTable.php | 2 +- .../Migrations/v400/RoleUsersTable.php | 2 +- .../Database/Migrations/v400/RolesTable.php | 2 +- .../Database/Migrations/v400/UsersTable.php | 2 +- .../Migrations/v400/VerificationsTable.php | 2 +- .../src/ServicesProvider/ServicesProvider.php | 12 +- .../account/tests/Unit/FactoriesTest.php | 27 +- app/sprinkles/admin/composer.json | 5 + .../admin/tests/Integration/SprunjeTests.php | 16 +- app/sprinkles/core/composer.json | 5 + app/sprinkles/core/config/default.php | 3 + .../core/src/Bakery}/Bake.php | 4 +- .../core/src/Bakery}/ClearCache.php | 5 +- .../core/src/Bakery}/Debug.php | 10 +- .../core/src/Bakery/MigrateCommand.php | 112 ++++ .../core/src/Bakery/MigrateRefreshCommand.php | 79 +++ .../core/src/Bakery/MigrateResetCommand.php | 124 ++++ .../src/Bakery/MigrateRollbackCommand.php | 71 +++ .../core/src/Bakery/MigrateStatusCommand.php | 97 +++ .../core/src/Bakery}/Setup.php | 8 +- app/sprinkles/core/src/Database/Migration.php | 54 ++ .../Migrations/v400/SessionsTable.php | 2 +- .../Migrations/v400/ThrottlesTable.php | 2 +- .../Migrator/DatabaseMigrationRepository.php | 210 +++++++ .../Migrator/MigrationDependencyAnalyser.php | 215 +++++++ .../Database/Migrator/MigrationLocator.php | 127 ++++ .../Migrator/MigrationLocatorInterface.php | 33 + .../Migrator/MigrationRepositoryInterface.php | 97 +++ .../core/src/Database/Migrator/Migrator.php | 507 +++++++++++++++ .../src/ServicesProvider/ServicesProvider.php | 144 +++-- .../core/tests/DatabaseTransactions.php | 48 ++ .../Integration/BakeryMigrateCommandTest.php | 98 +++ .../BakeryMigrateRefreshCommandTest.php | 85 +++ .../BakeryMigrateResetCommandTest.php | 93 +++ .../BakeryMigrateRollbackCommandTest.php | 98 +++ .../BakeryMigrateStatusCommandTest.php | 94 +++ .../DatabaseMigratorIntegrationTest.php | 325 ++++++++++ .../DatabaseMigratorServiceTest.php | 23 + .../Integration/DatabaseMigratorTest.php | 323 ++++++++++ .../core/tests/Integration/DatabaseTests.php | 23 +- .../MigrationDependencyAnalyserTest.php | 81 +++ .../Integration/MigrationLocatorTest.php | 160 +++++ .../Integration/MigrationRepositoryTest.php | 136 ++++ .../Migrations/DeprecatedClassTable.php | 33 + .../Migrations/UnfulfillableTable.php | 42 ++ .../one/CreatePasswordResetsTable.php | 38 ++ .../Migrations/one/CreateUsersTable.php | 42 ++ .../Migrations/two/CreateFlightsTable.php | 40 ++ app/sprinkles/core/tests/RefreshDatabase.php | 105 ++++ app/sprinkles/core/tests/TestDatabase.php | 24 + .../tests/Unit/BelongsToManyThroughTest.php | 5 - .../core/tests/Unit/DatabaseSyncableTest.php | 15 +- app/sprinkles/core/tests/Unit/SprunjeTest.php | 6 +- .../core/tests/Unit/TestDatabaseTraitTest.php | 38 ++ app/system/Bakery/Bakery.php | 37 +- app/system/Bakery/BaseCommand.php | 30 +- app/system/Bakery/Command/BuildAssets.php | 19 +- app/system/Bakery/Command/Migrate.php | 48 -- app/system/Bakery/Command/MigrateRefresh.php | 52 -- app/system/Bakery/Command/MigrateReset.php | 49 -- app/system/Bakery/Command/MigrateRollback.php | 51 -- app/system/Bakery/ConfirmableTrait.php | 63 ++ app/system/Bakery/Migration.php | 51 +- app/system/Bakery/Migrator.php | 584 ------------------ .../Migrations/v410/MigrationTable.php | 59 -- app/system/Database/Model/Migrations.php | 55 -- app/tests/DatabaseTransactions.php | 4 +- app/tests/TestCase.php | 40 +- app/tests/Unit/ExampleTest.php | 1 - 78 files changed, 4062 insertions(+), 1204 deletions(-) rename app/{system/Bakery/Command => sprinkles/core/src/Bakery}/Bake.php (95%) rename app/{system/Bakery/Command => sprinkles/core/src/Bakery}/ClearCache.php (95%) rename app/{system/Bakery/Command => sprinkles/core/src/Bakery}/Debug.php (95%) create mode 100644 app/sprinkles/core/src/Bakery/MigrateCommand.php create mode 100644 app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php create mode 100644 app/sprinkles/core/src/Bakery/MigrateResetCommand.php create mode 100644 app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php create mode 100644 app/sprinkles/core/src/Bakery/MigrateStatusCommand.php rename app/{system/Bakery/Command => sprinkles/core/src/Bakery}/Setup.php (98%) create mode 100644 app/sprinkles/core/src/Database/Migration.php create mode 100644 app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php create mode 100644 app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php create mode 100644 app/sprinkles/core/src/Database/Migrator/MigrationLocator.php create mode 100644 app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php create mode 100644 app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php create mode 100644 app/sprinkles/core/src/Database/Migrator/Migrator.php create mode 100644 app/sprinkles/core/tests/DatabaseTransactions.php create mode 100644 app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php create mode 100644 app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php create mode 100644 app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php create mode 100644 app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php create mode 100644 app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php create mode 100644 app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php create mode 100644 app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php create mode 100644 app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php create mode 100644 app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php create mode 100644 app/sprinkles/core/tests/Integration/MigrationLocatorTest.php create mode 100644 app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php create mode 100644 app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php create mode 100644 app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php create mode 100644 app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php create mode 100644 app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php create mode 100644 app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php create mode 100644 app/sprinkles/core/tests/RefreshDatabase.php create mode 100644 app/sprinkles/core/tests/TestDatabase.php create mode 100644 app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php delete mode 100644 app/system/Bakery/Command/Migrate.php delete mode 100644 app/system/Bakery/Command/MigrateRefresh.php delete mode 100644 app/system/Bakery/Command/MigrateReset.php delete mode 100644 app/system/Bakery/Command/MigrateRollback.php create mode 100644 app/system/Bakery/ConfirmableTrait.php delete mode 100644 app/system/Bakery/Migrator.php delete mode 100644 app/system/Database/Migrations/v410/MigrationTable.php delete mode 100644 app/system/Database/Model/Migrations.php diff --git a/.gitignore b/.gitignore index 61266a064..50f3949e4 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ build/node_modules/* # Ignore generated bundle schema files build/bundle.config.json build/bundle.result.json +build/package-lock.json # Ignore temporary build assets build/temp diff --git a/CHANGELOG.md b/CHANGELOG.md index eedfe16e0..e6d7df879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,44 @@ # Change Log -## v4.2.0-alpha +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +### Added - Use locale requested by browser when possible for guests (#718) - Add locale drop down to registration page, with the currently applied locale selected (#718) - Integrated improvements from [v4.0.25-Alpha](#v4025-alpha) +- Added tests for migrator and it's components. +- Added tests for `migrate` Bakery command and sub-commands. +- Added `database` option for `migrate` and `migrate:*` Bakery commands +- New `isProduction` method for Bakery command to test if app is in production mode +- `migrate` and `migrate:*` Bakery command now require confirmation before execution when in production mode. +- Added `migrate:status` Bakery command +- Added `RefreshDatabase` test Trait to use a fresh database for a test +- Added `TestDatabase` test Trait to use the in memory database for a test + +### Changed +- Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle. +- Re-written Migrator. The migrator is now detached from the console and Bakery. The migrator is now included in the ServicesProvider and included in the `Core` sprinkle. (#795) +- Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace. + +### Deprecated +- Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration`. +- Migrations dependencies property should now be a static property. +- Trait `\UserFrosting\Tests\DatabaseTransactions` has been deprecated. Tests should now use the `\UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` trait instead. (#826) + +### Removed +- The console IO instance is not available anymore in migrations. +- Removed the `io` property from migration classes. +- Removed Bakery `projectRoot` property. Use the `\UserFrosting\ROOT_DIR` constant instead. +- Removed `preted` option from Bakery `migrate:refresh` and `migrate:reset` commands. + +### Fixed + +### Security ## v4.1.16-alpha - Fix for `merge` bundling rule (#660) @@ -38,7 +73,7 @@ - Change "remember me" text - Improve table tool buttons - Twig extensions now implement `Twig_Extension_GlobalsInterface` as required by https://twig.symfony.com/doc/2.x/advanced.html#id1 (#788) -- Display element based on permissions for group list/info pages +- Display element based on permissions for group list/info pages - Factor the admin user creation out of migrations and into its own Bakery command (See #778) - Bakery `clear-cache` command now clears Twig and router cache (Fix #750) - Add Russian translations @@ -379,7 +414,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x - Use Laravel's Schema interface to create tables and default rows, instead of constructing them with SQL ## v0.3.1.20 -- Added `pushAlert()`,`clearAlerts()` in `public/js/userfrosting.js` and updated `flashAlerts()` +- Added `pushAlert()`,`clearAlerts()` in `public/js/userfrosting.js` and updated `flashAlerts()` - Revert changes to User::fresh() but leave comment regarding upgrading Eloquent ## v0.3.1.19 @@ -506,7 +541,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x - [Theming](https://v3.userfrosting.com/components/#theming) - [Plugins](https://v3.userfrosting.com/components/#plugins) -## v0.2.1 +## v0.2.1 - Implemented db-driven menu system. Menu items are pulled from the database, and can be modified via plugins. - Implemented backend templating of forms and tables via [Bootsole](https://github.com/alexweissman/bootsole). @@ -543,7 +578,7 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x - Included better functions for sanitizing user input, validating user ip, generating csrf (cross-site request forgery) tokens - thanks to contributor @r3wt ## v0.1.3 -- Root account (user id = 1) : created upon installation, cannot be deleted or disabled. +- Root account (user id = 1) : created upon installation, cannot be deleted or disabled. - Special color scheme for when logged in as root user. - Installer now guides user through creation of root account - Moved common JS and CSS includes to "includes.php" diff --git a/app/sprinkles/account/composer.json b/app/sprinkles/account/composer.json index fa2e17865..6188d0aaa 100644 --- a/app/sprinkles/account/composer.json +++ b/app/sprinkles/account/composer.json @@ -20,5 +20,10 @@ "psr-4": { "UserFrosting\\Sprinkle\\Account\\": "src/" } + }, + "autoload-dev": { + "psr-4": { + "UserFrosting\\Sprinkle\\Account\\Tests\\": "tests/" + } } } diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index cfaacef0d..01125a4fa 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -7,14 +7,10 @@ */ namespace UserFrosting\Sprinkle\Account\Bakery; -use Illuminate\Database\Capsule\Manager as Capsule; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; use UserFrosting\System\Bakery\DatabaseTest; -use UserFrosting\System\Database\Model\Migrations; use UserFrosting\Sprinkle\Account\Database\Models\User; use UserFrosting\Sprinkle\Account\Database\Models\Role; use UserFrosting\Sprinkle\Account\Facades\Password; @@ -63,15 +59,26 @@ protected function execute(InputInterface $input, OutputInterface $output) exit(1); } + /** + * @var \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator; + */ + $migrator = $this->ci->migrator; + + /** + * @var \UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository; + */ + $repository = $migrator->getRepository(); + // Need migration table - if (!Capsule::schema()->hasColumn('migrations', 'id')) { - $this->io->error("Migrations doesn't appear to have been run! Make sure the database is properly migrated by using the `php bakery migrate` command."); - exit(1); + if (!$repository->repositoryExists()) { + $this->io->error("Migrations doesn't appear to have been run! Make sure the database is properly migrated by using the `php bakery migrate` command."); + exit(1); } - // Make sure the required mirgations have been run + // Make sure the required migrations have been run + $ranMigrations = $repository->getRan(); foreach ($this->dependencies as $migration) { - if (!Migrations::where('migration', $migration)->exists()) { + if (!in_array($migration, $ranMigrations)) { $this->io->error("Migration `$migration` doesn't appear to have been run! Make sure all migrations are up to date by using the `php bakery migrate` command."); exit(1); } @@ -80,11 +87,8 @@ protected function execute(InputInterface $input, OutputInterface $output) // Make sure that there are no users currently in the user table // We setup the root account here so it can be done independent of the version check if (User::count() > 0) { - $this->io->note("Table 'users' is not empty. Skipping root account setup. To set up the root account again, please truncate or drop the table and try again."); - } else { - $this->io->writeln("Please answer the following questions to create the root account:\n"); // Get the account details @@ -125,8 +129,7 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Ask for the username * - * @access protected - * @return void + * @return string */ protected function askUsername() { @@ -139,9 +142,8 @@ protected function askUsername() /** * Validate the username. * - * @access protected - * @param mixed $userName - * @return void + * @param string $userName + * @return bool */ protected function validateUsername($userName) { @@ -169,8 +171,7 @@ protected function validateUsername($userName) /** * Ask for the email * - * @access protected - * @return void + * @return string */ protected function askEmail() { @@ -183,9 +184,8 @@ protected function askEmail() /** * Validate the email. * - * @access protected - * @param mixed $email - * @return void + * @param string $email + * @return bool */ protected function validateEmail($email) { @@ -207,8 +207,7 @@ protected function validateEmail($email) /** * Ask for the first name * - * @access protected - * @return void + * @return string */ protected function askFirstName() { @@ -221,9 +220,8 @@ protected function askFirstName() /** * validateFirstName function. * - * @access protected - * @param mixed $name - * @return void + * @param string $firstName + * @return bool */ protected function validateFirstName($firstName) { @@ -239,8 +237,7 @@ protected function validateFirstName($firstName) /** * Ask for the last name * - * @access protected - * @return void + * @return string */ protected function askLastName() { @@ -253,9 +250,8 @@ protected function askLastName() /** * validateLastName function. * - * @access protected - * @param mixed $lastName - * @return void + * @param string $lastName + * @return bool */ protected function validateLastName($lastName) { @@ -271,8 +267,7 @@ protected function validateLastName($lastName) /** * Ask for the password * - * @access protected - * @return void + * @return string */ protected function askPassword() { @@ -285,9 +280,8 @@ protected function askPassword() /** * validatePassword function. * - * @access protected - * @param mixed $password - * @return void + * @param string $password + * @return bool */ protected function validatePassword($password) { @@ -302,9 +296,8 @@ protected function validatePassword($password) /** * confirmPassword function. * - * @access protected - * @param mixed $passwordToConfirm - * @return void + * @param string $passwordToConfirm + * @return bool */ protected function confirmPassword($passwordToConfirm) { @@ -317,10 +310,9 @@ protected function confirmPassword($passwordToConfirm) /** * validatePasswordConfirmation function. * - * @access protected - * @param mixed $password - * @param mixed $passwordToConfirm - * @return void + * @param string $password + * @param string $passwordToConfirm + * @return bool */ protected function validatePasswordConfirmation($password, $passwordToConfirm) { @@ -331,4 +323,4 @@ protected function validatePasswordConfirmation($password, $passwordToConfirm) return true; } -} \ No newline at end of file +} diff --git a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php index 4e55c7c22..dc075adc5 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php @@ -7,7 +7,7 @@ */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php index c74615f61..1a6dc6f96 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php @@ -10,7 +10,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Account\Database\Models\Group; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Groups table migration diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php index e785cccb5..7eb9fd7df 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * password_resets table migration diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php index 2c2990ca0..ee7f6c821 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Permission_roles table migration diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php index 684b01abf..2a6406fe4 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php @@ -8,10 +8,9 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Account\Database\Models\Permission; use UserFrosting\Sprinkle\Account\Database\Models\Role; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Permissions table migration @@ -20,7 +19,6 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class PermissionsTable extends Migration @@ -28,7 +26,7 @@ class PermissionsTable extends Migration /** * {@inheritDoc} */ - public $dependencies = [ + static public $dependencies = [ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable', '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\PermissionRolesTable' ]; @@ -52,21 +50,7 @@ public function up() $table->charset = 'utf8'; }); } - } - /** - * {@inheritDoc} - */ - public function down() - { - $this->schema->drop('permissions'); - } - - /** - * {@inheritDoc} - */ - public function seed() - { // Skip this if table is not empty if (Permission::count() == 0) { @@ -259,4 +243,12 @@ public function seed() } } } + + /** + * {@inheritDoc} + */ + public function down() + { + $this->schema->drop('permissions'); + } } diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php index b96e32733..d3b55af24 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Persistences table migration diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php index 7f3648b0e..51ced3dba 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Role_users table migration diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php index 9cef49415..28c55230c 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php @@ -10,7 +10,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Account\Database\Models\Role; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Roles table migration diff --git a/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php b/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php index a65eeedad..4b0626bbd 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Users table migration diff --git a/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php index fa54da6ea..bbed6e588 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Verifications table migration diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index 4c3ab1527..77b636ec0 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -347,14 +347,14 @@ public function register($container) * This method is invoked when a user attempts to perform certain public actions when they are already logged in. * * @todo Forward to user's landing page or last visited page - * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Message\ResponseInterface $response * @param array $args * @return \Psr\Http\Message\ResponseInterface */ return function (Request $request, Response $response, array $args) use ($c) { $redirect = $c->router->pathFor('dashboard'); - + return $response->withRedirect($redirect, 302); }; }; @@ -367,8 +367,8 @@ public function register($container) * This method is invoked when a user completes the login process. * * Returns a callback that handles setting the `UF-Redirect` header after a successful login. - * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Message\ResponseInterface $response * @param array $args * @return \Psr\Http\Message\ResponseInterface */ @@ -376,7 +376,7 @@ public function register($container) // Backwards compatibility for the deprecated determineRedirectOnLogin service if ($c->has('determineRedirectOnLogin')) { $determineRedirectOnLogin = $c->determineRedirectOnLogin; - + return $determineRedirectOnLogin($response)->withStatus(200); } diff --git a/app/sprinkles/account/tests/Unit/FactoriesTest.php b/app/sprinkles/account/tests/Unit/FactoriesTest.php index ee2bf23fb..10dfc6de9 100644 --- a/app/sprinkles/account/tests/Unit/FactoriesTest.php +++ b/app/sprinkles/account/tests/Unit/FactoriesTest.php @@ -5,21 +5,38 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Unit; +namespace UserFrosting\Sprinkle\Account\Tests\Unit; use UserFrosting\Tests\TestCase; -use UserFrosting\Tests\DatabaseTransactions; +use UserFrosting\Sprinkle\Core\Tests\TestDatabase; +use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; /** * FactoriesTest class. * Tests the factories defined in this sprinkle are working - * - * @extends TestCase */ class FactoriesTest extends TestCase { - use DatabaseTransactions; + use TestDatabase; + use RefreshDatabase; + + /** + * Setup TestDatabase + */ + public function setUp() + { + // Boot parent TestCase, which will set up the database and connections for us. + parent::setUp(); + + // Setup test database + $this->setupTestDatabase(); + $this->refreshDatabase(); + } + /** + * Test the user factory + * @return void + */ function testUserFactory() { $fm = $this->ci->factory; diff --git a/app/sprinkles/admin/composer.json b/app/sprinkles/admin/composer.json index 8ccd5c0a7..a326ee6a5 100644 --- a/app/sprinkles/admin/composer.json +++ b/app/sprinkles/admin/composer.json @@ -18,5 +18,10 @@ "psr-4": { "UserFrosting\\Sprinkle\\Admin\\": "src/" } + }, + "autoload-dev": { + "psr-4": { + "UserFrosting\\Sprinkle\\Admin\\Tests\\": "tests/" + } } } diff --git a/app/sprinkles/admin/tests/Integration/SprunjeTests.php b/app/sprinkles/admin/tests/Integration/SprunjeTests.php index 9eb412202..bbdf9cf15 100644 --- a/app/sprinkles/admin/tests/Integration/SprunjeTests.php +++ b/app/sprinkles/admin/tests/Integration/SprunjeTests.php @@ -2,21 +2,23 @@ namespace UserFrosting\Tests\Integration; -use Exception; -use Illuminate\Database\Capsule\Manager as DB; -use Symfony\Component\Console\Style\SymfonyStyle; use UserFrosting\Sprinkle\Admin\Sprunje\UserPermissionSprunje; use UserFrosting\Sprinkle\Core\Util\ClassMapper; -use UserFrosting\Tests\DatabaseTransactions; use UserFrosting\Tests\TestCase; +use UserFrosting\Sprinkle\Core\Tests\TestDatabase; +use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; /** * Integration tests for the built-in Sprunje classes. */ class SprunjeTests extends TestCase { - use DatabaseTransactions; + use TestDatabase; + use RefreshDatabase; + /** + * @var ClassMapper + */ protected $classMapper; /** @@ -29,6 +31,10 @@ public function setUp() parent::setUp(); $this->classMapper = new ClassMapper(); + + // Setup test database + $this->setupTestDatabase(); + $this->refreshDatabase(); } /** diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index 52d39c901..2c01b7093 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -53,5 +53,10 @@ "psr-4": { "UserFrosting\\Sprinkle\\Core\\": "src/" } + }, + "autoload-dev": { + "psr-4": { + "UserFrosting\\Sprinkle\\Core\\Tests\\": "tests/" + } } } diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 5349058dd..e533e7bb2 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -94,6 +94,9 @@ 'Timeout' => 15 ] ], + 'migrations' => [ + 'repository_table' => 'migrations' + ], // Filesystem paths 'path' => [ 'document_root' => str_replace(DIRECTORY_SEPARATOR, \UserFrosting\DS, $_SERVER['DOCUMENT_ROOT']), diff --git a/app/system/Bakery/Command/Bake.php b/app/sprinkles/core/src/Bakery/Bake.php similarity index 95% rename from app/system/Bakery/Command/Bake.php rename to app/sprinkles/core/src/Bakery/Bake.php index 5dc0e277f..9e89fbded 100644 --- a/app/system/Bakery/Command/Bake.php +++ b/app/sprinkles/core/src/Bakery/Bake.php @@ -5,7 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\System\Bakery\Command; +namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -27,7 +27,7 @@ class Bake extends BaseCommand protected $buildPath; /** - * @var String $ufArt The UserFrosting ASCII art. + * @var string $ufArt The UserFrosting ASCII art. */ public $title = " _ _ ______ _ _ diff --git a/app/system/Bakery/Command/ClearCache.php b/app/sprinkles/core/src/Bakery/ClearCache.php similarity index 95% rename from app/system/Bakery/Command/ClearCache.php rename to app/sprinkles/core/src/Bakery/ClearCache.php index d38f3823a..1ca1b809b 100644 --- a/app/system/Bakery/Command/ClearCache.php +++ b/app/sprinkles/core/src/Bakery/ClearCache.php @@ -5,7 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\System\Bakery\Command; +namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -62,7 +62,6 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Flush the cached data from the cache service * - * @access protected * @return void */ protected function clearIlluminateCache() @@ -73,7 +72,6 @@ protected function clearIlluminateCache() /** * Clear the Twig cache using the Twig CacheHelper class * - * @access protected * @return bool true/false if operation is successfull */ protected function clearTwigCache() @@ -85,7 +83,6 @@ protected function clearTwigCache() /** * Clear the Router cache data file * - * @access protected * @return bool true/false if operation is successfull */ protected function clearRouterCache() diff --git a/app/system/Bakery/Command/Debug.php b/app/sprinkles/core/src/Bakery/Debug.php similarity index 95% rename from app/system/Bakery/Command/Debug.php rename to app/sprinkles/core/src/Bakery/Debug.php index 4e8a3e45b..3c731d736 100644 --- a/app/system/Bakery/Command/Debug.php +++ b/app/sprinkles/core/src/Bakery/Debug.php @@ -5,7 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\System\Bakery\Command; +namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -42,7 +42,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->title("UserFrosting"); $this->io->writeln("UserFrosing version : " . \UserFrosting\VERSION); $this->io->writeln("OS Name : " . php_uname('s')); - $this->io->writeln("Project Root : {$this->projectRoot}"); + $this->io->writeln("Project Root : " . \UserFrosting\ROOT_DIR); // Need to touch the config service first to load dotenv values $config = $this->ci->config; @@ -64,7 +64,6 @@ protected function execute(InputInterface $input, OutputInterface $output) * Check the minimum version of php. * This is done by composer itself, but we do it again for good mesure * - * @access public * @return void */ protected function checkPhpVersion() @@ -79,7 +78,6 @@ protected function checkPhpVersion() /** * Check the minimum version requirement of Node installed * - * @access public * @return void */ protected function checkNodeVersion() @@ -96,7 +94,6 @@ protected function checkNodeVersion() /** * Check the minimum version requirement for Npm * - * @access public * @return void */ protected function checkNpmVersion() @@ -114,7 +111,6 @@ protected function checkNpmVersion() * List all sprinkles defined in the Sprinkles schema file, * making sure this file exist at the same time * - * @access protected * @return void */ protected function listSprinkles() @@ -142,7 +138,6 @@ protected function listSprinkles() * Check the database connexion and setup the `.env` file if we can't * connect and there's no one found. * - * @access protected * @return void */ protected function checkDatabase() @@ -163,7 +158,6 @@ protected function checkDatabase() /** * Display database config as for debug purposes * - * @access protected * @return void */ protected function showConfig() diff --git a/app/sprinkles/core/src/Bakery/MigrateCommand.php b/app/sprinkles/core/src/Bakery/MigrateCommand.php new file mode 100644 index 000000000..ffafbac3a --- /dev/null +++ b/app/sprinkles/core/src/Bakery/MigrateCommand.php @@ -0,0 +1,112 @@ +setName("migrate") + ->setDescription("Perform database migration") + ->setHelp("This command runs all the pending database migrations.") + ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') + ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') + ->addOption('step', 's', InputOption::VALUE_NONE, 'Migrations will be run so they can be rolled back individually.'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title("UserFrosting's Migrator"); + + // Get options + $pretend = $input->getOption('pretend'); + $step = $input->getOption('step'); + + // Get migrator + $migrator = $this->setupMigrator($input); + + // Run migration + try { + $migrated = $migrator->run(['pretend' => $pretend, 'step' => $step]); + } catch (\Exception $e) { + $this->io->writeln($migrator->getNotes()); + $this->io->error($e->getMessage()); + exit(1); + } + + // Get notes and display them + $this->io->writeln($migrator->getNotes()); + + // If all went well, there's no fatal errors and we have migrated + // something, show some success + if (empty($migrated)) { + $this->io->success("Nothing to migrate"); + } else { + $this->io->success("Migration successful !"); + } + } + + /** + * Setup migrator and the shared options between other command + * + * @param InputInterface $input + * @return \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator The migrator instance + */ + protected function setupMigrator(InputInterface $input) + { + // Confirm action when in production mode + if (!$this->confirmToProceed($input->getOption('force'))) { + exit(1); + } + + /** @var \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator */ + $migrator = $this->ci->migrator; + + // Set connection to the selected database + $database = $input->getOption('database'); + if ($database != "") { + $this->io->note("Running {$this->getName()} with `$database` database connection"); + $this->ci->db->getDatabaseManager()->setDefaultConnection($database); + } + + // Make sure repository exist. Should be done in ServicesProvider, + // but if we change connection, it might not exist + if (!$migrator->repositoryExists()) { + $migrator->getRepository()->createRepository(); + } + + // Show note if pretending + if ($input->hasOption('pretend') && $input->getOption('pretend')) { + $this->io->note("Running {$this->getName()} in pretend mode"); + } + + return $migrator; + } +} diff --git a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php new file mode 100644 index 000000000..b82f99ba5 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php @@ -0,0 +1,79 @@ +setName("migrate:refresh") + ->setDescription("Rollback the last migration operation and run it up again") + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') + ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') + ->addOption('steps', 's', InputOption::VALUE_REQUIRED, 'Number of batch to rollback', 1); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title("Migration refresh"); + + // Get options + $steps = $input->getOption('steps'); + + // Get migrator + $migrator = $this->setupMigrator($input); + + // Rollback migration + try { + $rolledback = $migrator->rollback(['pretend' => false, 'steps' => $steps]); + } catch (\Exception $e) { + $this->io->writeln($migrator->getNotes()); + $this->io->error($e->getMessage()); + exit(1); + } + + // Get notes and display them + $this->io->writeln($migrator->getNotes()); + + // Stop if nothing was rolledback + if (empty($rolledback)) { + $this->io->success("Nothing to refresh"); + return; + } + + // Run back up again + $migrated = $migrator->run(['pretend' => false, 'step' => false]); + $this->io->writeln($migrator->getNotes()); + + // If all went well, there's no fatal errors and we have migrated + // something, show some success + if (empty($migrated)) { + $this->io->success("Nothing to refresh"); + } else { + $this->io->success("Refresh successful !"); + } + } +} diff --git a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php new file mode 100644 index 000000000..bfff71ae9 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php @@ -0,0 +1,124 @@ +setName("migrate:reset") + ->setDescription("Reset the whole database to an empty state, rolling back all migrations.") + ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') + ->addOption('hard', null, InputOption::VALUE_NONE, 'Force drop all tables in the database, even if they were not created or listed by the migrator') + ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title("Migration reset"); + + // Check if the hard option is used + if ($input->getOption('hard')) { + $this->performHardReset($input); + } else { + $this->performReset($input); + } + } + + /** + * Reset the whole database to an empty state by rolling back all migrations + * + * @param InputInterface $input + */ + protected function performReset(InputInterface $input) + { + // Get options + $pretend = $input->getOption('pretend'); + + // Get migrator + $migrator = $this->setupMigrator($input); + + // Reset migrator + try { + $resetted = $migrator->reset($pretend); + } catch (\Exception $e) { + $this->io->writeln($migrator->getNotes()); + $this->io->error($e->getMessage()); + exit(1); + } + + // Get notes and display them + $this->io->writeln($migrator->getNotes()); + + // Delete the repository + if (!$pretend && $migrator->repositoryExists()) { + $this->io->writeln("Deleting migration repository"); + $migrator->getRepository()->deleteRepository(); + } + + // If all went well, there's no fatal errors and we have migrated + // something, show some success + if (empty($resetted)) { + $this->io->success("Nothing to reset"); + } else { + $this->io->success("Reset successful !"); + } + } + + /** + * Hard reset the whole database to an empty state by dropping all tables + * + * @param InputInterface $input + */ + protected function performHardReset(InputInterface $input) + { + // Get current connection + $database = ($input->getOption('database')) ?: $this->ci->db->getDatabaseManager()->getDefaultConnection(); + + // Confirm action + $this->io->warning("This will drop all existing tables from the `$database` database, including tables not managed by bakery. All data will be lost! You have been warned!"); + if (!$this->io->confirm('Do you really wish to run this command?', false)) { + $this->io->comment('Command Cancelled!'); + exit(1); + } + + // Get shema Builder + $connection = $this->ci->db->connection($database); + $schema = $connection->getSchemaBuilder(); + + // Get a list of all tables + $tables = $connection->select('SHOW TABLES'); + foreach (array_map('reset', $tables) as $table) { + $this->io->writeln("Dropping table `$table`..."); + + // Perform drop + $schema->drop($table); + } + + $this->io->success("Hard reset successful !"); + } +} diff --git a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php new file mode 100644 index 000000000..8c85737fd --- /dev/null +++ b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php @@ -0,0 +1,71 @@ +setName("migrate:rollback") + ->setDescription("Rollback last database migration") + ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') + ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') + ->addOption('steps', 's', InputOption::VALUE_REQUIRED, 'Number of batch to rollback.', 1); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title("Migration rollback"); + + // Get options + $steps = $input->getOption('steps'); + $pretend = $input->getOption('pretend'); + + // Get migrator + $migrator = $this->setupMigrator($input); + + // Rollback migrations + try { + $migrated = $migrator->rollback(['pretend' => $pretend, 'steps' => $steps]); + } catch (\Exception $e) { + $this->io->writeln($migrator->getNotes()); + $this->io->error($e->getMessage()); + exit(1); + } + + // Get notes and display them + $this->io->writeln($migrator->getNotes()); + + // If all went well, there's no fatal errors and we have migrated + // something, show some success + if (empty($migrated)) { + $this->io->success("Nothing to rollback"); + } else { + $this->io->success("Rollback successful !"); + } + } +} diff --git a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php new file mode 100644 index 000000000..8718c8711 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php @@ -0,0 +1,97 @@ +setName("migrate:status") + ->setDescription("Show the list of installed and pending migration.") + ->setHelp("Show the list of installed and pending migration. This command also show if an installed migration is available in the Filesystem, so it can be run down by the rollback command") + ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title("Migration status"); + + // Get migrator + $migrator = $this->ci->migrator; + + // Set connection to the selected database + $migrator->setConnection($input->getOption('database')); + + // Get ran migrations. If repository doesn't exist, there's no ran + if (!$migrator->repositoryExists()) { + $ran = []; + } else { + $ran = $migrator->getRepository()->getRan(); + } + + // Get available migrations and calculate pending one + $available = $migrator->getAvailableMigrations(); + $pending = $migrator->pendingMigrations($available, $ran); + + // Display ran migrations + $this->io->section("Installed migrations"); + if (count($ran) > 0) { + $this->io->table( + ['Migration', 'Available?'], + $this->getStatusFor($ran, $available) + ); + } else { + $this->io->note("No installed migrations"); + } + + // Display pending migrations + $this->io->section("Pending migrations"); + if (count($pending) > 0) { + $this->io->listing($pending); + } else { + $this->io->note("No pending migrations"); + } + } + + /** + * Return an array of [migration, available] association. + * A migration is available if it's in the available stack (class is in the Filesystem) + * + * @param array $ran The ran migrations + * @param array $available The available migrations + * @return array An array of [migration, available] association + */ + protected function getStatusFor(array $ran, array $available) + { + return collect($ran)->map(function ($migration) use ($available) { + if (in_array($migration, $available)) { + return [$migration, 'Y']; + } else { + return [$migration, 'N']; + } + })->toArray(); + } +} diff --git a/app/system/Bakery/Command/Setup.php b/app/sprinkles/core/src/Bakery/Setup.php similarity index 98% rename from app/system/Bakery/Command/Setup.php rename to app/sprinkles/core/src/Bakery/Setup.php index b489ce26a..142b89c41 100644 --- a/app/system/Bakery/Command/Setup.php +++ b/app/sprinkles/core/src/Bakery/Setup.php @@ -5,7 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\System\Bakery\Command; +namespace UserFrosting\Sprinkle\Core\Bakery; use Illuminate\Database\Capsule\Manager as Capsule; use Symfony\Component\Console\Input\InputInterface; @@ -23,7 +23,7 @@ class Setup extends BaseCommand { /** - * envfile path + * @var string Path to the .env file */ protected $envPath = \UserFrosting\APP_DIR. '/.env'; @@ -72,7 +72,6 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Setup the `.env` file. * - * @access public * @return void */ public function setupEnv() @@ -112,7 +111,7 @@ public function setupEnv() // Use custom validator to accept empty password return $password; }); - + $dbParams = [ 'driver' => $driverName, 'host' => $host, @@ -188,7 +187,6 @@ public function setupEnv() /** * Return the database choices for the env setup. * - * @access protected * @return void */ protected function databaseDrivers() diff --git a/app/sprinkles/core/src/Database/Migration.php b/app/sprinkles/core/src/Database/Migration.php new file mode 100644 index 000000000..c990284f6 --- /dev/null +++ b/app/sprinkles/core/src/Database/Migration.php @@ -0,0 +1,54 @@ +schema = $schema; + } + + /** + * Method to apply changes to the database + */ + public function up() {} + + /** + * Method to revert changes applied by the `up` method + */ + public function down() {} +} diff --git a/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php b/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php index ac86ceb21..dae95ce53 100644 --- a/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php +++ b/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Sessions table migration diff --git a/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php b/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php index 1c742f746..e5af704fb 100644 --- a/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php +++ b/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php @@ -9,7 +9,7 @@ use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Schema\Builder; -use UserFrosting\System\Bakery\Migration; +use UserFrosting\Sprinkle\Core\Database\Migration; /** * Throttles table migration diff --git a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php new file mode 100644 index 000000000..fbce88977 --- /dev/null +++ b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php @@ -0,0 +1,210 @@ +table = $table; + $this->db = $db; + } + + /** + * Get the ran migrations. + * + * @return array An array of migration class names in the order they where ran + */ + public function getRan() + { + return $this->table() + ->orderBy('id', 'asc') + ->pluck('migration')->all(); + } + + /** + * Get list of migrations. + * + * @param int $steps Number of batch to return + * @return array + */ + public function getMigrations($steps) + { + $batch = max($this->getNextBatchNumber() - $steps, 1); + return $this->table()->where('batch', '>=', $batch)->orderBy('id', 'desc')->get()->pluck('migration')->all(); + } + + /** + * Get the last migration batch in reserve order they were ran (last one first) + * + * @return array + */ + public function getLast() + { + $query = $this->table()->where('batch', $this->getLastBatchNumber()); + + return $query->orderBy('id', 'desc')->get()->pluck('migration')->all(); + } + + /** + * Log that a migration was run. + * + * @param string $file + * @param int $batch + * @param string $sprinkle + * @return void + */ + public function log($file, $batch, $sprinkle = "") + { + $record = ['migration' => $file, 'batch' => $batch, 'sprinkle' => $sprinkle]; + + $this->table()->insert($record); + } + + /** + * Remove a migration from the log. + * + * @param string $migration + * @return void + */ + public function delete($migration) + { + $this->table()->where('migration', $migration)->delete(); + } + + /** + * Get the next migration batch number. + * + * @return int + */ + public function getNextBatchNumber() + { + return $this->getLastBatchNumber() + 1; + } + + /** + * Get the last migration batch number. + * + * @return int + */ + public function getLastBatchNumber() + { + return $this->table()->max('batch'); + } + + /** + * Create the migration repository data store. + * + * @return void + */ + public function createRepository() + { + $this->getSchemaBuilder()->create($this->table, function (Blueprint $table) { + // The migrations table is responsible for keeping track of which of the + // migrations have actually run for the application. We'll create the + // table to hold the migration file's path as well as the batch ID. + $table->increments('id'); + $table->string('sprinkle'); + $table->string('migration'); + $table->integer('batch'); + }); + } + + /** + * Delete the migration repository data store + * + * @return void + */ + public function deleteRepository() + { + $this->getSchemaBuilder()->drop($this->table); + } + + /** + * Determine if the migration repository exists. + * + * @return bool + */ + public function repositoryExists() + { + return $this->getSchemaBuilder()->hasTable($this->table); + } + + /** + * Get a query builder for the migration table. + * + * @return \Illuminate\Database\Query\Builder + */ + protected function table() + { + return $this->getConnection()->table($this->table); + } + + /** + * Returns the schema builder instance + * + * @return \Illuminate\Database\Schema\Builder + */ + public function getSchemaBuilder() + { + return $this->getConnection()->getSchemaBuilder(); + } + + /** + * Resolve the database connection instance. + * + * @return \Illuminate\Database\Connection + */ + public function getConnection() + { + return $this->db->getConnection($this->connection); + } + + /** + * Set the information source to gather data. + * + * @param string $name The source name + */ + public function setSource($name) + { + $this->connection = $name; + } +} diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php new file mode 100644 index 000000000..230bc15fa --- /dev/null +++ b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php @@ -0,0 +1,215 @@ +pending = collect($pending); + $this->installed = collect($installed); + } + + /** + * Analyse the dependencies + * + * @return void + */ + public function analyse() + { + // Reset fulfillable/unfulfillable lists + $this->analysed = false; + $this->fulfillable = collect([]); + $this->unfulfillable = collect([]); + + // Loop pending and check for dependencies + foreach ($this->pending as $migration) { + $this->validateClassDependencies($migration); + } + + $this->analysed = true; + } + + /** + * Validate if a migration is fulfillable. + * N.B.: The key element here is the recursion while validating the + * dependencies. This is very important as the order the migrations needs + * to be run is defined by this recursion. By waiting for the dependency + * to be marked as fulfillable to mark the parent as fulfillable, the + * parent class will be automatocally placed after it's dependencies + * in the `fullfillable` property. + * + * @param string $migrationName The migration classname + * @return bool True/False if the migration is fulfillable + */ + protected function validateClassDependencies($migrationName) + { + // Get migration dependencies + $dependencies = $this->getMigrationDependencies($migrationName); + + // If it's already marked as fulfillable, it's fulfillable + // Return true directly (it's already marked) + if ($this->fulfillable->contains($migrationName)) { + return true; + } + + // If it's already marked as unfulfillable, it's unfulfillable + // Return false directly (it's already marked) + if ($this->unfulfillable->contains($migrationName)) { + return false; + } + + // If it's already run, it's fulfillable + // Mark it as such for next time it comes up in this point + if ($this->installed->contains($migrationName)) { + return $this->markAsFulfillable($migrationName); + } + + // Loop dependencies. If one is not fulfillable, then this migration is not either + foreach ($dependencies as $dependency) { + + // The dependency might already be installed. Check that first + if ($this->installed->contains($dependency)) { + continue; + } + + // Check is the dependency is pending installation. If so, check for it's dependencies. + // If the dependency is not fullfillable, then this one isn't either + if (!$this->pending->contains($dependency) || !$this->validateClassDependencies($dependency)) { + return $this->markAsUnfulfillable($migrationName); + } + } + + // If no dependencies returned false, it's fulfillable + return $this->markAsFulfillable($migrationName); + } + + /** + * Return the fulfillable list. Analyse the stack if not done already + * + * @return array + */ + public function getFulfillable() + { + if (!$this->analysed) { + $this->analyse(); + } + + return $this->fulfillable->toArray(); + } + + /** + * Return the fulfillable list. Analyse the stack if not done already + * + * @return array + */ + public function getUnfulfillable() + { + if (!$this->analysed) { + $this->analyse(); + } + + return $this->unfulfillable->toArray(); + } + + /** + * Mark a dependency as fulfillable. Removes it from the pending list and add it to the fulfillable list + * + * @param string $migration The migration classname + * @return bool True, it's fulfillable + */ + protected function markAsFulfillable($migration) + { + $this->fulfillable->push($migration); + return true; + } + + /** + * Mark a dependency as unfulfillable. Removes it from the pending list and add it to the unfulfillable list + * + * @param string $migration The migration classname + * @return bool False, it's not fullfillable + */ + protected function markAsUnfulfillable($migration) + { + $this->unfulfillable->push($migration); + return false; + } + + /** + * Returns the migration dependency list + * Also handles the old deprecated behaviour where dependencies where not in a static property + * + * @param string $migration The migration class + * @return array The dependency list + */ + protected function getMigrationDependencies($migration) { + + // Make sure class exists + if (!class_exists($migration)) { + throw new BadClassNameException("Unable to find the migration class '$migration'." ); + } + + // If the `dependencies` property exist and is static, use this one. + // Otherwise, get a class instance and the non static property + $reflectionClass = new ReflectionClass($migration); + if ($reflectionClass->hasProperty('dependencies') && $reflectionClass->getProperty('dependencies')->isStatic()) { + return $migration::$dependencies; + } else if (property_exists($migration, 'dependencies')) { + Debug::debug("`$migration` uses a non static `dependencies` property. Please change the `dependencies` property to a static property."); + $instance = new $migration(); + return $instance->dependencies; + } else { + return []; + } + } +} diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php new file mode 100644 index 000000000..dd724a5ce --- /dev/null +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php @@ -0,0 +1,127 @@ +sprinkleManager = $sprinkleManager; + $this->files = $files; + } + + /** + * Returm a list of all available migration available for a specific sprinkle + * + * @param string $sprinkleName The sprinkle name + * @return array The list of available migration classes + */ + public function getMigrationsForSprinkle($sprinkleName) + { + // Get the sprinkle migration path and get all files in that path recursively + $path = $this->migrationDirectoryPath($sprinkleName); + + // If directory diesn't exist, stop + if (!$this->files->exists($path)) { + return []; + } + + // Get files + $files = $this->files->allFiles($path); + + // Transform the path into the mgiration full class name + $migrations = collect($files)->transform(function ($file) use ($sprinkleName, $path) { + return $this->getMigrationClassName($file, $path, $sprinkleName); + }); + + // Return as array + return $migrations->all(); + } + + /** + * Loop all the available sprinkles and return a list of their migrations + * + * @return array A list of all the migration files found for every sprinkle + */ + public function getMigrations() + { + $migrationsFiles = []; + foreach ($this->sprinkleManager->getSprinkleNames() as $sprinkle) { + $migrationsFiles = array_merge($this->getMigrationsForSprinkle($sprinkle), $migrationsFiles); + } + + return $migrationsFiles; + } + + /** + * Returns the path of the Migration directory. + * + * @param string $sprinkleName + * @return string The sprinkle Migration dir path + */ + protected function migrationDirectoryPath($sprinkleName) + { + return \UserFrosting\SPRINKLES_DIR . + \UserFrosting\DS . + $sprinkleName . + \UserFrosting\DS . + \UserFrosting\SRC_DIR_NAME . + "/Database/Migrations"; + } + + /** + * Get the full classname of a migration based on the absolute file path, + * the initial search path and the SprinkleName + * + * @param string $file The migration file absolute path + * @param string $path The initial search path + * @param string $sprinkleName The sprinkle name + * @return string The migration class name + */ + protected function getMigrationClassName($file, $path, $sprinkleName) + { + // Format the sprinkle name for the namespace + $sprinkleName = Str::studly($sprinkleName); + + // Extract the class name from the path and file + $relativePath = str_replace($path, '', $file); + $className = str_replace('.php', '', $relativePath); + $className = str_replace('/', '\\', $className); + + // Build the class name and namespace + return "\\UserFrosting\\Sprinkle\\".$sprinkleName."\\Database\\Migrations" . $className; + } +} diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php new file mode 100644 index 000000000..b98ba0925 --- /dev/null +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php @@ -0,0 +1,33 @@ +db = $db; + $this->repository = $repository; + $this->locator = $locator; + } + + /** + * Run all the specified migrations up. Check that dependencies are met before running + * + * @param array $options Options for the current operations [step, pretend] + * @return array The list of ran migrations + */ + public function run(array $options = []) + { + $this->notes = []; + + // Get the list of available migration classes in the the Filesystem + $availableMigrations = $this->getAvailableMigrations(); + + // Get ran migrations + $ranMigrations = $this->repository->getRan(); + + // Get outstanding migrations classes that requires to be run up + $pendingMigrations = $this->pendingMigrations($availableMigrations, $ranMigrations); + + // First we will just make sure that there are any migrations to run. If there + // aren't, we will just make a note of it to the developer so they're aware + // that all of the migrations have been run against this database system. + if (count($pendingMigrations) == 0) { + return []; + } + + // Next we need to validate that all pending migration dependencies are met or WILL BE MET + // This operation is important as it's the one that place the outstanding migrations + // in the correct order, making sure a migration script won't fail because the table + // it depends on has not been created yet (for example). + $analyser = new Analyser($pendingMigrations, $ranMigrations); + + // Any migration without a fulfilled dependency will cause this script to throw an exception + if ($unfulfillable = $analyser->getUnfulfillable()) { + $unfulfillableList = implode(", ", $unfulfillable); + throw new \Exception("Unfulfillable migrations found :: $unfulfillableList"); + } + + // Run pending migration up + return $this->runPending($analyser->getFulfillable(), $options); + } + + /** + * Get the migration classes that have not yet run. + * + * @param array $available The available migrations returned by the migration locator + * @param array $ran The list of already ran migrations returned by the migration repository + * @return array The list of pending migrations, ie the available migrations not ran yet + */ + public function pendingMigrations($available, $ran) + { + return collect($available)->reject(function ($migration) use ($ran) { + return collect($ran)->contains($migration); + })->values()->all(); + } + + /** + * Run an array of migrations. + * + * @param array $migrations An array of migrations classes names to be run (unsorted, unvalidated) + * @param array $options The options for the current operation [step, pretend] + * @return void + */ + protected function runPending(array $migrations, array $options = []) + { + // Next, we will get the next batch number for the migrations so we can insert + // correct batch number in the database migrations repository when we store + // each migration's execution. + $batch = $this->repository->getNextBatchNumber(); + + // We extract a few of the options. + $pretend = Arr::get($options, 'pretend', false); + $step = Arr::get($options, 'step', 0); + + // We now have an ordered array of migrations, we will spin through them and run the + // migrations "up" so the changes are made to the databases. We'll then log + // that the migration was run so we don't repeat it next time we execute. + foreach ($migrations as $migrationClass) { + $this->runUp($migrationClass, $batch, $pretend); + + if ($step) { + $batch++; + } + } + + return $migrations; + } + + /** + * Run "up" a migration class + * + * @param string $migrationClass The migration class name + * @param int $batch The current bacth number + * @param bool $pretend If this operation should be pretended / faked + * @return void + */ + protected function runUp($migrationClass, $batch, $pretend) + { + // First we will resolve a "real" instance of the migration class from + // the class name. Once we have the instances we can run the actual + // command such as "up" or "down", or we can just simulate the action. + $migration = $this->resolve($migrationClass); + + // Move into pretend mode if requested + if ($pretend) { + return $this->pretendToRun($migration, 'up'); + } + + // Run the actuall migration + $this->runMigration($migration, 'up'); + + // Once we have run a migrations class, we will log that it was run in this + // repository so that we don't try to run it next time we do a migration + // in the application. A migration repository keeps the migrate order. + $this->repository->log($migrationClass, $batch); + + $this->note("Migrated: {$migrationClass}"); + } + + /** + * Rollback the last migration operation. + * + * @param array $options The options for the current operation [steps, pretend] + * @return array The list of rolledback migration classes + */ + public function rollback(array $options = []) + { + $this->notes = []; + + // We want to pull in the last batch of migrations that ran on the previous + // migration operation. We'll then reverse those migrations and run each + // of them "down" to reverse the last migration "operation" which ran. + $migrations = $this->getMigrationsForRollback($options); + + if (count($migrations) === 0) { + return []; + } else { + return $this->rollbackMigrations($migrations, $options); + } + } + + /** + * Get the migrations for a rollback operation. + * + * @param array $options The options for the current operation + * @return array An ordered array of migrations to rollback + */ + protected function getMigrationsForRollback(array $options) + { + $steps = Arr::get($options, 'steps', 0); + if ($steps > 0) { + return $this->repository->getMigrations($steps); + } else { + return $this->repository->getLast(); + } + } + + /** + * Rollback the given migrations. + * + * @param array $migrations An array of migrations to rollback formated as an eloquent collection + * @param array $options The options for the current operation + * @return array The list of rolledback migration classes + */ + protected function rollbackMigrations(array $migrations, array $options) + { + $rolledBack = []; + + // Get the available migration classes in the filesystem + $availableMigrations = collect($this->getAvailableMigrations()); + + // Next we will run through all of the migrations and call the "down" method + // which will reverse each migration in order. This getLast method on the + // repository already returns these migration's classenames in reverse order. + foreach ($migrations as $migration) { + + // We have to make sure the class exist first + if (!$availableMigrations->contains($migration)) { + //throw new \Exception("Can't rollback migrations `$migration`. The migration class doesn't exist"); + continue; + } + + // Add the migration to the list of rolledback migration + $rolledBack[] = $migration; + + // Extract some options + $pretend = Arr::get($options, 'pretend', false); + + // Run the migration down + $this->runDown($migration, $pretend); + } + + return $rolledBack; + } + + /** + * Rolls all of the currently applied migrations back. + * + * @param bool $pretend Should this operation be pretended + * @return array An array of all the rolledback migration classes + */ + public function reset($pretend = false) + { + $this->notes = []; + + // We get the list of all the migrations class available and reverse + // said list so we can run them back in the correct order for resetting + // this database. This will allow us to get the database back into its + // "empty" state and ready to be migrated "up" again. + // + // !TODO :: Should compare to the install list to make sure no outstanding migration (ran, but with no migraiton class anymore) still exist in the db + $migrations = array_reverse($this->repository->getRan()); + + if (count($migrations) === 0) { + return []; + } else { + return $this->rollbackMigrations($migrations, compact('pretend')); + } + } + + /** + * Run "down" a migration instance. + * + * @param string $migrationClass The migration class name + * @param bool $pretend Is the operation should be pretended + * @return void + */ + protected function runDown($migrationClass, $pretend) + { + // We resolve an instance of the migration. Once we get an instance we can either run a + // pretend execution of the migration or we can run the real migration. + $instance = $this->resolve($migrationClass); + + if ($pretend) { + return $this->pretendToRun($instance, 'down'); + } + + $this->runMigration($instance, 'down'); + + // Once we have successfully run the migration "down" we will remove it from + // the migration repository so it will be considered to have not been run + // by the application then will be able to fire by any later operation. + $this->repository->delete($migrationClass); + + $this->note("Rolled back: {$migrationClass}"); + } + + /** + * Run a migration inside a transaction if the database supports it. + * Note : As of Laravel 5.4, only PostgresGrammar supports it + * + * @param object $migration The migration instance + * @param string $method The method used [up, down] + * @return void + */ + protected function runMigration($migration, $method) + { + $callback = function () use ($migration, $method) { + if (method_exists($migration, $method)) { + $migration->{$method}(); + } + }; + + if ($this->getSchemaGrammar()->supportsSchemaTransactions()) { + $this->getConnection()->transaction($callback); + } else { + $callback(); + } + + } + + /** + * Pretend to run the migrations. + * + * @param object $migration The migration instance + * @param string $method The method used [up, down] + * @return void + */ + protected function pretendToRun($migration, $method) + { + $name = get_class($migration); + $this->note("\n$name"); + + foreach ($this->getQueries($migration, $method) as $query) { + $this->note("> {$query['query']}"); + } + } + + /** + * Get all of the queries that would be run for a migration. + * + * @param object $migration The migration instance + * @param string $method The method used [up, down] + * @return array The queries executed by the processed schema + */ + protected function getQueries($migration, $method) + { + // Get the connection instance + $connection = $this->getConnection(); + + return $connection->pretend(function () use ($migration, $method) { + if (method_exists($migration, $method)) { + $migration->{$method}(); + } + }); + } + + /** + * Resolve a migration instance from it's class name. + * + * @param string $migrationClass The class name + * @return object The migration class instance + */ + public function resolve($migrationClass) + { + if (!class_exists($migrationClass)) { + throw new BadClassNameException("Unable to find the migration class '$migrationClass'." ); + } + + return new $migrationClass($this->getSchemaBuilder()); + } + + /** + * Get all of the migration files in a given path. + * + * @return array The list of migration classes found in the filesystem + */ + public function getAvailableMigrations() + { + return $this->locator->getMigrations(); + } + + /** + * Get the migration repository instance. + * + * @return \Illuminate\Database\Migrations\MigrationRepositoryInterface + */ + public function getRepository() + { + return $this->repository; + } + + /** + * Set the migration repository instance + * + * @param MigrationRepositoryInterface $repository + */ + public function setRepository(MigrationRepositoryInterface $repository) + { + $this->repository = $repository; + } + + /** + * Determine if the migration repository exists. + * + * @return bool If the repository exist + */ + public function repositoryExists() + { + return $this->repository->repositoryExists(); + } + + /** + * Get the migration locator instance. + * + * @return MigrationLocatorInterface + */ + public function getLocator() + { + return $this->locator; + } + + /** + * Set the migration locator instance + * + * @param MigrationLocatorInterface $locator + */ + public function setLocator(MigrationLocatorInterface $locator) + { + $this->locator = $locator; + } + + /** + * Get the schema builder. + * + * @return \Illuminate\Database\Schema\Builder + */ + public function getSchemaBuilder() + { + return $this->getConnection()->getSchemaBuilder(); + } + + /** + * Return the connection instance + * + * @return \Illuminate\Database\Connection + */ + public function getConnection() + { + return $this->db->getConnection($this->connection); + } + + /** + * Define which connection to use + * + * @param string $name The connection name + */ + public function setConnection($name) + { + $this->repository->setSource($name); + $this->connection = $name; + } + + /** + * Get instance of Grammar + * @return \Illuminate\Database\Schema\Grammars\Grammar + */ + protected function getSchemaGrammar() + { + return $this->getConnection()->getSchemaGrammar(); + } + + /** + * Raise a note event for the migrator. + * + * @param string $message The message + * @return void + */ + protected function note($message) + { + $this->notes[] = $message; + } + + /** + * Get the notes for the last operation. + * + * @return array An array of notes + */ + public function getNotes() + { + return $this->notes; + } +} diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 42dc3fbf1..cdbcffe8c 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -20,14 +20,12 @@ use League\FactoryMuffin\FactoryMuffin; use League\FactoryMuffin\Faker\Facade as Faker; use Monolog\Formatter\LineFormatter; -use Monolog\Handler\ErrorLogHandler; use Monolog\Handler\StreamHandler; use Monolog\Logger; use Slim\Csrf\Guard; use Slim\Http\Uri; use Slim\Views\Twig; use Slim\Views\TwigExtension; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use UserFrosting\Assets\AssetBundleSchema; use UserFrosting\Cache\TaggableFileStore; use UserFrosting\Cache\MemcachedStore; @@ -46,6 +44,9 @@ use UserFrosting\Sprinkle\Core\Mail\Mailer; use UserFrosting\Sprinkle\Core\Alert\CacheAlertStream; use UserFrosting\Sprinkle\Core\Alert\SessionAlertStream; +use UserFrosting\Sprinkle\Core\Database\Migrator\Migrator; +use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocator; +use UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository; use UserFrosting\Sprinkle\Core\Router; use UserFrosting\Sprinkle\Core\Throttle\Throttler; use UserFrosting\Sprinkle\Core\Throttle\ThrottleRule; @@ -92,17 +93,18 @@ public function register(ContainerInterface $container) /** * Asset loader service - * + * + + * + * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. * Loads assets from a specified relative location. * Assets are Javascript, CSS, image, and other files used by your site. - * - * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. */ $container['assetLoader'] = function ($c) { $basePath = \UserFrosting\SPRINKLES_DIR; - $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; - return new AssetLoader($basePath, $pattern); + $al = new AssetLoader($basePath, $pattern); + return $al; }; /** @@ -111,10 +113,7 @@ public function register(ContainerInterface $container) * Loads raw or compiled asset information from your bundle.config.json schema file. * Assets are Javascript, CSS, image, and other files used by your site. */ - $container['assets'] = function ($c) { - $config = $c->config; - $locator = $c->locator; - + // Hacky way to clean up locator paths. $locatorPaths = []; foreach ($locator->getPaths('assets') as $pathSet) { @@ -122,24 +121,20 @@ public function register(ContainerInterface $container) $locatorPaths[] = $path; } } + $container['assets'] = function ($c) { + $config = $c->config; + $locator = $c->locator; - // Load asset schema - if ($config['assets.use_raw']) { - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; - - $sprinkles = $c->sprinkleManager->getSprinkleNames(); + $sprinkles = $c->sprinkleManager->getSprinkleNames(); $prefixTransformer = new PrefixTransformer(); $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); - foreach ($sprinkles as $sprinkle) { $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); } $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); - // Load raw asset bundles for each Sprinkle. - // Retrieve locations of raw asset bundle schemas that exist. $bundleSchemas = $locator->findResources('sprinkles://' . $config['assets.raw.schema']); @@ -149,21 +144,28 @@ public function register(ContainerInterface $container) foreach ($bundleSchemas as $bundleSchema) { $bundles->extend($bundleSchema); - } // Add bundles to asset manager. $assets->addAssetBundles($bundles); - } - } else { - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; + // TODO: move this out into PathBuilder and Loader classes in userfrosting/assets + // This would also allow us to define and load bundles in themes + $bundleSchemas = array_reverse($locator->findResources('sprinkles://' . $config['assets.raw.schema'], true, true)); $assets = new Assets($locator, 'assets', $baseUrl); $assets->overrideBasePath($locator->getBase() . '/public/assets'); - // Load compiled asset bundle. $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); + $as->loadRawSchemaFile($schema); + return $assets; + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; + $aub = new CompiledAssetUrlBuilder($baseUrl); + + $as = new AssetBundleSchema($aub); + $as->loadCompiledSchemaFile($locator->findResource("build://" . $config['assets.compiled.schema'], true, true)); } - return $assets; + $am = new AssetManager($aub, $as); + + return $am; }; /** @@ -225,21 +227,27 @@ public function register(ContainerInterface $container) } catch (InvalidPathException $e) { // Skip loading the environment config file if it doesn't exist. } + $uri = $c->request->getUri(); - // Get configuration mode from environment - $mode = getenv('UF_MODE') ?: ''; + $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); + if (!isset($config['site.uri.public'])) { + $base_uri = $config['site.uri.base']; - // Construct and load config repository - $builder = new ConfigPathBuilder($c->locator, 'config://'); - $loader = new ArrayFileLoader($builder->buildPaths($mode)); - $config = new Repository($loader->load()); + $public = new Uri( + $base_uri['scheme'], + $base_uri['host'], + $base_uri['port'], + $base_uri['path'] + ); - // Construct base url from components, if not explicitly specified - if (!isset($config['site.uri.public'])) { - $uri = $c->request->getUri(); + // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) + if (!$config['assets.use_raw']) { + $c->locator->resetScheme('assets'); + $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); + } // Slim\Http\Uri likes to add trailing slashes when the path is empty, so this fixes that. - $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); + $config['site.uri.public'] = trim($public, '/'); } // Hacky fix to prevent sessions from being hit too much: ignore CSRF middleware for requests for raw assets ;-) @@ -251,12 +259,6 @@ public function register(ContainerInterface $container) $config->set('csrf.blacklist', $csrfBlacklist); - // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) - if (!$config['assets.use_raw']) { - $c->locator->resetScheme('assets'); - $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); - } - return $config; }; @@ -407,28 +409,14 @@ public function register(ContainerInterface $container) $fm = new FactoryMuffin(); // Load all of the model definitions + $request = $c->request; $fm->loadFactories($factoriesPath); // Set the locale. Could be the config one, but for testing English should do Faker::setLocale('en_EN'); return $fm; - }; - - /** - * Builds search paths for locales in all Sprinkles. - */ - $container['localePathBuilder'] = function ($c) { - $config = $c->config; - $request = $c->request; - - // Make sure the locale config is a valid string - if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { - throw new \UnexpectedValueException('The locale config is not a valid string.'); - } - // Get default locales as specified in configurations. - $locales = explode(',', $config['site.locales.default']); // Add supported browser preferred locales. if ($request->hasHeader('Accept-Language')) { @@ -456,15 +444,29 @@ public function register(ContainerInterface $container) } } } - + // Sort, extract keys, and merge with $locales asort($allowedLocales, SORT_NUMERIC); $locales = array_merge($locales, array_keys($allowedLocales)); - + // Remove duplicates, while maintaining fallback order $locales = array_reverse(array_unique(array_reverse($locales), SORT_STRING)); } + /** + * Builds search paths for locales in all Sprinkles. + */ + $container['localePathBuilder'] = function ($c) { + $config = $c->config; + + // Make sure the locale config is a valid string + if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { + throw new \UnexpectedValueException('The locale config is not a valid string.'); + } + + // Load the base locale file(s) as specified in the configuration + $locales = explode(',', $config['site.locales.default']); + return new LocalePathBuilder($c->locator, 'locale://', $locales); }; @@ -502,6 +504,26 @@ public function register(ContainerInterface $container) return $log; }; + /** + * Migrator service. + * + * This service handles database migration operations + */ + $container['migrator'] = function ($c) { + $migrator = new Migrator( + $c->db, + new DatabaseMigrationRepository($c->db, $c->config['migrations.repository_table']), + new MigrationLocator($c->sprinkleManager, new Filesystem) + ); + + // Make sure repository exist + if (!$migrator->repositoryExists()) { + $migrator->getRepository()->createRepository(); + } + + return $migrator; + }; + /** * Error-handler for 404 errors. Notice that we manually create a UserFrosting NotFoundException, * and a NotFoundExceptionHandler. This lets us pass through to the UF error handling system. @@ -548,7 +570,9 @@ public function register(ContainerInterface $container) $container['router'] = function ($c) { $routerCacheFile = false; if (isset($c->config['settings.routerCacheFile'])) { - $routerCacheFile = $c->config['settings.routerCacheFile']; + $fs = new Filesystem; + + } return (new Router)->setCacheFile($routerCacheFile); @@ -562,7 +586,7 @@ public function register(ContainerInterface $container) // Create appropriate handler based on config if ($config['session.handler'] == 'file') { - $fs = new FileSystem; + $fs = new Filesystem; $handler = new FileSessionHandler($fs, $c->locator->findResource('session://'), $config['session.minutes']); } elseif ($config['session.handler'] == 'database') { $connection = $c->db->connection(); diff --git a/app/sprinkles/core/tests/DatabaseTransactions.php b/app/sprinkles/core/tests/DatabaseTransactions.php new file mode 100644 index 000000000..82676f133 --- /dev/null +++ b/app/sprinkles/core/tests/DatabaseTransactions.php @@ -0,0 +1,48 @@ +ci->db; + + foreach ($this->connectionsToTransact() as $name) { + $database->connection($name)->beginTransaction(); + } + + $this->beforeApplicationDestroyed(function () use ($database) { + foreach ($this->connectionsToTransact() as $name) { + $database->connection($name)->rollBack(); + } + }); + } + + /** + * The database connections that should have transactions. + * + * @return array + */ + protected function connectionsToTransact() + { + return property_exists($this, 'connectionsToTransact') + ? $this->connectionsToTransact : [null]; + } +} diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php new file mode 100644 index 000000000..735098da7 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php @@ -0,0 +1,98 @@ +shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => false])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testMigrationRepositoryCreatedWhenNecessary() + { + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $repository = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository'); + + $migrator->shouldReceive('repositoryExists')->once()->andReturn(false); + $migrator->shouldReceive('getRepository')->once()->andReturn($repository); + $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => false])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + $repository->shouldReceive('createRepository')->once(); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testTheCommandMayBePretended() + { + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('run')->once()->with(['pretend' => true, 'step' => false])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, ['--pretend' => true]); + } + + public function testStepMayBeSet() + { + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => true])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, ['--step' => true]); + } + + protected function runCommand($migrator, $input = []) + { + // Place the mock migrator inside the $ci + $ci = $this->ci; + $ci->migrator = $migrator; + + // Create the app, create the command, replace $ci and add the command to the app + $app = new Application(); + $command = new MigrateCommand(); + $command->setContainer($ci); + $app->add($command); + + // Add the command to the input to create the execute argument + $execute = array_merge([ + 'command' => $command->getName() + ], $input); + + // Execute command tester + $commandTester = new CommandTester($command); + $commandTester->execute($execute); + + return $commandTester; + } +} diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php new file mode 100644 index 000000000..f496de7f5 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php @@ -0,0 +1,85 @@ +shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 1])->andReturn(['foo']); + $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => false])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testBasicCallWithNotthingToRollback() + { + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 1])->andReturn([]); + $migrator->shouldNotReceive('run'); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testStepsMayBeSet() + { + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 3])->andReturn(['foo']); + $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => false])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, ['--steps' => 3]); + } + + protected function runCommand($migrator, $input = []) + { + // Place the mock migrator inside the $ci + $ci = $this->ci; + $ci->migrator = $migrator; + + // Create the app, create the command, replace $ci and add the command to the app + $app = new Application(); + $command = new MigrateRefreshCommand(); + $command->setContainer($ci); + $app->add($command); + + // Add the command to the input to create the execute argument + $execute = array_merge([ + 'command' => $command->getName() + ], $input); + + // Execute command tester + $commandTester = new CommandTester($command); + $commandTester->execute($execute); + + return $commandTester; + } +} diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php new file mode 100644 index 000000000..7a37965d1 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php @@ -0,0 +1,93 @@ +shouldReceive('deleteRepository')->andReturn(null); + + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->twice()->andReturn(true); + $migrator->shouldReceive('reset')->once()->with(false)->andReturn(['foo']); + $migrator->shouldReceive('getNotes'); + $migrator->shouldReceive('getRepository')->once()->andReturn($repository); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testBasicCallWithNotthingToRollback() + { + // Setup repository mock + $repository = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository'); + $repository->shouldReceive('deleteRepository')->andReturn(null); + + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->twice()->andReturn(true); + $migrator->shouldReceive('reset')->once()->with(false)->andReturn([]); + $migrator->shouldReceive('getNotes'); + $migrator->shouldReceive('getRepository')->once()->andReturn($repository); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testTheCommandMayBePretended() + { + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('reset')->once()->with(true)->andReturn(['foo']); + $migrator->shouldReceive('getNotes'); + $migrator->shouldNotReceive('getRepository'); + + // Run command + $commandTester = $this->runCommand($migrator, ['--pretend' => true]); + } + + protected function runCommand($migrator, $input = []) + { + // Place the mock migrator inside the $ci + $ci = $this->ci; + $ci->migrator = $migrator; + + // Create the app, create the command, replace $ci and add the command to the app + $app = new Application(); + $command = new MigrateResetCommand(); + $command->setContainer($ci); + $app->add($command); + + // Add the command to the input to create the execute argument + $execute = array_merge([ + 'command' => $command->getName() + ], $input); + + // Execute command tester + $commandTester = new CommandTester($command); + $commandTester->execute($execute); + + return $commandTester; + } +} diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php new file mode 100644 index 000000000..af0ee7f6d --- /dev/null +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php @@ -0,0 +1,98 @@ +shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 1])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testMigrationRepositoryCreatedWhenNecessary() + { + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $repository = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository'); + + $migrator->shouldReceive('repositoryExists')->once()->andReturn(false); + $migrator->shouldReceive('getRepository')->once()->andReturn($repository); + $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 1])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + $repository->shouldReceive('createRepository')->once(); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testTheCommandMayBePretended() + { + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('rollback')->once()->with(['pretend' => true, 'steps' => 1])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, ['--pretend' => true]); + } + + public function testStepsMayBeSet() + { + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 3])->andReturn([]); + $migrator->shouldReceive('getNotes'); + + // Run command + $commandTester = $this->runCommand($migrator, ['--steps' => 3]); + } + + protected function runCommand($migrator, $input = []) + { + // Place the mock migrator inside the $ci + $ci = $this->ci; + $ci->migrator = $migrator; + + // Create the app, create the command, replace $ci and add the command to the app + $app = new Application(); + $command = new MigrateRollbackCommand(); + $command->setContainer($ci); + $app->add($command); + + // Add the command to the input to create the execute argument + $execute = array_merge([ + 'command' => $command->getName() + ], $input); + + // Execute command tester + $commandTester = new CommandTester($command); + $commandTester->execute($execute); + + return $commandTester; + } +} diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php new file mode 100644 index 000000000..95f1a6e24 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php @@ -0,0 +1,94 @@ +shouldReceive('setConnection')->once()->with(null)->andReturn(null); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRepository')->once()->andReturn($repository); + $migrator->shouldReceive('getAvailableMigrations')->once()->andReturn($available); + $migrator->shouldReceive('pendingMigrations')->once()->with($available, $installed)->andReturn($pending); + + $repository->shouldReceive('getRan')->once()->andReturn($installed); + + // Run command + $commandTester = $this->runCommand($migrator, []); + } + + public function testDatabaseMayBeSet() + { + // Setup migrator mock + $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); + $repository = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository'); + + // Define dummy data + $available = ['foo', 'bar', 'oof', 'rab']; + $installed = ['foo', 'bar']; + $pending = ['oof', 'rab']; + + // Set expectations + $migrator->shouldReceive('setConnection')->once()->with('test')->andReturn(null); + $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRepository')->once()->andReturn($repository); + $migrator->shouldReceive('getAvailableMigrations')->once()->andReturn($available); + $migrator->shouldReceive('pendingMigrations')->once()->with($available, $installed)->andReturn($pending); + + $repository->shouldReceive('getRan')->once()->andReturn($installed); + + // Run command + $commandTester = $this->runCommand($migrator, ['--database' => 'test']); + } + + protected function runCommand($migrator, $input = []) + { + // Place the mock migrator inside the $ci + $ci = $this->ci; + $ci->migrator = $migrator; + + // Create the app, create the command, replace $ci and add the command to the app + $app = new Application(); + $command = new MigrateStatusCommand(); + $command->setContainer($ci); + $app->add($command); + + // Add the command to the input to create the execute argument + $execute = array_merge([ + 'command' => $command->getName() + ], $input); + + // Execute command tester + $commandTester = new CommandTester($command); + $commandTester->execute($execute); + + return $commandTester; + } +} diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php new file mode 100644 index 000000000..f37e5e516 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php @@ -0,0 +1,325 @@ +repository = new DatabaseMigrationRepository($this->ci->db, $this->migrationTable); + $this->locator = new MigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + + // Get the migrator instance and setup right connection + $this->migrator = new Migrator($this->ci->db, $this->repository, $this->locator); + $this->migrator->setConnection($this->connection); + + // Get schema Builder + $this->schema = $this->migrator->getSchemaBuilder(); + + if (!$this->repository->repositoryExists()) { + $this->repository->createRepository(); + } + } + + public function testMigrationRepositoryCreated() + { + $this->assertTrue($this->schema->hasTable($this->migrationTable)); + } + + public function testBasicMigration() + { + $ran = $this->migrator->run(); + + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + + $this->assertEquals($this->locator->getMigrations(), $ran); + } + + public function testRepository() + { + $ran = $this->migrator->run(); + + // Theses assertions makes sure the repository and the migration returns the same format + // N.B.: getLast return the migrations in reverse order (last ran first) + $this->assertEquals($this->locator->getMigrations(), $ran); + $this->assertEquals(array_reverse($this->locator->getMigrations()), $this->repository->getLast()); + $this->assertEquals($this->locator->getMigrations(), $this->repository->getRan()); + } + + public function testMigrationsCanBeRolledBack() + { + // Run up + $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + + $rolledBack = $this->migrator->rollback(); + $this->assertFalse($this->schema->hasTable('users')); + $this->assertFalse($this->schema->hasTable('password_resets')); + + // Make sure the data returned from migrator is accurate. + // N.B.: The order returned by the rollback method is ordered by which + // migration was rollbacked first (reversed from the order they where ran up) + $this->assertEquals(array_reverse($this->locator->getMigrations()), $rolledBack); + } + + public function testMigrationsCanBeReset() + { + // Run up + $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + + $rolledBack = $this->migrator->reset(); + $this->assertFalse($this->schema->hasTable('users')); + $this->assertFalse($this->schema->hasTable('password_resets')); + + // Make sure the data returned from migrator is accurate. + $this->assertEquals(array_reverse($this->locator->getMigrations()), $rolledBack); + } + + public function testNoErrorIsThrownWhenNoOutstandingMigrationsExist() + { + $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + $this->migrator->run(); + } + + public function testNoErrorIsThrownWhenNothingToRollback() + { + $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + $this->migrator->rollback(); + $this->assertFalse($this->schema->hasTable('users')); + $this->assertFalse($this->schema->hasTable('password_resets')); + $this->migrator->rollback(); + } + + public function testPretendUp() + { + $result = $this->migrator->run(['pretend' => true]); + $notes = $this->migrator->getNotes(); + $this->assertFalse($this->schema->hasTable('users')); + $this->assertFalse($this->schema->hasTable('password_resets')); + $this->assertNotEquals([], $notes); + } + + public function testPretendRollback() + { + // Run up as usual + $result = $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + + $rolledBack = $this->migrator->rollback(['pretend' => true]); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + $this->assertEquals(array_reverse($this->locator->getMigrations()), $rolledBack); + } + + public function testChangeRepositoryAndDeprecatedClass() + { + // Change the repository so we can test with the DeprecatedMigrationLocatorStub + $locator = new DeprecatedMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $this->migrator->setLocator($locator); + + // Run up + $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('deprecated_table')); + + // Rollback + $this->migrator->rollback(); + $this->assertFalse($this->schema->hasTable('deprecated_table')); + } + + public function testWithInvalidClass() + { + // Change the repository so we can test with the InvalidMigrationLocatorStub + $locator = new InvalidMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $this->migrator->setLocator($locator); + + // Expect a `BadClassNameException` exception + $this->expectException(BadClassNameException::class); + + // Run up + $this->migrator->run(); + } + + public function testDependableMigrations() + { + // Change the repository so we can test with the DependableMigrationLocatorStub + $locator = new DependableMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $this->migrator->setLocator($locator); + + // Run up + $migrated = $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + $this->assertTrue($this->schema->hasTable('flights')); + + // Note here the `two` migration has been placed at the bottom even if + // it was supposed to be migrated first from the order the locator + // returned them. This is because `two` migration depends on `one` migrations + // We only check the last one, we don't care about the order the first two are since they are not dependendent on eachother + $this->assertEquals('\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable', $migrated[2]); + } + + public function testDependableMigrationsWithInstalled() + { + // Run the `one` migrations + $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + + // Change the repository so we can run up the `two` migrations + $locator = new FlightsTableMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $this->migrator->setLocator($locator); + + // Run up again + $migrated = $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('flights')); + + // Only the `CreateFlightsTable` migration should be ran + $this->assertEquals([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ], $migrated); + } + + public function testUnfulfillableMigrations() + { + // Change the repository so we can test with the DeprecatedStub + $locator = new UnfulfillableMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $this->migrator->setLocator($locator); + + // Should have an exception for unfulfilled migrations + $this->expectException(\Exception::class); + $migrated = $this->migrator->run(); + } +} + +class MigrationLocatorStub extends MigrationLocator { + public function getMigrations() + { + return [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' + ]; + } +} + +class FlightsTableMigrationLocatorStub extends MigrationLocator { + public function getMigrations() + { + return [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ]; + } +} + +/** + * This stub contain migration which file doesn't exists + */ +class InvalidMigrationLocatorStub extends MigrationLocator { + public function getMigrations() + { + return [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\Foo' + ]; + } +} + +/** + * This stub contain migration which order they need to be run is different + * than the order the file are returned because of dependencies management. + * The `two` migration should be run last since it depends on the other two + */ +class DependableMigrationLocatorStub extends MigrationLocator { + public function getMigrations() + { + return [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' + ]; + } +} + +/** + * This stub contain migration which order they need to be run is different + * than the order the file are returned because of dependencies management + */ +class UnfulfillableMigrationLocatorStub extends MigrationLocator { + public function getMigrations() + { + return [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\UnfulfillableTable' + ]; + } +} + +/** + * This stub contain migration which order they need to be run is different + * than the order the file are returned because of dependencies management + */ +class DeprecatedMigrationLocatorStub extends MigrationLocator { + public function getMigrations() + { + return [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\DeprecatedClassTable' + ]; + } +} diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php new file mode 100644 index 000000000..e6d5a5ca7 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php @@ -0,0 +1,23 @@ +assertInstanceOf('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator', $this->ci->migrator); + } +} diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php new file mode 100644 index 000000000..cae4cb2d5 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php @@ -0,0 +1,323 @@ +schema = m::mock(Builder::class); + $this->repository = m::mock(DatabaseMigrationRepository::class); + $this->locator = m::mock(MigrationLocator::class); + $capsule = m::mock(Capsule::class); + $this->connection = m::mock(Connection::class); + + // Set global expections for $capule and $connection + $capsule->shouldReceive('getConnection')->andReturn($this->connection); + $this->connection->shouldReceive('getSchemaBuilder')->andReturn($this->schema); + + // Setup the migrator instance + $this->migrator = new Migrator($capsule, $this->repository, $this->locator); + } + + /** + * Basic test to make sure the base method syntaxt is ok + */ + public function testMigratorUpWithNoMigrations() + { + // Locator will be asked to return the avaialble migrations + $this->locator->shouldReceive('getMigrations')->once()->andReturn([]); + + // Repository will be asked to return the ran migrations + $this->repository->shouldReceive('getRan')->once()->andReturn([]); + + $migrations = $this->migrator->run(); + $this->assertEmpty($migrations); + } + + /** + * Basic test where all avaialble migrations are pending and fulfillable + */ + public function testMigratorUpWithOnlyPendingMigrations() + { + // The migrations set + $testMigrations = [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ]; + + // When running up, Locator will return all 3 migration classes + $this->locator->shouldReceive('getMigrations')->andReturn($testMigrations); + + // Repository will be asked to return the ran migrations, the next batch number and will log 3 new migrations + $this->repository->shouldReceive('getRan')->andReturn([]); + $this->repository->shouldReceive('getNextBatchNumber')->andReturn(1); + $this->repository->shouldReceive('log')->times(3)->andReturn(null); + + // SchemaBuilder will create all 3 tables + $this->schema->shouldReceive('create')->times(3)->andReturn(null); + + // Connection will be asked for the SchemaGrammar + $grammar = m::mock(Grammar::class); + $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); + $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); + + // Run migrations up + $migrations = $this->migrator->run(); + + // All classes should have been migrated + $this->assertEquals($testMigrations, $migrations); + } + + /** + * Test where one of the avaialble migrations is already installed + */ + public function testMigratorUpWithOneInstalledMigrations() + { + // When running up, Locator will return all 3 migration classes + $this->locator->shouldReceive('getMigrations')->andReturn([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ]); + + // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations + $this->repository->shouldReceive('getRan')->andReturn([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable' + ]); + $this->repository->shouldReceive('getNextBatchNumber')->andReturn(2); + $this->repository->shouldReceive('log')->times(2)->andReturn(null); + + // SchemaBuilder will only create 2 tables + $this->schema->shouldReceive('create')->times(2)->andReturn(null); + + // Connection will be asked for the SchemaGrammar + $grammar = m::mock(Grammar::class); + $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); + $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); + + // Run migrations up + $migrations = $this->migrator->run(); + + // The migration already ran shoudn't be in the pending ones + $this->assertEquals([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ], $migrations); + } + + /** + * Test where all avaialble migrations have been ran + */ + public function testMigratorUpWithNoPendingMigrations() + { + // The migrations set + $testMigrations = [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ]; + + // When running up, Locator will return all 3 migration classes + $this->locator->shouldReceive('getMigrations')->andReturn($testMigrations); + + // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations + $this->repository->shouldReceive('getRan')->andReturn($testMigrations); + $this->repository->shouldNotReceive('getNextBatchNumber'); + $this->repository->shouldNotReceive('log'); + + // SchemaBuilder will only create 2 tables + $this->schema->shouldNotReceive('create'); + + // Run migrations up + $migrations = $this->migrator->run(); + + // The migration already ran shoudn't be in the pending ones + $this->assertEquals([], $migrations); + } + + /** + * Test where one of the available migrations is missing a dependency + */ + //!TODO + + /** + * Test rolling back where no migrations have been ran + */ + public function testMigratorRollbackWithNoInstalledMigrations() + { + // Repository will be asked to return the last batch of ran migrations + $this->repository->shouldReceive('getLast')->andReturn([]); + + // Run migrations up + $migrations = $this->migrator->rollback(); + + // The migration already ran shoudn't be in the pending ones + $this->assertEquals([], $migrations); + } + + /** + * Test rolling back all installed migrations + */ + public function testMigratorRollbackAllInstalledMigrations() + { + // The migrations set + $testMigrations = [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ]; + + // When running up, Locator will return all 3 migration classes + $this->locator->shouldReceive('getMigrations')->once()->andReturn($testMigrations); + + // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations + $this->repository->shouldReceive('getLast')->once()->andReturn($testMigrations); + $this->repository->shouldReceive('delete')->times(3)->andReturn([]); + + // SchemaBuilder will only create 2 tables + $this->schema->shouldReceive('dropIfExists')->times(3)->andReturn([]); + + // Connection will be asked for the SchemaGrammar + $grammar = m::mock(Grammar::class); + $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); + $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); + + // Run migrations up + $migrations = $this->migrator->rollback(); + + // The migration already ran shoudn't be in the pending ones + $this->assertEquals($testMigrations, $migrations); + } + + /** + * Test where one of the installed migration is not in the available migration classes + */ + public function testMigratorRollbackAllInstalledMigrationsWithOneMissing() + { + // When running up, Locator will return all 3 migration classes + $this->locator->shouldReceive('getMigrations')->once()->andReturn([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' + ]); + + // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations + $this->repository->shouldReceive('getLast')->once()->andReturn([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' + ]); + $this->repository->shouldReceive('delete')->times(1)->andReturn([]); + + // SchemaBuilder will only create 2 tables + $this->schema->shouldReceive('dropIfExists')->times(1)->andReturn([]); + + // Connection will be asked for the SchemaGrammar + $grammar = m::mock(Grammar::class); + $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); + $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); + + // Run migrations up + $migrations = $this->migrator->rollback(); + + // The migration already ran shoudn't be in the pending ones + $this->assertEquals([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' + ], $migrations); + } + + /** + * Test where one of the installed migration is not in the available migration classes + */ + public function testMigratorResetAllInstalledMigrations() + { + // The migrations set + $testMigrations = [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ]; + + // When running up, Locator will return all 3 migration classes + $this->locator->shouldReceive('getMigrations')->once()->andReturn($testMigrations); + + // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations + $this->repository->shouldReceive('getRan')->once()->andReturn($testMigrations); + $this->repository->shouldReceive('delete')->times(3)->andReturn([]); + + // SchemaBuilder will only create 2 tables + $this->schema->shouldReceive('dropIfExists')->times(3)->andReturn([]); + + // Connection will be asked for the SchemaGrammar + $grammar = m::mock(Grammar::class); + $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); + $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); + + // Run migrations up + $migrations = $this->migrator->reset(); + + // The migration already ran shoudn't be in the pending ones + $this->assertEquals(array_reverse($testMigrations), $migrations); + } +} diff --git a/app/sprinkles/core/tests/Integration/DatabaseTests.php b/app/sprinkles/core/tests/Integration/DatabaseTests.php index 231bb8664..c841d0788 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseTests.php +++ b/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -2,15 +2,10 @@ namespace UserFrosting\Tests\Integration; -use Exception; - use UserFrosting\Tests\TestCase; -use Illuminate\Database\Eloquent\SoftDeletes; -use Illuminate\Database\Capsule\Manager as DB; - -use UserFrosting\Sprinkle\Core\Database\Models\Model; - use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Database\Schema\Blueprint; +use UserFrosting\Sprinkle\Core\Database\Models\Model; class DatabaseTests extends TestCase { @@ -34,13 +29,13 @@ public function setUp() protected function createSchema() { - $this->schema($this->schemaName)->create('users', function ($table) { + $this->schema($this->schemaName)->create('users', function (Blueprint $table) { $table->increments('id'); $table->string('name')->nullable(); }); // Users have multiple email addresses - $this->schema($this->schemaName)->create('emails', function ($table) { + $this->schema($this->schemaName)->create('emails', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id'); $table->string('label'); @@ -48,7 +43,7 @@ protected function createSchema() }); // Users have multiple phones (polymorphic - other entities can have phones as well) - $this->schema($this->schemaName)->create('phones', function ($table) { + $this->schema($this->schemaName)->create('phones', function (Blueprint $table) { $table->increments('id'); $table->string('label'); $table->string('number', 20); @@ -56,18 +51,18 @@ protected function createSchema() }); // Users have multiple roles... (m:m) - $this->schema($this->schemaName)->create('role_users', function ($table) { + $this->schema($this->schemaName)->create('role_users', function (Blueprint $table) { $table->integer('user_id')->unsigned(); $table->integer('role_id')->unsigned(); }); - $this->schema($this->schemaName)->create('roles', function ($table) { + $this->schema($this->schemaName)->create('roles', function (Blueprint $table) { $table->increments('id'); $table->string('slug'); }); // And Roles have multiple permissions... (m:m) - $this->schema($this->schemaName)->create('permission_roles', function ($table) { + $this->schema($this->schemaName)->create('permission_roles', function (Blueprint $table) { $table->integer('permission_id')->unsigned(); $table->integer('role_id')->unsigned(); }); @@ -815,6 +810,7 @@ public function testQueryExcludeWildcard() /** * Get a database connection instance. * + * @param string $connection [description] * @return \Illuminate\Database\Connection */ protected function connection($connection = 'test_integration') @@ -825,6 +821,7 @@ protected function connection($connection = 'test_integration') /** * Get a schema builder instance. * + * @param string $connection * @return \Illuminate\Database\Schema\Builder */ protected function schema($connection = 'test_integration') diff --git a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php new file mode 100644 index 000000000..03f8bf7af --- /dev/null +++ b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php @@ -0,0 +1,81 @@ +assertEquals($migrations, $analyser->getFulfillable()); + $this->assertEquals([], $analyser->getUnfulfillable()); + } + + public function testAnalyserWithInvalidClass() + { + $migrations = [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\Foo' + ]; + + $analyser = new MigrationDependencyAnalyser($migrations, []); + + $this->expectException(BadClassNameException::class); + $analyser->analyse(); + } + + public function testAnalyserWithReordered() + { + $analyser = new MigrationDependencyAnalyser([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' + ], []); + + $this->assertEquals([], $analyser->getUnfulfillable()); + $this->assertEquals([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ], $analyser->getFulfillable()); + } + + public function testAnalyserWithUnfulfillable() + { + $migrations = [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\UnfulfillableTable' + ]; + + $analyser = new MigrationDependencyAnalyser($migrations, []); + + $this->assertEquals([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' + ], $analyser->getFulfillable()); + + $this->assertEquals([ + '\\UserFrosting\\Tests\\Integration\\Migrations\\UnfulfillableTable' + ], $analyser->getUnfulfillable()); + } +} diff --git a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php new file mode 100644 index 000000000..fc61ee729 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php @@ -0,0 +1,160 @@ +shouldReceive('getSprinkleNames')->once()->andReturn([ + 'core', + 'Account' + ]); + + // Simulate the Filesystem. + $filesystem = m::mock('Illuminate\Filesystem\Filesystem'); + + // When `MigrationLocator` will ask the filesystem for `glob` and `core` sprinkle, + // filesystem will return fake test path. + $filesystem->shouldReceive('exists')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->andReturn(true); + $filesystem->shouldReceive('allFiles')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->once()->andReturn([ + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/one/CreateUsersTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/one/CreatePasswordResetsTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/two/CreateFlightsTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/CreateMainTable.php') + ]); + + // When `MigrationLocator` will also ask the filesystem the same thing, but for the `account` sprinkle + $filesystem->shouldReceive('exists')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/Account/src/Database/Migrations")->andReturn(true); + $filesystem->shouldReceive('allFiles')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/Account/src/Database/Migrations")->once()->andReturn([ + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/Account/src/Database/Migrations/one/CreateUsersTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/Account/src/Database/Migrations/one/CreatePasswordResetsTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/Account/src/Database/Migrations/two/CreateFlightsTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/Account/src/Database/Migrations/CreateMainTable.php') + ]); + + // Create a new MigrationLocator instance with our simulated SprinkleManager and filesystem + // and ask to find core sprinkle migration files + $locator = new MigrationLocator($sprinkleManager, $filesystem); + $results = $locator->getMigrations(); + + // The `getMigrationForSprinkle` method should return this + $expected = [ + "\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\one\\CreateUsersTable", + "\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\one\\CreatePasswordResetsTable", + "\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\two\\CreateFlightsTable", + "\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\CreateMainTable", + "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreateUsersTable", + "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreatePasswordResetsTable", + "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\two\\CreateFlightsTable", + "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\CreateMainTable" + ]; + + // Test results match expectations + $this->assertEquals($expected, $results); + } + + /** + * Make sure migrations can be returned for a specific sprinkle + */ + public function testGetMigrationsForSprinkle() + { + // Simulate the SprinkleManager + $sprinkleManager = m::mock('UserFrosting\System\Sprinkle\SprinkleManager'); + + // Simulate the Filesystem. + $filesystem = m::mock('Illuminate\Filesystem\Filesystem'); + + // When `MigrationLocator` will ask the filesystem for `glob`, which it should do only once, + // filesystem will return fake test path. + $filesystem->shouldReceive('exists')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->andReturn(true); + $filesystem->shouldReceive('allFiles')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->once()->andReturn([ + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/one/CreateUsersTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/one/CreatePasswordResetsTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/two/CreateFlightsTable.php'), + new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/CreateMainTable.php') + ]); + + // Create a new MigrationLocator instance with our simulated SprinkleManager and filesystem + // and ask to find core sprinkle migration files + $locator = new MigrationLocator($sprinkleManager, $filesystem); + $results = $locator->getMigrationsForSprinkle('core'); + + // The `getMigrationForSprinkle` method should return this + $expected = [ + "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreateUsersTable", + "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreatePasswordResetsTable", + "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\two\\CreateFlightsTable", + "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\CreateMainTable" + ]; + + // Test results match expectations + $this->assertEquals($expected, $results); + } + + /** + * Make sure no error is thrown if the Migration dir doesn't exist + */ + public function testGetMigrationsForSprinkleWithNoMigrationDir() + { + // Simulate the SprinkleManager + $sprinkleManager = m::mock('UserFrosting\System\Sprinkle\SprinkleManager'); + + // Simulate the Filesystem. + $filesystem = m::mock('Illuminate\Filesystem\Filesystem'); + + // When `MigrationLocator` will ask the filesystem for `glob`, which it should do only once, + // filesystem will return fake test path. + $filesystem->shouldReceive('exists')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->andReturn(false); + $filesystem->shouldNotReceive('allFiles'); + + // Create a new MigrationLocator instance with our simulated SprinkleManager and filesystem + // and ask to find core sprinkle migration files + $locator = new MigrationLocator($sprinkleManager, $filesystem); + $results = $locator->getMigrationsForSprinkle('core'); + + // Test results match expectations + $this->assertEquals([], $results); + } + + /** + * Test MigratonLocator against the real thing, no Mockery + */ + function testActualInstance() + { + // Get sprinkle manager and make sure `core` is returned + $sprinkleManager = $this->ci->sprinkleManager; + $this->assertContains('core', $sprinkleManager->getSprinkleNames()); + + // Create a new MigrationLocator instance with our real SprinkleManager and filesystem + // and ask to find core sprinkle migration files + $locator = new MigrationLocator($sprinkleManager, new Filesystem); + $results = $locator->getMigrationsForSprinkle('core'); + + // Test results match expectations + $this->assertContains('\UserFrosting\Sprinkle\Core\Database\Migrations\v400\SessionsTable', $results); + } +} diff --git a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php new file mode 100644 index 000000000..b1fda8aa2 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php @@ -0,0 +1,136 @@ +repository = new DatabaseMigrationRepository($capsule, 'migrations'); + + // Set global expections for $capule and $connection + // Repository -> capsule -> connection -> Schema + // When repository call `getConnection`, it will receive the connection mock + // When repository call `getSchemaBuilder`, it will receive the schema builder mock + $capsule->shouldReceive('getConnection')->andReturn($connection); + $connection->shouldReceive('getSchemaBuilder')->andReturn($schemaBuilder); + } + + public function testGetRanMigrationsListMigrationsByPackage() + { + $query = m::mock('stdClass'); + + // Set expectations for the Connection mock + $this->repository->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); + + // When getRan is called, the $query should be orderedBy batch, then migration and pluck. + $query->shouldReceive('orderBy')->once()->with('id', 'asc')->andReturn(new Collection([['migration' => 'bar']])); + + $this->assertEquals(['bar'], $this->repository->getRan()); + } + + public function testGetLastBatchNumberReturnsMaxBatch() + { + $query = m::mock('stdClass'); + + // Set expectations for the Connection mock + $this->repository->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); + + // Table query will need to tell what is the max batch number + $query->shouldReceive('max')->once()->andReturn(1); + + $this->assertEquals(1, $this->repository->getLastBatchNumber()); + } + + public function testGetLastMigrationsGetsAllMigrationsWithTheLatestBatchNumber() + { + $query = m::mock('stdClass'); + + // Set expectations for the Connection mock. Table will be get twice + // (once for max batch, once to get the migration list) + $this->repository->getConnection()->shouldReceive('table')->twice()->with('migrations')->andReturn($query); + + // Table query will need to tell what is the max batch number + $query->shouldReceive('max')->once()->with('batch')->andReturn(1); + + // Table should be asked to search for batch 1, orderBy migration and return the foo migration + $query->shouldReceive('where')->once()->with('batch', 1)->andReturn($query); + $query->shouldReceive('orderBy')->once()->with('id', 'desc')->andReturn($query); + $query->shouldReceive('get')->once()->andReturn(new Collection([['migration' => 'foo']])); + + $this->assertEquals(['foo'], $this->repository->getLast()); + } + + public function testLogMethodInsertsRecordIntoMigrationTable() + { + $query = m::mock('stdClass'); + + // Set expectations for the Connection mock + $this->repository->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); + + // When log is called, the table query should receive the insert statement + $query->shouldReceive('insert')->once()->with(['migration' => 'bar', 'batch' => 1, 'sprinkle' => '']); + + $this->repository->log('bar', 1); + } + + public function testDeleteMethodRemovesAMigrationFromTheTable() + { + $query = m::mock('stdClass'); + + // Set expectations for the Connection mock + $this->repository->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); + + // When delete is called, a where and delete operation should be performed on the table + $query->shouldReceive('where')->once()->with('migration', 'foo')->andReturn($query); + $query->shouldReceive('delete')->once(); + + $this->repository->delete('foo'); + } + + public function testGetNextBatchNumberReturnsLastBatchNumberPlusOne() + { + $query = m::mock('stdClass'); + + // Set expectations for the Connection mock + $this->repository->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); + + // Table query will need to tell what is the max batch number + $query->shouldReceive('max')->once()->andReturn(2); + + $this->assertEquals(3, $this->repository->getNextBatchNumber()); + } + + public function testCreateRepositoryCreatesProperDatabaseTable() + { + // Setup expectations for SchemaBuilder. When asked to create the repository, the schema should reeceive the create command + $this->repository->getSchemaBuilder()->shouldReceive('create')->once()->with('migrations', m::type('Closure')); + $this->repository->createRepository(); + } +} diff --git a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php new file mode 100644 index 000000000..0b8bb1d5b --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php @@ -0,0 +1,33 @@ +schema->create('deprecated_table', function (Blueprint $table) { + $table->string('email')->index(); + $table->string('token')->index(); + $table->timestamp('created_at'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $this->schema->dropIfExists('deprecated_table'); + } +} diff --git a/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php b/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php new file mode 100644 index 000000000..f21a8058a --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php @@ -0,0 +1,42 @@ +schema->create('unfulfillable', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $this->schema->dropIfExists('unfulfillable'); + } +} diff --git a/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php b/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php new file mode 100644 index 000000000..4f4470052 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php @@ -0,0 +1,38 @@ +schema->create('password_resets', function (Blueprint $table) { + $table->string('email')->index(); + $table->string('token')->index(); + $table->timestamp('created_at'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $this->schema->dropIfExists('password_resets'); + } +} diff --git a/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php b/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php new file mode 100644 index 000000000..f193261ca --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php @@ -0,0 +1,42 @@ +schema->create('users', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + $table->string('email')->unique(); + $table->string('password'); + $table->rememberToken(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $this->schema->dropIfExists('users'); + } +} diff --git a/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php b/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php new file mode 100644 index 000000000..c27cbad99 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php @@ -0,0 +1,40 @@ +schema->create('flights', function (Blueprint $table) { + $table->increments('id'); + $table->string('name'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + $this->schema->dropIfExists('flights'); + } +} diff --git a/app/sprinkles/core/tests/RefreshDatabase.php b/app/sprinkles/core/tests/RefreshDatabase.php new file mode 100644 index 000000000..05a824f02 --- /dev/null +++ b/app/sprinkles/core/tests/RefreshDatabase.php @@ -0,0 +1,105 @@ +usingInMemoryDatabase() + ? $this->refreshInMemoryDatabase() + : $this->refreshTestDatabase(); + } + + /** + * Determine if an in-memory database is being used. + * + * @return bool + */ + protected function usingInMemoryDatabase() + { + $connection = $this->ci->db->getConnection(); + return $connection->getDatabaseName() == ':memory:'; + } + + /** + * Refresh the in-memory database. + * + * @return void + */ + protected function refreshInMemoryDatabase() + { + $this->ci->migrator->run(); + } + + /** + * Refresh a conventional test database. + * + * @return void + */ + protected function refreshTestDatabase() + { + if (! self::$migrated) { + + // Refresh the Database. Rollback all migrations and start over + $this->ci->migrator->reset(); + $this->ci->migrator->run(); + + self::$migrated = true; + } + + $this->beginDatabaseTransaction(); + } + + /** + * Handle database transactions on the specified connections. + * + * @return void + */ + protected function beginDatabaseTransaction() + { + $database = $this->ci->db; + + foreach ($this->connectionsToTransact() as $name) { + $database->connection($name)->beginTransaction(); + } + + $this->beforeApplicationDestroyed(function () use ($database) { + foreach ($this->connectionsToTransact() as $name) { + $database->connection($name)->rollBack(); + } + }); + } + + /** + * The database connections that should have transactions. + * + * @return array + */ + protected function connectionsToTransact() + { + return property_exists($this, 'connectionsToTransact') + ? $this->connectionsToTransact : [null]; + } +} diff --git a/app/sprinkles/core/tests/TestDatabase.php b/app/sprinkles/core/tests/TestDatabase.php new file mode 100644 index 000000000..4578a07ce --- /dev/null +++ b/app/sprinkles/core/tests/TestDatabase.php @@ -0,0 +1,24 @@ +ci->db->getDatabaseManager()->setDefaultConnection('test_integration'); + } +} diff --git a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php index d4fd4f831..9413f046a 100644 --- a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php +++ b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php @@ -7,21 +7,16 @@ */ namespace UserFrosting\Tests\Unit; -use Illuminate\Database\Capsule\Manager as DB; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Mockery as m; -use ReflectionClass; use UserFrosting\Tests\TestCase; -use UserFrosting\Tests\DatabaseTransactions; use UserFrosting\Sprinkle\Core\Database\Builder as QueryBuilder; use UserFrosting\Sprinkle\Core\Database\Models\Model; use UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough; /** * Tests the BelongsToManyThrough relation. - * - * @extends TestCase */ class BelongsToManyThroughTest extends TestCase { diff --git a/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php b/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php index 188b01246..8ae4c8d65 100644 --- a/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php +++ b/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php @@ -5,16 +5,13 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Unit; +namespace UserFrosting\Sprinkle\Core\Tests\Unit; use stdClass; use Mockery as m; -use ReflectionClass; use PHPUnit\Framework\TestCase; use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Collection; -use Illuminate\Support\Collection as BaseCollection; -use Illuminate\Database\Eloquent\ModelNotFoundException; +use Illuminate\Support\Collection; use UserFrosting\Sprinkle\Core\Database\Relations\HasManySyncable; @@ -36,9 +33,9 @@ public function testSyncMethod($list) $relation->getRelated()->shouldReceive('getKeyName')->once()->andReturn('id'); // Simulate fetching of current relationships (1,2,3) - $query = m::mock('stdClass'); + $query = m::mock(stdClass::class); $relation->shouldReceive('newQuery')->once()->andReturn($query); - $query->shouldReceive('pluck')->once()->with('id')->andReturn(new BaseCollection([1, 2, 3])); + $query->shouldReceive('pluck')->once()->with('id')->andReturn(new Collection([1, 2, 3])); // withoutGlobalScopes will get called exactly 3 times $relation->getRelated()->shouldReceive('withoutGlobalScopes')->times(3)->andReturn($query); @@ -47,7 +44,7 @@ public function testSyncMethod($list) $query->shouldReceive('whereIn')->once()->with('id', [1])->andReturn($query); $query->shouldReceive('delete')->once()->andReturn($query); - // Test updates to existing items in relationship (2,3) + // Test updates to existing items in relationship (2,3) $query->shouldReceive('where')->once()->with('id', 2)->andReturn($query); $query->shouldReceive('update')->once()->with(['id' => 2, 'species' => 'Tyto'])->andReturn($query); $query->shouldReceive('where')->once()->with('id', 3)->andReturn($query); @@ -58,7 +55,7 @@ public function testSyncMethod($list) 'id' => 'x' ]); $model->shouldReceive('getAttribute')->with('id')->andReturn('x'); - + $this->assertEquals(['created' => ['x'], 'deleted' => [1], 'updated' => [2,3]], $relation->sync($list)); } diff --git a/app/sprinkles/core/tests/Unit/SprunjeTest.php b/app/sprinkles/core/tests/Unit/SprunjeTest.php index fa193196e..c77925a80 100644 --- a/app/sprinkles/core/tests/Unit/SprunjeTest.php +++ b/app/sprinkles/core/tests/Unit/SprunjeTest.php @@ -5,12 +5,10 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Unit; +namespace UserFrosting\Sprinkle\Core\Tests\Unit; -use Illuminate\Database\Capsule\Manager as DB; use Mockery as m; use UserFrosting\Tests\TestCase; -use UserFrosting\Tests\DatabaseTransactions; use UserFrosting\Sprinkle\Core\Database\Builder as Builder; use UserFrosting\Sprinkle\Core\Database\Models\Model; use UserFrosting\Sprinkle\Core\Sprunje\Sprunje; @@ -19,8 +17,6 @@ /** * SprunjeTest class. * Tests a basic Sprunje. - * - * @extends TestCase */ class SprunjeTest extends TestCase { diff --git a/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php b/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php new file mode 100644 index 000000000..83e7c7ed0 --- /dev/null +++ b/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php @@ -0,0 +1,38 @@ +setupTestDatabase(); + } + + /** + * Test the TestDatabase traits works + */ + public function testTrait() + { + // Use the test_integration for this test + $connection = $this->ci->db->getConnection(); + $this->assertEquals('test_integration', $connection->getName()); + } +} diff --git a/app/system/Bakery/Bakery.php b/app/system/Bakery/Bakery.php index 8be84809c..959d02c83 100644 --- a/app/system/Bakery/Bakery.php +++ b/app/system/Bakery/Bakery.php @@ -19,17 +19,17 @@ class Bakery { /** - * @var $app Symfony\Component\Console\Application + * @var $app Symfony\Component\Console\Application */ protected $app; /** - * @var ContainerInterface The global container object, which holds all your services. + * @var \Interop\Container\ContainerInterface The global container object, which holds all your services. */ protected $ci; /** - * Constructor + * Constructor */ public function __construct() { @@ -56,7 +56,9 @@ public function __construct() } /** - * Run the Symfony Console App + * Run the Symfony Console App + * + * @return void */ public function run() { @@ -64,7 +66,9 @@ public function run() } /** - * Return the list of available commands for a specific sprinkle + * Return the list of available commands for a specific sprinkle + * + * @return void */ protected function loadCommands() { @@ -86,8 +90,11 @@ protected function loadCommands() } /** - * Return the list of available commands for a specific sprinkle - * Sprinkles commands should be located in `src/Bakery/` + * Return the list of available commands for a specific sprinkle + * Sprinkles commands should be located in `src/Bakery/` + * + * @param string $sprinkle The sprinkle name + * @return \Illuminate\Support\Collection A collection of commands */ protected function getSprinkleCommands($sprinkle) { @@ -108,7 +115,9 @@ protected function getSprinkleCommands($sprinkle) } /** - * Return the list of available commands in system/Bakery/Command/ + * Return the list of available commands in system/Bakery/Command/ + * + * @return \Illuminate\Support\Collection A collection of commands */ protected function getBakeryCommands() { @@ -127,11 +136,10 @@ protected function getBakeryCommands() } /** - * Returns the path of the Migration directory. + * Returns the path of the Bakery commands directory. * - * @access protected - * @param mixed $sprinkleName - * @return void + * @param string $sprinkleName The sprinkle name + * @return string The sprinkle bakery command directory path */ protected function commandDirectoryPath($sprinkleName) { @@ -144,10 +152,9 @@ protected function commandDirectoryPath($sprinkleName) } /** - * Write the base Sprinkles schema file if it doesn't exist. + * Write the base `sprinkles.json` file if none exist. * - * @access protected - * @return void + * @return string The sprinkle model file */ protected function setupBaseSprinkleList() { diff --git a/app/system/Bakery/BaseCommand.php b/app/system/Bakery/BaseCommand.php index 1a59141b4..209178992 100644 --- a/app/system/Bakery/BaseCommand.php +++ b/app/system/Bakery/BaseCommand.php @@ -24,18 +24,13 @@ abstract class BaseCommand extends Command { /** - * @var @Symfony\Component\Console\Style\SymfonyStyle - * See http://symfony.com/doc/current/console/style.html + * @var @Symfony\Component\Console\Style\SymfonyStyle + * See http://symfony.com/doc/current/console/style.html */ protected $io; /** - * @var string Path to the project root folder - */ - protected $projectRoot; - - /** - * @var ContainerInterface $ci The global container object, which holds all of the UserFrosting services. + * @var ContainerInterface $ci The global container object, which holds all of UserFristing services. */ protected $ci; @@ -45,14 +40,29 @@ abstract class BaseCommand extends Command protected function initialize(InputInterface $input, OutputInterface $output) { $this->io = new SymfonyStyle($input, $output); - $this->projectRoot = \UserFrosting\ROOT_DIR; } /** - * Setup the global container object + * Setup the global container object + * + * @param ContainerInterface $ci */ public function setContainer(ContainerInterface $ci) { $this->ci = $ci; } + + /** + * Return if the app is in production mode + * + * @return bool True/False if the app is in production mode + */ + protected function isProduction() + { + // N.B.: Need to touch the config service first to load dotenv values + $config = $this->ci->config; + $mode = getenv("UF_MODE") ?: ''; + + return ($mode == "production"); + } } diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/system/Bakery/Command/BuildAssets.php index 3143ab1c8..7dc4cf257 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/system/Bakery/Command/BuildAssets.php @@ -47,7 +47,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->title("UserFrosting's Assets Builder"); // Set $path - $this->buildPath = $this->projectRoot . \UserFrosting\DS . \UserFrosting\BUILD_DIR_NAME; + $this->buildPath = \UserFrosting\ROOT_DIR . \UserFrosting\DS . \UserFrosting\BUILD_DIR_NAME; // Delete cached data is requested if ($input->getOption('force')) { @@ -183,19 +183,4 @@ protected function clean() exit(1); } } - - /** - * Return if the app is in production mode - * - * @access protected - * @return bool - */ - protected function isProduction() - { - // N.B.: Need to touch the config service first to load dotenv values - $config = $this->ci->config; - $mode = getenv("UF_MODE") ?: ''; - - return ($mode == "production"); - } -} \ No newline at end of file +} diff --git a/app/system/Bakery/Command/Migrate.php b/app/system/Bakery/Command/Migrate.php deleted file mode 100644 index c0a5b4f3a..000000000 --- a/app/system/Bakery/Command/Migrate.php +++ /dev/null @@ -1,48 +0,0 @@ -setName("migrate") - ->setDescription("Perform database migration") - ->setHelp("This command runs all the pending database migrations.") - ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->io->title("UserFrosting's Migrator"); - - $pretend = $input->getOption('pretend'); - - $migrator = new Migrator($this->io, $this->ci); - $migrator->runUp($pretend); - } -} \ No newline at end of file diff --git a/app/system/Bakery/Command/MigrateRefresh.php b/app/system/Bakery/Command/MigrateRefresh.php deleted file mode 100644 index 3d18c41fe..000000000 --- a/app/system/Bakery/Command/MigrateRefresh.php +++ /dev/null @@ -1,52 +0,0 @@ -setName("migrate:refresh") - ->setDescription("Rollback the last migration operation and run it up again") - ->addOption('steps', 's', InputOption::VALUE_REQUIRED, 'Number of steps to rollback', 1) - ->addOption('sprinkle', null, InputOption::VALUE_REQUIRED, 'The sprinkle to rollback', "") - ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->io->title("Migration refresh"); - - $step = $input->getOption('steps'); - $sprinkle = $input->getOption('sprinkle'); - $pretend = $input->getOption('pretend'); - - $migrator = new Migrator($this->io, $this->ci); - $migrator->runDown($step, $sprinkle, $pretend); - $migrator->runUp($pretend); - } -} \ No newline at end of file diff --git a/app/system/Bakery/Command/MigrateReset.php b/app/system/Bakery/Command/MigrateReset.php deleted file mode 100644 index 9e38cbb02..000000000 --- a/app/system/Bakery/Command/MigrateReset.php +++ /dev/null @@ -1,49 +0,0 @@ -setName("migrate:reset") - ->setDescription("Reset the whole database to an empty state") - ->addOption('sprinkle', null, InputOption::VALUE_REQUIRED, 'The sprinkle to rollback', "") - ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->io->title("Migration reset"); - - $sprinkle = $input->getOption('sprinkle'); - $pretend = $input->getOption('pretend'); - - $migrator = new Migrator($this->io, $this->ci); - $migrator->runDown(-1, $sprinkle, $pretend); - } -} \ No newline at end of file diff --git a/app/system/Bakery/Command/MigrateRollback.php b/app/system/Bakery/Command/MigrateRollback.php deleted file mode 100644 index 916f5eef8..000000000 --- a/app/system/Bakery/Command/MigrateRollback.php +++ /dev/null @@ -1,51 +0,0 @@ -setName("migrate:rollback") - ->setDescription("Rollback last database migration") - ->addOption('steps', 's', InputOption::VALUE_REQUIRED, 'Number of steps to rollback', 1) - ->addOption('sprinkle', null, InputOption::VALUE_REQUIRED, 'The sprinkle to rollback', "") - ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode'); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - $this->io->title("Migration rollback"); - - $step = $input->getOption('steps'); - $sprinkle = $input->getOption('sprinkle'); - $pretend = $input->getOption('pretend'); - - $migrator = new Migrator($this->io, $this->ci); - $migrator->runDown($step, $sprinkle, $pretend); - } -} \ No newline at end of file diff --git a/app/system/Bakery/ConfirmableTrait.php b/app/system/Bakery/ConfirmableTrait.php new file mode 100644 index 000000000..2e3bc03c0 --- /dev/null +++ b/app/system/Bakery/ConfirmableTrait.php @@ -0,0 +1,63 @@ +getDefaultConfirmCallback() : $callback; + + // Process callback to determine if we should ask for confirmation + $shouldConfirm = $callback instanceof Closure ? call_user_func($callback) : $callback; + + if ($shouldConfirm & !$force) { + + // Display warning + $this->io->warning($warning); + + // Ask confirmation + $confirmed = $this->io->confirm('Do you really wish to run this command?', false); + + if (! $confirmed) { + $this->io->comment('Command Cancelled!'); + return false; + } + } + + return true; + } + + /** + * Get the default confirmation callback. + * + * @return \Closure + */ + protected function getDefaultConfirmCallback() + { + return function () { + return $this->isProduction(); + }; + } +} diff --git a/app/system/Bakery/Migration.php b/app/system/Bakery/Migration.php index e6c6ae0b3..0b2843602 100644 --- a/app/system/Bakery/Migration.php +++ b/app/system/Bakery/Migration.php @@ -8,57 +8,28 @@ namespace UserFrosting\System\Bakery; use Illuminate\Database\Schema\Builder; +use UserFrosting\Sprinkle\Core\Database\Migration as NewMigration; use Symfony\Component\Console\Style\SymfonyStyle; +use UserFrosting\Sprinkle\Core\Facades\Debug; /** * Abstract Migration class. * - * @abstract + * @deprecated since 4.2.0 Use `UserFrosting\Sprinkle\Core\Database\Migration` instead * @author Alex Weissman (https://alexanderweissman.com) */ -abstract class Migration +class Migration extends NewMigration { /** - * @var Illuminate\Database\Schema\Builder $schema - */ - protected $schema; - - /** - * @var @Composer\IO\IOInterface - */ - protected $io; - - /** - * List of dependencies for this migration. - * Should return an array of class required to be run before this migration - */ - public $dependencies = []; - - /** - * __construct function. + * Constructor * - * @access public - * @param Illuminate\Database\Schema\Builder $schema - * @return void + * @param Builder $schema The schema builder + * @param SymfonyStyle $io The SymfonyStyle instance */ - public function __construct(Builder $schema, SymfonyStyle $io) + public function __construct(Builder $schema = null, SymfonyStyle $io = null) { - $this->schema = $schema; - $this->io = $io; - } + Debug::debug("`UserFrosting\System\Bakery\Migration` has been deprecated and will be removed in future versions. Please have your `" . static::class . "` migration extend the base `UserFrosting\Sprinkle\Core\Database\Migration` class instead."); - /** - * Method to apply changes to the database - */ - public function up() {} - - /** - * Method to revert changes applied by the `up` method - */ - public function down() {} - - /** - * Method to seed new information to the database - */ - public function seed() {} + parent::__construct($schema); + } } diff --git a/app/system/Bakery/Migrator.php b/app/system/Bakery/Migrator.php deleted file mode 100644 index 611f73f50..000000000 --- a/app/system/Bakery/Migrator.php +++ /dev/null @@ -1,584 +0,0 @@ -io = $io; - $this->ci = $ci; - - // Start by testing the DB connexion, just in case - try { - $this->io->writeln("Testing database connection", OutputInterface::VERBOSITY_VERBOSE); - $this->testDB(); - $this->io->writeln("Ok", OutputInterface::VERBOSITY_VERBOSE); - } catch (\Exception $e) { - $this->io->error($e->getMessage()); - exit(1); - } - - // Get schema required to run the table blueprints - $this->schema = Capsule::schema(); - - // Make sure the setup table exist - $this->setupVersionTable(); - } - - /** - * Run all the migrations available - * - * @access public - * @param bool $pretend (default: false) - * @return void - */ - public function runUp($pretend = false) - { - // Get installed migrations and pluck by class name. We only need this for now - $migrations = Migrations::get(); - $this->installed = $migrations->pluck('migration'); - - $this->io->writeln("\nInstalled migrations:", OutputInterface::VERBOSITY_VERBOSE); - $this->io->writeln($this->installed->toArray(), OutputInterface::VERBOSITY_VERBOSE); - - // Get pending migrations - $this->io->section("Fetching available migrations"); - $this->pending = $this->getPendingMigrations(); - - // If there's no pending migration, don't need to go further - if ($this->pending->isEmpty()) { - $this->io->success("Nothing to migrate !"); - return; - } - - // Resolve the dependencies - $this->resolveDependencies(); - - // If there are any unfulfillable migration, we can't continue - if (!$this->unfulfillable->isEmpty()) { - - $msg = "\nSome migrations dependencies can't be met. Check those migrations for unmet dependencies and try again:"; - - foreach ($this->unfulfillable as $migration) { - $msg .= "\n{$migration->className} depends on \n - "; - $msg .= implode("\n - ", $migration->dependencies); - $msg .= "\n"; - } - - $this->io->error($msg); - exit(1); - } - - // Ready to run ! - $this->io->section("Running migrations"); - - if ($pretend) { - $this->io->note("Running migration in pretend mode"); - } - - // We have a list of fulfillable migration, we run them up! - foreach ($this->fulfillable as $migration) { - $this->io->write("\n> Migrating {$migration->className}..."); - - if ($pretend) { - $this->io->newLine(); - $this->pretendToRun($migration, 'up'); - } else { - $migration->up(); - $migration->seed(); - $this->log($migration); - $this->io->writeln(" Done!"); - } - } - - // If all went well and there's no fatal errors, we are ready to bake - $this->io->success("Migration successful !"); - } - - /** - * Rollback the last btach of migrations. - * - * @access public - * @param int $step (default: 1). Number of batch we will be going back. -1 revert all migrations - * @param string $sprinkle (default: "") Limit rollback to a specific sprinkle - * @param bool $pretend (default: false) - * @return void - */ - public function runDown($step = 1, $sprinkle = "", $pretend = false) - { - // Can't go furhter down than 1 step - if ($step <= 0 && $step != -1) { - throw new \InvalidArgumentException("Step can't be 0 or less"); - } - - // Get last batch number - $batch = $this->getNextBatchNumber(); - - // Calculate the number of steps back we need to take - if ($step == -1) { - $stepsBack = 1; - $this->io->warning("Rolling back all migrations"); - } else { - $stepsBack = max($batch - $step, 1); - $this->io->note("Rolling back $step steps to batch $stepsBack", OutputInterface::VERBOSITY_VERBOSE); - } - - // Get installed migrations - $migrations = Migrations::orderBy("id", "desc")->where('batch', '>=', $stepsBack); - - // Add the sprinkle requirement too - if ($sprinkle != "") { - $this->io->note("Rolling back sprinkle `$sprinkle`", OutputInterface::VERBOSITY_VERBOSE); - $migrations->where('sprinkle', $sprinkle); - } - - // Run query - $migrations = $migrations->get(); - - // If there's nothing to rollback, stop here - if ($migrations->isEmpty()) { - $this->io->writeln("Nothing to rollback"); - exit(1); - } - - // Get pending migrations - $this->io->writeln("Migration to rollback:"); - $this->io->listing($migrations->pluck('migration')->toArray()); - - // Ask confirmation to continue. - if (!$pretend && !$this->io->confirm("Continue?", false)) { - exit(1); - } - - if ($pretend) { - $this->io->note("Rolling back in pretend mode"); - } - - // Loop again to run down each migration - foreach ($migrations as $migration) { - - // Check if those migration class are available - if (!class_exists($migration->migration)) { - $this->io->warning("Migration class {$migration->migration} doesn't exist."); - continue; - } - - $this->io->write("> Rolling back {$migration->migration}..."); - $migrationClass = $migration->migration; - $instance = new $migrationClass($this->schema, $this->io); - - if ($pretend) { - $this->io->newLine(); - $this->pretendToRun($instance, 'down'); - } else { - $instance->down(); - $migration->delete(); - $this->io->writeln(" Done!"); - } - - $this->io->newLine(); - } - - // If all went well and there's no fatal errors, we are ready to bake - $this->io->success("Rollback successful !"); - } - - /** - * Pretend to run migration class. - * - * @access protected - * @param mixed $migration - * @param string $method up/down - */ - protected function pretendToRun($migration, $method) - { - foreach ($this->getQueries($migration, $method) as $query) { - $this->io->writeln($query['query'], OutputInterface::VERBOSITY_VERBOSE); - } - } - - /** - * Return all of the queries that would be run for a migration. - * - * @access protected - * @param mixed $migration - * @param string $method up/down - * @return void - */ - protected function getQueries($migration, $method) - { - $db = $this->schema->getConnection(); - - return $db->pretend(function () use ($migration, $method) { - if (method_exists($migration, $method)) { - $migration->{$method}(); - } - }); - } - - /** - * Get pending migrations by looking at all the migration files - * and finding the one not yet runed by compairing with the ran migrations - * - * @access protected - * @return void - */ - protected function getPendingMigrations() - { - $pending = collect([]); - - // Get the sprinkle list - $sprinkles = $this->ci->sprinkleManager->getSprinkleNames(); - - // Loop all the sprinkles to find their pending migrations - foreach ($sprinkles as $sprinkle) { - - $this->io->writeln("> Fetching from `$sprinkle`"); - - // We get all the migrations. This will return them as a colleciton of class names - $migrations = $this->getMigrations($sprinkle); - - // We filter the available migration by removing the one that have already been run - // This reject the class name found in the installed collection - $migrations = $migrations->reject(function ($value, $key) { - return $this->installed->contains($value); - }); - - // Load each class - foreach ($migrations as $migrationClass) { - - // Make sure the class exist - if (!class_exists($migrationClass)) { - throw new BadClassNameException("Unable to find the migration class '$migrationClass'." ); - } - - // Load the migration class - $migration = new $migrationClass($this->schema, $this->io); - - //Set the sprinkle - $migration->sprinkle = $sprinkle; - - // Also set the class name. We could find it using ::class, but this - // will make it easier to manipulate the collection - $migration->className = $migrationClass; - - // Add it to the pending list - $pending->push($migration); - } - } - - // Get pending migrations - $pendingArray = ($pending->pluck('className')->toArray()) ?: ""; - $this->io->writeln("\nPending migrations:", OutputInterface::VERBOSITY_VERBOSE); - $this->io->writeln($pendingArray, OutputInterface::VERBOSITY_VERBOSE); - - return $pending; - } - - /** - * Get the list of migrations avaiables in the filesystem. - * Return a list of resolved className - * - * @access public - * @param string $sprinkleName - * @return void - */ - public function getMigrations($sprinkle) - { - // Find all the migration files - $path = $this->migrationDirectoryPath($sprinkle); - $files = glob($path . "*/*.php"); - - // Transform the array in a collection - $migrations = collect($files); - - // We transform the path into a migration object - $migrations->transform(function ($file) use ($sprinkle, $path) { - // Deconstruct the path - $migration = str_replace($path, "", $file); - $className = basename($file, '.php'); - $sprinkleName = Str::studly($sprinkle); - $version = str_replace("/$className.php", "", $migration); - - // Reconstruct the classname - $className = "\\UserFrosting\\Sprinkle\\".$sprinkleName."\\Database\\Migrations\\".$version."\\".$className; - - return $className; - }); - - return $migrations; - } - - /** - * Resolve all the dependencies for all the pending migrations - * This function fills in the `fullfillable` and `unfulfillable` list - * - * @access protected - * @return void - */ - protected function resolveDependencies() - { - $this->io->writeln("\nResolving migrations dependencies...", OutputInterface::VERBOSITY_VERBOSE); - - // Reset fulfillable/unfulfillable lists - $this->fulfillable = collect([]); - $this->unfulfillable = collect([]); - - // Loop pending and check for dependencies - foreach ($this->pending as $migration) { - $this->validateClassDependencies($migration); - } - - $fulfillable = ($this->fulfillable->pluck('className')->toArray()) ?: ""; - $this->io->writeln("\nFulfillable migrations:", OutputInterface::VERBOSITY_VERBOSE); - $this->io->writeln($fulfillable, OutputInterface::VERBOSITY_VERBOSE); - - $unfulfillable = ($this->unfulfillable->pluck('className')->toArray()) ?: ""; - $this->io->writeln("\nUnfulfillable migrations:", OutputInterface::VERBOSITY_VERBOSE); - $this->io->writeln($unfulfillable, OutputInterface::VERBOSITY_VERBOSE); - } - - /** - * Check if a migration dependencies are met. - * To test if a migration is fulfillable, the class must : - * Already been installed OR exist and have all it's dependencies met - * - * @access protected - * @param $migration - * @return bool true/false if all conditions are met - */ - protected function validateClassDependencies($migration) - { - $this->io->writeln("> Checking dependencies for {$migration->className}", OutputInterface::VERBOSITY_VERBOSE); - - // If it's already marked as fulfillable, it's fulfillable - // Return true directly (it's already marked) - if ($this->fulfillable->contains($migration)) { - return true; - } - - // If it's already marked as unfulfillable, it's unfulfillable - // Return false directly (it's already marked) - if ($this->unfulfillable->contains($migration)) { - return false; - } - - // If it's already run, it's fulfillable - // Mark it as such for next time it comes up in this loop - if ($this->installed->contains($migration->className)) { - return $this->markAsFulfillable($migration); - } - - // Loop dependencies. If one is not fulfillable, then this one is not either - foreach ($migration->dependencies as $dependencyClass) { - - // The dependency might already be installed. Check that first - if ($this->installed->contains($dependencyClass)) { - continue; - } - - // Try to find it in the `pending` list. Cant' find it? Then it's not fulfillable - $dependency = $this->pending->where('className', $dependencyClass)->first(); - - // Check migration dependencies of this one right now - // If ti's not fullfillable, then this one isn't either - if (!$dependency || !$this->validateClassDependencies($dependency)) { - return $this->markAsUnfulfillable($migration); - } - } - - // If no dependencies returned false, it's fulfillable - return $this->markAsFulfillable($migration); - } - - /** - * Mark a dependency as fulfillable. - * Removes it from the pending list and add it to the fulfillable list - * - * @access protected - * @param $migration - * @return true - */ - protected function markAsFulfillable($migration) - { - $this->fulfillable->push($migration); - return true; - } - - /** - * Mark a dependency as unfulfillable. - * Removes it from the pending list and add it to the unfulfillable list - * - * @access protected - * @param $migration - * @return false - */ - protected function markAsUnfulfillable($migration) - { - $this->unfulfillable->push($migration); - return false; - } - - /** - * Log that a migration was run. - * - * @access public - * @param mixed $migration - * @return void - */ - protected function log($migration) - { - // Get the next batch number if not defined - if (!$this->batch) { - $this->batch = $this->getNextBatchNumber(); - } - - $log = new Migrations([ - 'sprinkle' => $migration->sprinkle, - 'migration' => $migration->className, - 'batch' => $this->batch - ]); - $log->save(); - } - - /** - * Return the next batch number from the db. - * Batch number is used to group together migration run in the same operation - * - * @access public - * @return int the next batch number - */ - public function getNextBatchNumber() - { - $batch = Migrations::max('batch'); - return ($batch) ? $batch + 1 : 1; - } - - /** - * Create the migration history table if needed. - * Also check if the tables requires migrations - * We run the migration file manually for this one - * - * @access public - * @return void - */ - protected function setupVersionTable() - { - // Check if the `migrations` table exist. Create it manually otherwise - if (!$this->schema->hasColumn($this->table, 'id')) { - $this->io->section("Creating the `{$this->table}` table"); - - $migration = new \UserFrosting\System\Database\Migrations\v410\MigrationTable($this->schema, $this->io); - $migration->up(); - - $this->io->success("Table `{$this->table}` created"); - } - } - - /** - * Returns the path of the Migration directory. - * - * @access protected - * @param mixed $sprinkleName - * @return void - */ - protected function migrationDirectoryPath($sprinkleName) - { - $path = \UserFrosting\SPRINKLES_DIR . - \UserFrosting\DS . - $sprinkleName . - \UserFrosting\DS . - \UserFrosting\SRC_DIR_NAME . - "/Database/Migrations/"; - - return $path; - } -} diff --git a/app/system/Database/Migrations/v410/MigrationTable.php b/app/system/Database/Migrations/v410/MigrationTable.php deleted file mode 100644 index fb833dfa8..000000000 --- a/app/system/Database/Migrations/v410/MigrationTable.php +++ /dev/null @@ -1,59 +0,0 @@ -schema->create('migrations', function (Blueprint $table) { - $table->increments('id'); - $table->string('sprinkle'); - $table->string('migration'); - $table->integer('batch'); - $table->timestamps(); - - $table->engine = 'InnoDB'; - $table->collation = 'utf8_unicode_ci'; - $table->charset = 'utf8'; - }); - - // Drop the old `version` table if found - if ($this->schema->hasTable('version')) { - $this->schema->drop('version'); - } - } - - /** - * {@inheritDoc} - */ - public function down() - { - $this->schema->drop('migrations'); - } -} diff --git a/app/system/Database/Model/Migrations.php b/app/system/Database/Model/Migrations.php deleted file mode 100644 index 6a0942e49..000000000 --- a/app/system/Database/Model/Migrations.php +++ /dev/null @@ -1,55 +0,0 @@ -where('sprinkle', $sprinkleName); - } -} diff --git a/app/tests/DatabaseTransactions.php b/app/tests/DatabaseTransactions.php index ed2225bef..88d853f11 100644 --- a/app/tests/DatabaseTransactions.php +++ b/app/tests/DatabaseTransactions.php @@ -22,7 +22,7 @@ trait DatabaseTransactions */ public function beginDatabaseTransaction() { - $database = $this->ci['db']; + $database = $this->ci->db; foreach ($this->connectionsToTransact() as $name) { $database->connection($name)->beginTransaction(); @@ -45,4 +45,4 @@ protected function connectionsToTransact() return property_exists($this, 'connectionsToTransact') ? $this->connectionsToTransact : [null]; } -} \ No newline at end of file +} diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php index 1115abee4..bd8b2237f 100644 --- a/app/tests/TestCase.php +++ b/app/tests/TestCase.php @@ -10,6 +10,8 @@ use Slim\App; use PHPUnit\Framework\TestCase as BaseTestCase; use UserFrosting\System\UserFrosting; +use UserFrosting\Sprinkle\Core\Facades\Debug; +use UserFrosting\Tests\DatabaseTransactions; /** * Class to handle Test @@ -82,11 +84,8 @@ protected function setUpTraits() { $uses = array_flip(class_uses_recursive(static::class)); - /*if (isset($uses[DatabaseMigrations::class])) { - $this->runDatabaseMigrations(); - }*/ - if (isset($uses[DatabaseTransactions::class])) { + Debug::debug("`UserFrosting\Tests\DatabaseTransactions` has been deprecated and will be removed in future versions. Please use `UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` class instead."); $this->beginDatabaseTransaction(); } } @@ -155,12 +154,14 @@ public function afterApplicationCreated(callable $callback) } /** - * Asserts that collections are equivalent. + * Asserts that collections are equivalent. * - * @param array $expected - * @param array $actual - * @param string $message - * @throws PHPUnit_Framework_AssertionFailedError + * @param array $expected + * @param array $actual + * @param string $key [description] + * @param string $message [description] + * @throws \PHPUnit_Framework_AssertionFailedError + * @return void */ public static function assertCollectionsSame($expected, $actual, $key = 'id', $message = '') { @@ -203,10 +204,10 @@ protected function beforeApplicationDestroyed(callable $callback) */ /** - * Cast an item to an array if it has a toArray() method. + * Cast an item to an array if it has a toArray() method. * - * @param $item Collection|mixed[]|mixed - * @return mixed|mixed[] + * @param object $item + * @return mixed */ protected static function castToComparable($item) { @@ -214,7 +215,10 @@ protected static function castToComparable($item) } /** - * Remove all relations on a collection of models. + * Remove all relations on a collection of models. + * + * @param array $models + * @return void */ protected static function ignoreRelations($models) { @@ -223,14 +227,20 @@ protected static function ignoreRelations($models) } } + /** + * cloneObjectArray + * + * @param array $original + * @return array + */ protected function cloneObjectArray($original) { $cloned = []; - + foreach ($original as $k => $v) { $cloned[$k] = clone $v; } return $cloned; } -} \ No newline at end of file +} diff --git a/app/tests/Unit/ExampleTest.php b/app/tests/Unit/ExampleTest.php index 4ac3e840f..ec7a47ca3 100644 --- a/app/tests/Unit/ExampleTest.php +++ b/app/tests/Unit/ExampleTest.php @@ -3,7 +3,6 @@ namespace UserFrosting\Tests\Unit; use UserFrosting\Tests\TestCase; -use UserFrosting\Tests\DatabaseTransactions; class ExampleTest extends TestCase { From 3b62302616ac2407ddf1a0464d595f3798058ae0 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 11 Jan 2018 20:57:41 -0500 Subject: [PATCH 025/237] Fix git merge catastrophe --- .../src/ServicesProvider/ServicesProvider.php | 109 +++++++++--------- 1 file changed, 54 insertions(+), 55 deletions(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index cdbcffe8c..f22dce04f 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -20,12 +20,14 @@ use League\FactoryMuffin\FactoryMuffin; use League\FactoryMuffin\Faker\Facade as Faker; use Monolog\Formatter\LineFormatter; +use Monolog\Handler\ErrorLogHandler; use Monolog\Handler\StreamHandler; use Monolog\Logger; use Slim\Csrf\Guard; use Slim\Http\Uri; use Slim\Views\Twig; use Slim\Views\TwigExtension; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use UserFrosting\Assets\AssetBundleSchema; use UserFrosting\Cache\TaggableFileStore; use UserFrosting\Cache\MemcachedStore; @@ -94,17 +96,16 @@ public function register(ContainerInterface $container) /** * Asset loader service * - - * - * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. * Loads assets from a specified relative location. * Assets are Javascript, CSS, image, and other files used by your site. + * + * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. */ $container['assetLoader'] = function ($c) { $basePath = \UserFrosting\SPRINKLES_DIR; + $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; + return new AssetLoader($basePath, $pattern); - $al = new AssetLoader($basePath, $pattern); - return $al; }; /** @@ -113,6 +114,9 @@ public function register(ContainerInterface $container) * Loads raw or compiled asset information from your bundle.config.json schema file. * Assets are Javascript, CSS, image, and other files used by your site. */ + $container['assets'] = function ($c) { + $config = $c->config; + $locator = $c->locator; // Hacky way to clean up locator paths. $locatorPaths = []; @@ -121,20 +125,24 @@ public function register(ContainerInterface $container) $locatorPaths[] = $path; } } - $container['assets'] = function ($c) { - $config = $c->config; - $locator = $c->locator; + // Load asset schema + if ($config['assets.use_raw']) { + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; $sprinkles = $c->sprinkleManager->getSprinkleNames(); + $prefixTransformer = new PrefixTransformer(); $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); + foreach ($sprinkles as $sprinkle) { $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); } $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); + // Load raw asset bundles for each Sprinkle. + // Retrieve locations of raw asset bundle schemas that exist. $bundleSchemas = $locator->findResources('sprinkles://' . $config['assets.raw.schema']); @@ -144,28 +152,21 @@ public function register(ContainerInterface $container) foreach ($bundleSchemas as $bundleSchema) { $bundles->extend($bundleSchema); + } // Add bundles to asset manager. $assets->addAssetBundles($bundles); - // TODO: move this out into PathBuilder and Loader classes in userfrosting/assets - // This would also allow us to define and load bundles in themes - $bundleSchemas = array_reverse($locator->findResources('sprinkles://' . $config['assets.raw.schema'], true, true)); + } + } else { + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; $assets = new Assets($locator, 'assets', $baseUrl); $assets->overrideBasePath($locator->getBase() . '/public/assets'); + // Load compiled asset bundle. $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); - $as->loadRawSchemaFile($schema); - return $assets; - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; - $aub = new CompiledAssetUrlBuilder($baseUrl); - - $as = new AssetBundleSchema($aub); - $as->loadCompiledSchemaFile($locator->findResource("build://" . $config['assets.compiled.schema'], true, true)); } - $am = new AssetManager($aub, $as); - - return $am; + return $assets; }; /** @@ -227,27 +228,21 @@ public function register(ContainerInterface $container) } catch (InvalidPathException $e) { // Skip loading the environment config file if it doesn't exist. } - $uri = $c->request->getUri(); - $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); - if (!isset($config['site.uri.public'])) { - $base_uri = $config['site.uri.base']; + // Get configuration mode from environment + $mode = getenv('UF_MODE') ?: ''; - $public = new Uri( - $base_uri['scheme'], - $base_uri['host'], - $base_uri['port'], - $base_uri['path'] - ); + // Construct and load config repository + $builder = new ConfigPathBuilder($c->locator, 'config://'); + $loader = new ArrayFileLoader($builder->buildPaths($mode)); + $config = new Repository($loader->load()); - // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) - if (!$config['assets.use_raw']) { - $c->locator->resetScheme('assets'); - $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); - } + // Construct base url from components, if not explicitly specified + if (!isset($config['site.uri.public'])) { + $uri = $c->request->getUri(); // Slim\Http\Uri likes to add trailing slashes when the path is empty, so this fixes that. - $config['site.uri.public'] = trim($public, '/'); + $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); } // Hacky fix to prevent sessions from being hit too much: ignore CSRF middleware for requests for raw assets ;-) @@ -259,6 +254,12 @@ public function register(ContainerInterface $container) $config->set('csrf.blacklist', $csrfBlacklist); + // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) + if (!$config['assets.use_raw']) { + $c->locator->resetScheme('assets'); + $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); + } + return $config; }; @@ -409,14 +410,28 @@ public function register(ContainerInterface $container) $fm = new FactoryMuffin(); // Load all of the model definitions - $request = $c->request; $fm->loadFactories($factoriesPath); // Set the locale. Could be the config one, but for testing English should do Faker::setLocale('en_EN'); return $fm; + }; + + /** + * Builds search paths for locales in all Sprinkles. + */ + $container['localePathBuilder'] = function ($c) { + $config = $c->config; + $request = $c->request; + + // Make sure the locale config is a valid string + if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { + throw new \UnexpectedValueException('The locale config is not a valid string.'); + } + // Get default locales as specified in configurations. + $locales = explode(',', $config['site.locales.default']); // Add supported browser preferred locales. if ($request->hasHeader('Accept-Language')) { @@ -453,20 +468,6 @@ public function register(ContainerInterface $container) $locales = array_reverse(array_unique(array_reverse($locales), SORT_STRING)); } - /** - * Builds search paths for locales in all Sprinkles. - */ - $container['localePathBuilder'] = function ($c) { - $config = $c->config; - - // Make sure the locale config is a valid string - if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { - throw new \UnexpectedValueException('The locale config is not a valid string.'); - } - - // Load the base locale file(s) as specified in the configuration - $locales = explode(',', $config['site.locales.default']); - return new LocalePathBuilder($c->locator, 'locale://', $locales); }; @@ -570,9 +571,7 @@ public function register(ContainerInterface $container) $container['router'] = function ($c) { $routerCacheFile = false; if (isset($c->config['settings.routerCacheFile'])) { - $fs = new Filesystem; - - + $routerCacheFile = $c->config['settings.routerCacheFile']; } return (new Router)->setCacheFile($routerCacheFile); From 9fa4a77fc2e669d804f5f6ce09cfe559f4114ffc Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 11 Jan 2018 21:09:03 -0500 Subject: [PATCH 026/237] This was wrong --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 50f3949e4..61266a064 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,6 @@ build/node_modules/* # Ignore generated bundle schema files build/bundle.config.json build/bundle.result.json -build/package-lock.json # Ignore temporary build assets build/temp From aaef7e3ae38df5cfeac94d03af084296271f617e Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 11 Jan 2018 21:53:25 -0500 Subject: [PATCH 027/237] CRLF -> LF --- .../src/ServicesProvider/ServicesProvider.php | 1392 ++++++++--------- 1 file changed, 696 insertions(+), 696 deletions(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 66274f8e2..a211244c9 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -1,696 +1,696 @@ -config; - - if ($config['alert.storage'] == 'cache') { - return new CacheAlertStream($config['alert.key'], $c->translator, $c->cache, $c->config); - } elseif ($config['alert.storage'] == 'session') { - return new SessionAlertStream($config['alert.key'], $c->translator, $c->session); - } else { - throw new \Exception("Bad alert storage handler type '{$config['alert.storage']}' specified in configuration file."); - } - }; - - /** - * Asset loader service - * - * Loads assets from a specified relative location. - * Assets are Javascript, CSS, image, and other files used by your site. - * - * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. - */ - $container['assetLoader'] = function ($c) { - $basePath = \UserFrosting\SPRINKLES_DIR; - $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; - - return new AssetLoader($basePath, $pattern); - }; - - /** - * Asset manager service. - * - * Loads raw or compiled asset information from your bundle.config.json schema file. - * Assets are Javascript, CSS, image, and other files used by your site. - */ - $container['assets'] = function ($c) { - $config = $c->config; - $locator = $c->locator; - - // Hacky way to clean up locator paths. - $locatorPaths = []; - foreach ($locator->getPaths('assets') as $pathSet) { - foreach ($pathSet as $path) { - $locatorPaths[] = $path; - } - } - - // Load asset schema - if ($config['assets.use_raw']) { - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; - - $sprinkles = $c->sprinkleManager->getSprinkleNames(); - - $prefixTransformer = new PrefixTransformer(); - $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); - $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); - - foreach ($sprinkles as $sprinkle) { - $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); - } - $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); - - // Load raw asset bundles for each Sprinkle. - - // Retrieve locations of raw asset bundle schemas that exist. - $bundleSchemas = $locator->findResources('sprinkles://' . $config['assets.raw.schema']); - - // Load asset bundle schemas that exist. - if (array_key_exists(0, $bundleSchemas)) { - $bundles = new RawAssetBundles(array_shift($bundleSchemas)); - - foreach ($bundleSchemas as $bundleSchema) { - $bundles->extend($bundleSchema); - } - - // Add bundles to asset manager. - $assets->addAssetBundles($bundles); - } - } else { - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; - $assets = new Assets($locator, 'assets', $baseUrl); - $assets->overrideBasePath($locator->getBase() . '/public/assets'); - - // Load compiled asset bundle. - $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); - } - - return $assets; - }; - - /** - * Cache service. - * - * @return \Illuminate\Cache\TaggedCache - */ - $container['cache'] = function ($c) { - - $config = $c->config; - - if ($config['cache.driver'] == 'file') { - $path = $c->locator->findResource('cache://', true, true); - $cacheStore = new TaggableFileStore($path); - } elseif ($config['cache.driver'] == 'memcached') { - // We need to inject the prefix in the memcached config - $config = array_merge($config['cache.memcached'], ['prefix' => $config['cache.prefix']]); - $cacheStore = new MemcachedStore($config); - } elseif ($config['cache.driver'] == 'redis') { - // We need to inject the prefix in the redis config - $config = array_merge($config['cache.redis'], ['prefix' => $config['cache.prefix']]); - $cacheStore = new RedisStore($config); - } else { - throw new \Exception("Bad cache store type '{$config['cache.driver']}' specified in configuration file."); - } - - return $cacheStore->instance(); - }; - - /** - * Middleware to check environment. - * - * @todo We should cache the results of this, the first time that it succeeds. - */ - $container['checkEnvironment'] = function ($c) { - $checkEnvironment = new CheckEnvironment($c->view, $c->locator, $c->cache); - return $checkEnvironment; - }; - - /** - * Class mapper. - * - * Creates an abstraction on top of class names to allow extending them in sprinkles. - */ - $container['classMapper'] = function ($c) { - $classMapper = new ClassMapper(); - $classMapper->setClassMapping('query_builder', 'UserFrosting\Sprinkle\Core\Database\Builder'); - $classMapper->setClassMapping('throttle', 'UserFrosting\Sprinkle\Core\Database\Models\Throttle'); - return $classMapper; - }; - - /** - * Site config service (separate from Slim settings). - * - * Will attempt to automatically determine which config file(s) to use based on the value of the UF_MODE environment variable. - */ - $container['config'] = function ($c) { - // Grab any relevant dotenv variables from the .env file - try { - $dotenv = new Dotenv(\UserFrosting\APP_DIR); - $dotenv->load(); - } catch (InvalidPathException $e) { - // Skip loading the environment config file if it doesn't exist. - } - - // Get configuration mode from environment - $mode = getenv('UF_MODE') ?: ''; - - // Construct and load config repository - $builder = new ConfigPathBuilder($c->locator, 'config://'); - $loader = new ArrayFileLoader($builder->buildPaths($mode)); - $config = new Repository($loader->load()); - - // Construct base url from components, if not explicitly specified - if (!isset($config['site.uri.public'])) { - $uri = $c->request->getUri(); - - // Slim\Http\Uri likes to add trailing slashes when the path is empty, so this fixes that. - $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); - } - - // Hacky fix to prevent sessions from being hit too much: ignore CSRF middleware for requests for raw assets ;-) - // See https://github.com/laravel/framework/issues/8172#issuecomment-99112012 for more information on why it's bad to hit Laravel sessions multiple times in rapid succession. - $csrfBlacklist = $config['csrf.blacklist']; - $csrfBlacklist['^/' . $config['assets.raw.path']] = [ - 'GET' - ]; - - $config->set('csrf.blacklist', $csrfBlacklist); - - // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) - if (!$config['assets.use_raw']) { - $c->locator->resetScheme('assets'); - $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); - } - - return $config; - }; - - /** - * Initialize CSRF guard middleware. - * - * @see https://github.com/slimphp/Slim-Csrf - */ - $container['csrf'] = function ($c) { - $csrfKey = $c->config['session.keys.csrf']; - - // Workaround so that we can pass storage into CSRF guard. - // If we tried to directly pass the indexed portion of `session` (for example, $c->session['site.csrf']), - // we would get an 'Indirect modification of overloaded element of UserFrosting\Session\Session' error. - // If we tried to assign an array and use that, PHP would only modify the local variable, and not the session. - // Since ArrayObject is an object, PHP will modify the object itself, allowing it to persist in the session. - if (!$c->session->has($csrfKey)) { - $c->session[$csrfKey] = new \ArrayObject(); - } - $csrfStorage = $c->session[$csrfKey]; - - $onFailure = function ($request, $response, $next) { - $e = new BadRequestException("The CSRF code was invalid or not provided."); - $e->addUserMessage('CSRF_MISSING'); - throw $e; - - return $next($request, $response); - }; - - return new Guard($c->config['csrf.name'], $csrfStorage, $onFailure, $c->config['csrf.storage_limit'], $c->config['csrf.strength'], $c->config['csrf.persistent_token']); - }; - - /** - * Initialize Eloquent Capsule, which provides the database layer for UF. - * - * @todo construct the individual objects rather than using the facade - */ - $container['db'] = function ($c) { - $config = $c->config; - - $capsule = new Capsule; - - foreach ($config['db'] as $name => $dbConfig) { - $capsule->addConnection($dbConfig, $name); - } - - $queryEventDispatcher = new Dispatcher(new Container); - - $capsule->setEventDispatcher($queryEventDispatcher); - - // Register as global connection - $capsule->setAsGlobal(); - - // Start Eloquent - $capsule->bootEloquent(); - - if ($config['debug.queries']) { - $logger = $c->queryLogger; - - foreach ($config['db'] as $name => $dbConfig) { - $capsule->connection($name)->enableQueryLog(); - } - - // Register listener - $queryEventDispatcher->listen(QueryExecuted::class, function ($query) use ($logger) { - $logger->debug("Query executed on database [{$query->connectionName}]:", [ - 'query' => $query->sql, - 'bindings' => $query->bindings, - 'time' => $query->time . ' ms' - ]); - }); - } - - return $capsule; - }; - - /** - * Debug logging with Monolog. - * - * Extend this service to push additional handlers onto the 'debug' log stack. - */ - $container['debugLogger'] = function ($c) { - $logger = new Logger('debug'); - - $logFile = $c->locator->findResource('log://userfrosting.log', true, true); - - $handler = new StreamHandler($logFile); - - $formatter = new MixedFormatter(null, null, true); - - $handler->setFormatter($formatter); - $logger->pushHandler($handler); - - return $logger; - }; - - /** - * Custom error-handler for recoverable errors. - */ - $container['errorHandler'] = function ($c) { - $settings = $c->settings; - - $handler = new ExceptionHandlerManager($c, $settings['displayErrorDetails']); - - // Register the base HttpExceptionHandler. - $handler->registerHandler('\UserFrosting\Support\Exception\HttpException', '\UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler'); - - // Register the NotFoundExceptionHandler. - $handler->registerHandler('\UserFrosting\Support\Exception\NotFoundException', '\UserFrosting\Sprinkle\Core\Error\Handler\NotFoundExceptionHandler'); - - // Register the PhpMailerExceptionHandler. - $handler->registerHandler('\phpmailerException', '\UserFrosting\Sprinkle\Core\Error\Handler\PhpMailerExceptionHandler'); - - return $handler; - }; - - /** - * Error logging with Monolog. - * - * Extend this service to push additional handlers onto the 'error' log stack. - */ - $container['errorLogger'] = function ($c) { - $log = new Logger('errors'); - - $logFile = $c->locator->findResource('log://userfrosting.log', true, true); - - $handler = new StreamHandler($logFile, Logger::WARNING); - - $formatter = new LineFormatter(null, null, true); - - $handler->setFormatter($formatter); - $log->pushHandler($handler); - - return $log; - }; - - /** - * Factory service with FactoryMuffin. - * - * Provide access to factories for the rapid creation of objects for the purpose of testing - */ - $container['factory'] = function ($c) { - - // Get the path of all of the sprinkle's factories - $factoriesPath = $c->locator->findResources('factories://', true, true); - - // Create a new Factory Muffin instance - $fm = new FactoryMuffin(); - - // Load all of the model definitions - $fm->loadFactories($factoriesPath); - - // Set the locale. Could be the config one, but for testing English should do - Faker::setLocale('en_EN'); - - return $fm; - }; - - /** - * Builds search paths for locales in all Sprinkles. - */ - $container['localePathBuilder'] = function ($c) { - $config = $c->config; - $request = $c->request; - - // Make sure the locale config is a valid string - if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { - throw new \UnexpectedValueException('The locale config is not a valid string.'); - } - - // Get default locales as specified in configurations. - $locales = explode(',', $config['site.locales.default']); - - // Add supported browser preferred locales. - if ($request->hasHeader('Accept-Language')) { - $allowedLocales = []; - foreach (explode(',', $request->getHeaderLine('Accept-Language')) as $index => $browserLocale) { - // Split to access q - $parts = explode(';', $browserLocale) ?: []; - - // Ensure locale valid - if (array_key_exists(0, $parts)) { - // Format for UF's i18n - $parts[0] = str_replace('-', '_', $parts[0]); - // Ensure locale available - if (array_key_exists($parts[0], $config['site.locales.available'])) { - // Determine preference level, and add to $allowedLocales - if (array_key_exists(1, $parts)) { - $parts[1] = str_replace('q=', '', $parts[1]); - // Sanitize with int cast (bad values go to 0) - $parts[1] = (int)$parts[1]; - } else { - $parts[1] = 1; - } - // Add to list, and format for UF's i18n. - $allowedLocales[$parts[0]] = $parts[1]; - } - } - } - - // Sort, extract keys, and merge with $locales - asort($allowedLocales, SORT_NUMERIC); - $locales = array_merge($locales, array_keys($allowedLocales)); - - // Remove duplicates, while maintaining fallback order - $locales = array_reverse(array_unique(array_reverse($locales), SORT_STRING)); - } - - return new LocalePathBuilder($c->locator, 'locale://', $locales); - }; - - /** - * Mail service. - */ - $container['mailer'] = function ($c) { - $mailer = new Mailer($c->mailLogger, $c->config['mail']); - - // Use UF debug settings to override any service-specific log settings. - if (!$c->config['debug.smtp']) { - $mailer->getPhpMailer()->SMTPDebug = 0; - } - - return $mailer; - }; - - /** - * Mail logging service. - * - * PHPMailer will use this to log SMTP activity. - * Extend this service to push additional handlers onto the 'mail' log stack. - */ - $container['mailLogger'] = function ($c) { - $log = new Logger('mail'); - - $logFile = $c->locator->findResource('log://userfrosting.log', true, true); - - $handler = new StreamHandler($logFile); - $formatter = new LineFormatter(null, null, true); - - $handler->setFormatter($formatter); - $log->pushHandler($handler); - - return $log; - }; - - /** - * Migrator service. - * - * This service handles database migration operations - */ - $container['migrator'] = function ($c) { - $migrator = new Migrator( - $c->db, - new DatabaseMigrationRepository($c->db, $c->config['migrations.repository_table']), - new MigrationLocator($c->sprinkleManager, new Filesystem) - ); - - // Make sure repository exist - if (!$migrator->repositoryExists()) { - $migrator->getRepository()->createRepository(); - } - - return $migrator; - }; - - /** - * Error-handler for 404 errors. Notice that we manually create a UserFrosting NotFoundException, - * and a NotFoundExceptionHandler. This lets us pass through to the UF error handling system. - */ - $container['notFoundHandler'] = function ($c) { - return function ($request, $response) use ($c) { - $exception = new NotFoundException; - $handler = new NotFoundExceptionHandler($c, $request, $response, $exception, $c->settings['displayErrorDetails']); - return $handler->handle(); - }; - }; - - /** - * Error-handler for PHP runtime errors. Notice that we just pass this through to our general-purpose - * error-handling service. - */ - $container['phpErrorHandler'] = function ($c) { - return $c->errorHandler; - }; - - /** - * Laravel query logging with Monolog. - * - * Extend this service to push additional handlers onto the 'query' log stack. - */ - $container['queryLogger'] = function ($c) { - $logger = new Logger('query'); - - $logFile = $c->locator->findResource('log://userfrosting.log', true, true); - - $handler = new StreamHandler($logFile); - - $formatter = new MixedFormatter(null, null, true); - - $handler->setFormatter($formatter); - $logger->pushHandler($handler); - - return $logger; - }; - - /** - * Override Slim's default router with the UF router. - */ - $container['router'] = function ($c) { - $routerCacheFile = false; - if (isset($c->config['settings.routerCacheFile'])) { - $routerCacheFile = $c->config['settings.routerCacheFile']; - } - - return (new Router)->setCacheFile($routerCacheFile); - }; - - /** - * Start the PHP session, with the name and parameters specified in the configuration file. - */ - $container['session'] = function ($c) { - $config = $c->config; - - // Create appropriate handler based on config - if ($config['session.handler'] == 'file') { - $fs = new Filesystem; - $handler = new FileSessionHandler($fs, $c->locator->findResource('session://'), $config['session.minutes']); - } elseif ($config['session.handler'] == 'database') { - $connection = $c->db->connection(); - // Table must exist, otherwise an exception will be thrown - $handler = new DatabaseSessionHandler($connection, $config['session.database.table'], $config['session.minutes']); - } else { - throw new \Exception("Bad session handler type '{$config['session.handler']}' specified in configuration file."); - } - - // Create, start and return a new wrapper for $_SESSION - $session = new Session($handler, $config['session']); - $session->start(); - - return $session; - }; - - /** - * Request throttler. - * - * Throttles (rate-limits) requests of a predefined type, with rules defined in site config. - */ - $container['throttler'] = function ($c) { - $throttler = new Throttler($c->classMapper); - - $config = $c->config; - - if ($config->has('throttles') && ($config['throttles'] !== null)) { - foreach ($config['throttles'] as $type => $rule) { - if ($rule) { - $throttleRule = new ThrottleRule($rule['method'], $rule['interval'], $rule['delays']); - $throttler->addThrottleRule($type, $throttleRule); - } else { - $throttler->addThrottleRule($type, null); - } - } - } - - return $throttler; - }; - - /** - * Translation service, for translating message tokens. - */ - $container['translator'] = function ($c) { - // Load the translations - $paths = $c->localePathBuilder->buildPaths(); - $loader = new ArrayFileLoader($paths); - - // Create the $translator object - $translator = new MessageTranslator($loader->load()); - - return $translator; - }; - - /** - * Set up Twig as the view, adding template paths for all sprinkles and the Slim Twig extension. - * - * Also adds the UserFrosting core Twig extension, which provides additional functions, filters, global variables, etc. - */ - $container['view'] = function ($c) { - $templatePaths = $c->locator->findResources('templates://', true, true); - - $view = new Twig($templatePaths); - - $loader = $view->getLoader(); - - $sprinkles = $c->sprinkleManager->getSprinkleNames(); - - // Add Sprinkles' templates namespaces - foreach ($sprinkles as $sprinkle) { - $path = \UserFrosting\SPRINKLES_DIR . \UserFrosting\DS . - $sprinkle . \UserFrosting\DS . - \UserFrosting\TEMPLATE_DIR_NAME . \UserFrosting\DS; - - if (is_dir($path)) { - $loader->addPath($path, $sprinkle); - } - } - - $twig = $view->getEnvironment(); - - if ($c->config['cache.twig']) { - $twig->setCache($c->locator->findResource('cache://twig', true, true)); - } - - if ($c->config['debug.twig']) { - $twig->enableDebug(); - $view->addExtension(new \Twig_Extension_Debug()); - } - - // Register the Slim extension with Twig - $slimExtension = new TwigExtension( - $c->router, - $c->request->getUri() - ); - $view->addExtension($slimExtension); - - // Register the core UF extension with Twig - $coreExtension = new CoreExtension($c); - $view->addExtension($coreExtension); - - return $view; - }; - } -} +config; + + if ($config['alert.storage'] == 'cache') { + return new CacheAlertStream($config['alert.key'], $c->translator, $c->cache, $c->config); + } elseif ($config['alert.storage'] == 'session') { + return new SessionAlertStream($config['alert.key'], $c->translator, $c->session); + } else { + throw new \Exception("Bad alert storage handler type '{$config['alert.storage']}' specified in configuration file."); + } + }; + + /** + * Asset loader service + * + * Loads assets from a specified relative location. + * Assets are Javascript, CSS, image, and other files used by your site. + * + * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. + */ + $container['assetLoader'] = function ($c) { + $basePath = \UserFrosting\SPRINKLES_DIR; + $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; + + return new AssetLoader($basePath, $pattern); + }; + + /** + * Asset manager service. + * + * Loads raw or compiled asset information from your bundle.config.json schema file. + * Assets are Javascript, CSS, image, and other files used by your site. + */ + $container['assets'] = function ($c) { + $config = $c->config; + $locator = $c->locator; + + // Hacky way to clean up locator paths. + $locatorPaths = []; + foreach ($locator->getPaths('assets') as $pathSet) { + foreach ($pathSet as $path) { + $locatorPaths[] = $path; + } + } + + // Load asset schema + if ($config['assets.use_raw']) { + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; + + $sprinkles = $c->sprinkleManager->getSprinkleNames(); + + $prefixTransformer = new PrefixTransformer(); + $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); + $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); + + foreach ($sprinkles as $sprinkle) { + $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); + } + $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); + + // Load raw asset bundles for each Sprinkle. + + // Retrieve locations of raw asset bundle schemas that exist. + $bundleSchemas = $locator->findResources('sprinkles://' . $config['assets.raw.schema']); + + // Load asset bundle schemas that exist. + if (array_key_exists(0, $bundleSchemas)) { + $bundles = new RawAssetBundles(array_shift($bundleSchemas)); + + foreach ($bundleSchemas as $bundleSchema) { + $bundles->extend($bundleSchema); + } + + // Add bundles to asset manager. + $assets->addAssetBundles($bundles); + } + } else { + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; + $assets = new Assets($locator, 'assets', $baseUrl); + $assets->overrideBasePath($locator->getBase() . '/public/assets'); + + // Load compiled asset bundle. + $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); + } + + return $assets; + }; + + /** + * Cache service. + * + * @return \Illuminate\Cache\TaggedCache + */ + $container['cache'] = function ($c) { + + $config = $c->config; + + if ($config['cache.driver'] == 'file') { + $path = $c->locator->findResource('cache://', true, true); + $cacheStore = new TaggableFileStore($path); + } elseif ($config['cache.driver'] == 'memcached') { + // We need to inject the prefix in the memcached config + $config = array_merge($config['cache.memcached'], ['prefix' => $config['cache.prefix']]); + $cacheStore = new MemcachedStore($config); + } elseif ($config['cache.driver'] == 'redis') { + // We need to inject the prefix in the redis config + $config = array_merge($config['cache.redis'], ['prefix' => $config['cache.prefix']]); + $cacheStore = new RedisStore($config); + } else { + throw new \Exception("Bad cache store type '{$config['cache.driver']}' specified in configuration file."); + } + + return $cacheStore->instance(); + }; + + /** + * Middleware to check environment. + * + * @todo We should cache the results of this, the first time that it succeeds. + */ + $container['checkEnvironment'] = function ($c) { + $checkEnvironment = new CheckEnvironment($c->view, $c->locator, $c->cache); + return $checkEnvironment; + }; + + /** + * Class mapper. + * + * Creates an abstraction on top of class names to allow extending them in sprinkles. + */ + $container['classMapper'] = function ($c) { + $classMapper = new ClassMapper(); + $classMapper->setClassMapping('query_builder', 'UserFrosting\Sprinkle\Core\Database\Builder'); + $classMapper->setClassMapping('throttle', 'UserFrosting\Sprinkle\Core\Database\Models\Throttle'); + return $classMapper; + }; + + /** + * Site config service (separate from Slim settings). + * + * Will attempt to automatically determine which config file(s) to use based on the value of the UF_MODE environment variable. + */ + $container['config'] = function ($c) { + // Grab any relevant dotenv variables from the .env file + try { + $dotenv = new Dotenv(\UserFrosting\APP_DIR); + $dotenv->load(); + } catch (InvalidPathException $e) { + // Skip loading the environment config file if it doesn't exist. + } + + // Get configuration mode from environment + $mode = getenv('UF_MODE') ?: ''; + + // Construct and load config repository + $builder = new ConfigPathBuilder($c->locator, 'config://'); + $loader = new ArrayFileLoader($builder->buildPaths($mode)); + $config = new Repository($loader->load()); + + // Construct base url from components, if not explicitly specified + if (!isset($config['site.uri.public'])) { + $uri = $c->request->getUri(); + + // Slim\Http\Uri likes to add trailing slashes when the path is empty, so this fixes that. + $config['site.uri.public'] = trim($uri->getBaseUrl(), '/'); + } + + // Hacky fix to prevent sessions from being hit too much: ignore CSRF middleware for requests for raw assets ;-) + // See https://github.com/laravel/framework/issues/8172#issuecomment-99112012 for more information on why it's bad to hit Laravel sessions multiple times in rapid succession. + $csrfBlacklist = $config['csrf.blacklist']; + $csrfBlacklist['^/' . $config['assets.raw.path']] = [ + 'GET' + ]; + + $config->set('csrf.blacklist', $csrfBlacklist); + + // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) + if (!$config['assets.use_raw']) { + $c->locator->resetScheme('assets'); + $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); + } + + return $config; + }; + + /** + * Initialize CSRF guard middleware. + * + * @see https://github.com/slimphp/Slim-Csrf + */ + $container['csrf'] = function ($c) { + $csrfKey = $c->config['session.keys.csrf']; + + // Workaround so that we can pass storage into CSRF guard. + // If we tried to directly pass the indexed portion of `session` (for example, $c->session['site.csrf']), + // we would get an 'Indirect modification of overloaded element of UserFrosting\Session\Session' error. + // If we tried to assign an array and use that, PHP would only modify the local variable, and not the session. + // Since ArrayObject is an object, PHP will modify the object itself, allowing it to persist in the session. + if (!$c->session->has($csrfKey)) { + $c->session[$csrfKey] = new \ArrayObject(); + } + $csrfStorage = $c->session[$csrfKey]; + + $onFailure = function ($request, $response, $next) { + $e = new BadRequestException("The CSRF code was invalid or not provided."); + $e->addUserMessage('CSRF_MISSING'); + throw $e; + + return $next($request, $response); + }; + + return new Guard($c->config['csrf.name'], $csrfStorage, $onFailure, $c->config['csrf.storage_limit'], $c->config['csrf.strength'], $c->config['csrf.persistent_token']); + }; + + /** + * Initialize Eloquent Capsule, which provides the database layer for UF. + * + * @todo construct the individual objects rather than using the facade + */ + $container['db'] = function ($c) { + $config = $c->config; + + $capsule = new Capsule; + + foreach ($config['db'] as $name => $dbConfig) { + $capsule->addConnection($dbConfig, $name); + } + + $queryEventDispatcher = new Dispatcher(new Container); + + $capsule->setEventDispatcher($queryEventDispatcher); + + // Register as global connection + $capsule->setAsGlobal(); + + // Start Eloquent + $capsule->bootEloquent(); + + if ($config['debug.queries']) { + $logger = $c->queryLogger; + + foreach ($config['db'] as $name => $dbConfig) { + $capsule->connection($name)->enableQueryLog(); + } + + // Register listener + $queryEventDispatcher->listen(QueryExecuted::class, function ($query) use ($logger) { + $logger->debug("Query executed on database [{$query->connectionName}]:", [ + 'query' => $query->sql, + 'bindings' => $query->bindings, + 'time' => $query->time . ' ms' + ]); + }); + } + + return $capsule; + }; + + /** + * Debug logging with Monolog. + * + * Extend this service to push additional handlers onto the 'debug' log stack. + */ + $container['debugLogger'] = function ($c) { + $logger = new Logger('debug'); + + $logFile = $c->locator->findResource('log://userfrosting.log', true, true); + + $handler = new StreamHandler($logFile); + + $formatter = new MixedFormatter(null, null, true); + + $handler->setFormatter($formatter); + $logger->pushHandler($handler); + + return $logger; + }; + + /** + * Custom error-handler for recoverable errors. + */ + $container['errorHandler'] = function ($c) { + $settings = $c->settings; + + $handler = new ExceptionHandlerManager($c, $settings['displayErrorDetails']); + + // Register the base HttpExceptionHandler. + $handler->registerHandler('\UserFrosting\Support\Exception\HttpException', '\UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler'); + + // Register the NotFoundExceptionHandler. + $handler->registerHandler('\UserFrosting\Support\Exception\NotFoundException', '\UserFrosting\Sprinkle\Core\Error\Handler\NotFoundExceptionHandler'); + + // Register the PhpMailerExceptionHandler. + $handler->registerHandler('\phpmailerException', '\UserFrosting\Sprinkle\Core\Error\Handler\PhpMailerExceptionHandler'); + + return $handler; + }; + + /** + * Error logging with Monolog. + * + * Extend this service to push additional handlers onto the 'error' log stack. + */ + $container['errorLogger'] = function ($c) { + $log = new Logger('errors'); + + $logFile = $c->locator->findResource('log://userfrosting.log', true, true); + + $handler = new StreamHandler($logFile, Logger::WARNING); + + $formatter = new LineFormatter(null, null, true); + + $handler->setFormatter($formatter); + $log->pushHandler($handler); + + return $log; + }; + + /** + * Factory service with FactoryMuffin. + * + * Provide access to factories for the rapid creation of objects for the purpose of testing + */ + $container['factory'] = function ($c) { + + // Get the path of all of the sprinkle's factories + $factoriesPath = $c->locator->findResources('factories://', true, true); + + // Create a new Factory Muffin instance + $fm = new FactoryMuffin(); + + // Load all of the model definitions + $fm->loadFactories($factoriesPath); + + // Set the locale. Could be the config one, but for testing English should do + Faker::setLocale('en_EN'); + + return $fm; + }; + + /** + * Builds search paths for locales in all Sprinkles. + */ + $container['localePathBuilder'] = function ($c) { + $config = $c->config; + $request = $c->request; + + // Make sure the locale config is a valid string + if (!is_string($config['site.locales.default']) || $config['site.locales.default'] == '') { + throw new \UnexpectedValueException('The locale config is not a valid string.'); + } + + // Get default locales as specified in configurations. + $locales = explode(',', $config['site.locales.default']); + + // Add supported browser preferred locales. + if ($request->hasHeader('Accept-Language')) { + $allowedLocales = []; + foreach (explode(',', $request->getHeaderLine('Accept-Language')) as $index => $browserLocale) { + // Split to access q + $parts = explode(';', $browserLocale) ?: []; + + // Ensure locale valid + if (array_key_exists(0, $parts)) { + // Format for UF's i18n + $parts[0] = str_replace('-', '_', $parts[0]); + // Ensure locale available + if (array_key_exists($parts[0], $config['site.locales.available'])) { + // Determine preference level, and add to $allowedLocales + if (array_key_exists(1, $parts)) { + $parts[1] = str_replace('q=', '', $parts[1]); + // Sanitize with int cast (bad values go to 0) + $parts[1] = (int)$parts[1]; + } else { + $parts[1] = 1; + } + // Add to list, and format for UF's i18n. + $allowedLocales[$parts[0]] = $parts[1]; + } + } + } + + // Sort, extract keys, and merge with $locales + asort($allowedLocales, SORT_NUMERIC); + $locales = array_merge($locales, array_keys($allowedLocales)); + + // Remove duplicates, while maintaining fallback order + $locales = array_reverse(array_unique(array_reverse($locales), SORT_STRING)); + } + + return new LocalePathBuilder($c->locator, 'locale://', $locales); + }; + + /** + * Mail service. + */ + $container['mailer'] = function ($c) { + $mailer = new Mailer($c->mailLogger, $c->config['mail']); + + // Use UF debug settings to override any service-specific log settings. + if (!$c->config['debug.smtp']) { + $mailer->getPhpMailer()->SMTPDebug = 0; + } + + return $mailer; + }; + + /** + * Mail logging service. + * + * PHPMailer will use this to log SMTP activity. + * Extend this service to push additional handlers onto the 'mail' log stack. + */ + $container['mailLogger'] = function ($c) { + $log = new Logger('mail'); + + $logFile = $c->locator->findResource('log://userfrosting.log', true, true); + + $handler = new StreamHandler($logFile); + $formatter = new LineFormatter(null, null, true); + + $handler->setFormatter($formatter); + $log->pushHandler($handler); + + return $log; + }; + + /** + * Migrator service. + * + * This service handles database migration operations + */ + $container['migrator'] = function ($c) { + $migrator = new Migrator( + $c->db, + new DatabaseMigrationRepository($c->db, $c->config['migrations.repository_table']), + new MigrationLocator($c->sprinkleManager, new Filesystem) + ); + + // Make sure repository exist + if (!$migrator->repositoryExists()) { + $migrator->getRepository()->createRepository(); + } + + return $migrator; + }; + + /** + * Error-handler for 404 errors. Notice that we manually create a UserFrosting NotFoundException, + * and a NotFoundExceptionHandler. This lets us pass through to the UF error handling system. + */ + $container['notFoundHandler'] = function ($c) { + return function ($request, $response) use ($c) { + $exception = new NotFoundException; + $handler = new NotFoundExceptionHandler($c, $request, $response, $exception, $c->settings['displayErrorDetails']); + return $handler->handle(); + }; + }; + + /** + * Error-handler for PHP runtime errors. Notice that we just pass this through to our general-purpose + * error-handling service. + */ + $container['phpErrorHandler'] = function ($c) { + return $c->errorHandler; + }; + + /** + * Laravel query logging with Monolog. + * + * Extend this service to push additional handlers onto the 'query' log stack. + */ + $container['queryLogger'] = function ($c) { + $logger = new Logger('query'); + + $logFile = $c->locator->findResource('log://userfrosting.log', true, true); + + $handler = new StreamHandler($logFile); + + $formatter = new MixedFormatter(null, null, true); + + $handler->setFormatter($formatter); + $logger->pushHandler($handler); + + return $logger; + }; + + /** + * Override Slim's default router with the UF router. + */ + $container['router'] = function ($c) { + $routerCacheFile = false; + if (isset($c->config['settings.routerCacheFile'])) { + $routerCacheFile = $c->config['settings.routerCacheFile']; + } + + return (new Router)->setCacheFile($routerCacheFile); + }; + + /** + * Start the PHP session, with the name and parameters specified in the configuration file. + */ + $container['session'] = function ($c) { + $config = $c->config; + + // Create appropriate handler based on config + if ($config['session.handler'] == 'file') { + $fs = new Filesystem; + $handler = new FileSessionHandler($fs, $c->locator->findResource('session://'), $config['session.minutes']); + } elseif ($config['session.handler'] == 'database') { + $connection = $c->db->connection(); + // Table must exist, otherwise an exception will be thrown + $handler = new DatabaseSessionHandler($connection, $config['session.database.table'], $config['session.minutes']); + } else { + throw new \Exception("Bad session handler type '{$config['session.handler']}' specified in configuration file."); + } + + // Create, start and return a new wrapper for $_SESSION + $session = new Session($handler, $config['session']); + $session->start(); + + return $session; + }; + + /** + * Request throttler. + * + * Throttles (rate-limits) requests of a predefined type, with rules defined in site config. + */ + $container['throttler'] = function ($c) { + $throttler = new Throttler($c->classMapper); + + $config = $c->config; + + if ($config->has('throttles') && ($config['throttles'] !== null)) { + foreach ($config['throttles'] as $type => $rule) { + if ($rule) { + $throttleRule = new ThrottleRule($rule['method'], $rule['interval'], $rule['delays']); + $throttler->addThrottleRule($type, $throttleRule); + } else { + $throttler->addThrottleRule($type, null); + } + } + } + + return $throttler; + }; + + /** + * Translation service, for translating message tokens. + */ + $container['translator'] = function ($c) { + // Load the translations + $paths = $c->localePathBuilder->buildPaths(); + $loader = new ArrayFileLoader($paths); + + // Create the $translator object + $translator = new MessageTranslator($loader->load()); + + return $translator; + }; + + /** + * Set up Twig as the view, adding template paths for all sprinkles and the Slim Twig extension. + * + * Also adds the UserFrosting core Twig extension, which provides additional functions, filters, global variables, etc. + */ + $container['view'] = function ($c) { + $templatePaths = $c->locator->findResources('templates://', true, true); + + $view = new Twig($templatePaths); + + $loader = $view->getLoader(); + + $sprinkles = $c->sprinkleManager->getSprinkleNames(); + + // Add Sprinkles' templates namespaces + foreach ($sprinkles as $sprinkle) { + $path = \UserFrosting\SPRINKLES_DIR . \UserFrosting\DS . + $sprinkle . \UserFrosting\DS . + \UserFrosting\TEMPLATE_DIR_NAME . \UserFrosting\DS; + + if (is_dir($path)) { + $loader->addPath($path, $sprinkle); + } + } + + $twig = $view->getEnvironment(); + + if ($c->config['cache.twig']) { + $twig->setCache($c->locator->findResource('cache://twig', true, true)); + } + + if ($c->config['debug.twig']) { + $twig->enableDebug(); + $view->addExtension(new \Twig_Extension_Debug()); + } + + // Register the Slim extension with Twig + $slimExtension = new TwigExtension( + $c->router, + $c->request->getUri() + ); + $view->addExtension($slimExtension); + + // Register the core UF extension with Twig + $coreExtension = new CoreExtension($c); + $view->addExtension($coreExtension); + + return $view; + }; + } +} From a296034a5be6ce80910054f60bffa428be448cc7 Mon Sep 17 00:00:00 2001 From: Jordan Mele <=> Date: Fri, 12 Jan 2018 15:35:00 +1100 Subject: [PATCH 028/237] Bump jQuery version. --- app/sprinkles/core/package.json | 48 +++++++++---------- .../templates/pages/abstract/base.html.twig | 2 +- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/app/sprinkles/core/package.json b/app/sprinkles/core/package.json index 982a59385..892f55b4c 100644 --- a/app/sprinkles/core/package.json +++ b/app/sprinkles/core/package.json @@ -1,24 +1,24 @@ -{ - "private": true, - "dependencies": { - "bootstrap": "^3.3.6", - "clipboard": "^1.5.16", - "font-awesome": "^4.7.0", - "handlebars": "^3.0.3", - "jquery": "^2.2.4", - "jquery-ui": "^1.12.0", - "jquery-validation": "~1.14.0", - "select2": "^4.0.5", - "tablesorter": "^2.28.5", - "moment": "^2.17.1", - "speakingurl": "^11.0.0", - "icheck": "^1.0.1", - "jquery-slimscroll": "~1.3.8", - "fastclick": "^1.0.6", - "ionicons": "^2.0.1", - "urijs": "^1.18.4" - }, - "resolutions": { - "optimist": "0.6.1" - } -} +{ + "private": true, + "dependencies": { + "bootstrap": "^3.3.6", + "clipboard": "^1.5.16", + "font-awesome": "^4.7.0", + "handlebars": "^3.0.3", + "jquery": "^3.2.1", + "jquery-ui": "^1.12.0", + "jquery-validation": "~1.14.0", + "select2": "^4.0.5", + "tablesorter": "^2.28.5", + "moment": "^2.17.1", + "speakingurl": "^11.0.0", + "icheck": "^1.0.1", + "jquery-slimscroll": "~1.3.8", + "fastclick": "^1.0.6", + "ionicons": "^2.0.1", + "urijs": "^1.18.4" + }, + "resolutions": { + "optimist": "0.6.1" + } +} diff --git a/app/sprinkles/core/templates/pages/abstract/base.html.twig b/app/sprinkles/core/templates/pages/abstract/base.html.twig index 1fdd45aa0..359678d84 100644 --- a/app/sprinkles/core/templates/pages/abstract/base.html.twig +++ b/app/sprinkles/core/templates/pages/abstract/base.html.twig @@ -81,7 +81,7 @@ {# Override this block in a child layout template or page template to override site-level scripts. #} {% block scripts_site %} - + From c8b9ee3718d94bba489db6b194211b5e7d72312b Mon Sep 17 00:00:00 2001 From: Jordan Mele <=> Date: Fri, 12 Jan 2018 15:41:50 +1100 Subject: [PATCH 029/237] Explicitly marked package.json and package-lock.json as using lf line endings. --- .gitattributes | 7 ++++++- build/package-lock.json | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/.gitattributes b/.gitattributes index 7b46d28e7..35b742117 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,8 @@ # Forces Git to handle line endings, preventing any changes (like from editors or tools) being commited. # Also improves reliability of tools like Git Lens. -* text=auto \ No newline at end of file +* text=auto + +# NPM always rewrites package.json and package-lock.json to lf. +# This stops the annoying tendancy for false positive changes to appear under Windows. +package.json text=lf +package-lock.json text=lf \ No newline at end of file diff --git a/build/package-lock.json b/build/package-lock.json index 7d20b25e0..7c46a2860 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -1029,7 +1029,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -2222,7 +2222,7 @@ "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", "dev": true }, "http-signature": { @@ -3128,7 +3128,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -3187,7 +3187,7 @@ "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { "hosted-git-info": "2.5.0", @@ -3489,7 +3489,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "dev": true, "requires": { "asap": "2.0.6" @@ -3518,7 +3518,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "dev": true, "requires": { "is-number": "3.0.0", @@ -3839,7 +3839,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, "semver": { @@ -4094,7 +4094,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -4109,7 +4109,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -4142,7 +4142,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -4157,7 +4157,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -4292,7 +4292,7 @@ "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", "dev": true, "optional": true }, From e634c5da0f11625e4400f38bc6babafc7a872903 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 13 Jan 2018 18:26:23 -0500 Subject: [PATCH 030/237] Fix assets onColision issue --- app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 2 +- app/sprinkles/core/src/Util/RawAssetBundles.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index a211244c9..67693b369 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -144,7 +144,7 @@ public function register(ContainerInterface $container) // Load raw asset bundles for each Sprinkle. // Retrieve locations of raw asset bundle schemas that exist. - $bundleSchemas = $locator->findResources('sprinkles://' . $config['assets.raw.schema']); + $bundleSchemas = array_reverse($locator->findResources('sprinkles://' . $config['assets.raw.schema'])); // Load asset bundle schemas that exist. if (array_key_exists(0, $bundleSchemas)) { diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index 0ed207774..b9c958a21 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -23,7 +23,7 @@ class RawAssetBundles extends GulpBundleAssetsRawBundles { * Extends the currently loaded bundles with another bundle schema. * * @param string - * + * * @throws FileNotFoundException if file cannot be found. * @throws JsonException if file cannot be parsed as JSON. * @throws InvalidBundlesFileException if unexpected value encountered. @@ -41,7 +41,7 @@ public function extend($filePath) if (isset($bundlesFile->bundle)) { foreach ($bundlesFile->bundle as $bundleName => $bundle) { // Get collision setting. - $collisionRule = (isset($bundle->options->sprinkle->onCollision) ?: 'replace'); + $collisionRule = ($bundle->options->sprinkle->onCollision ?: 'replace'); // Handle CSS bundle if specified. if (isset($bundle->styles)) { From 97b105eb15a3a51de6e6c40cdc600c4f6c89b66a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 13 Jan 2018 20:23:46 -0500 Subject: [PATCH 031/237] Add missing import --- app/sprinkles/core/src/Util/RawAssetBundles.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index b9c958a21..561a9c431 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -9,6 +9,7 @@ namespace UserFrosting\Sprinkle\Core\Util; use UserFrosting\Assets\AssetBundles\GulpBundleAssetsRawBundles; +use UserFrosting\Assets\Exception\InvalidBundlesFileException; /** * RawAssetBundles Class @@ -17,15 +18,15 @@ * * @author Alex Weissman (https://alexanderweissman.com) */ -class RawAssetBundles extends GulpBundleAssetsRawBundles { + class RawAssetBundles extends GulpBundleAssetsRawBundles { /** * Extends the currently loaded bundles with another bundle schema. * - * @param string + * @param string $filePath * - * @throws FileNotFoundException if file cannot be found. - * @throws JsonException if file cannot be parsed as JSON. + * @throws \UserFrosting\Support\Exception\FileNotFoundException if file cannot be found. + * @throws \UserFrosting\Support\Exception\JsonException if file cannot be parsed as JSON. * @throws InvalidBundlesFileException if unexpected value encountered. */ public function extend($filePath) From b24f56691a317b869b3346ced64a8d6bea499af2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 13 Jan 2018 21:52:15 -0500 Subject: [PATCH 032/237] Fix issue with CacheAlertStream --- app/sprinkles/core/src/Alert/CacheAlertStream.php | 8 ++++---- .../core/src/ServicesProvider/ServicesProvider.php | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/sprinkles/core/src/Alert/CacheAlertStream.php b/app/sprinkles/core/src/Alert/CacheAlertStream.php index a2a27fe5b..1fd51316a 100644 --- a/app/sprinkles/core/src/Alert/CacheAlertStream.php +++ b/app/sprinkles/core/src/Alert/CacheAlertStream.php @@ -7,7 +7,7 @@ */ namespace UserFrosting\Sprinkle\Core\Alert; -use Illuminate\Cache\TaggedCache; +use Illuminate\Cache\Repository as Cache; use UserFrosting\I18n\MessageTranslator; use UserFrosting\Support\Repository\Repository; @@ -23,7 +23,7 @@ class CacheAlertStream extends AlertStream { /** - * @var TaggedCache Object We use the cache object so that added messages will automatically appear in the cache. + * @var Cache Object We use the cache object so that added messages will automatically appear in the cache. */ protected $cache; @@ -37,10 +37,10 @@ class CacheAlertStream extends AlertStream * * @param string $messagesKey Store the messages under this key * @param MessageTranslator|null $translator - * @param TaggedCache $cache + * @param Cache $cache * @param Repository $config */ - public function __construct($messagesKey, MessageTranslator $translator = null, TaggedCache $cache, Repository $config) + public function __construct($messagesKey, MessageTranslator $translator = null, Cache $cache, Repository $config) { $this->cache = $cache; $this->config = $config; diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index a211244c9..6af776d63 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -172,7 +172,7 @@ public function register(ContainerInterface $container) /** * Cache service. * - * @return \Illuminate\Cache\TaggedCache + * @return \Illuminate\Cache\Repository */ $container['cache'] = function ($c) { From f34240bd730e5fa434d121e146ac72222f9741db Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Wed, 17 Jan 2018 15:21:21 +1100 Subject: [PATCH 033/237] Improved `build-build` reliability. -`assets` dir is optional in Sprinkles, so check. - Delete `yarn.lock` to ensure vendor assets get updated. --- build/gulpfile.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 90fe615bf..995d6fac2 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -61,8 +61,8 @@ gulp.task('assets-install', () => { if (yarnPaths.length > 0) { // Yes there are! - // Delete old package.json - del.sync('../app/assets/package.json', { force: true }); + // Delete old package.json and yarn.lock + del.sync(['../app/assets/package.json', '../app/assets/yarn.lock'], { force: true }); // Generate package.json let yarnTemplate = {// Private makes sure it isn't published, and cuts out a lot of unnecessary fields. @@ -87,7 +87,8 @@ gulp.task('assets-install', () => { } else del.sync([ '../app/assets/package.json', - '../app/assets/node_modules/' + '../app/assets/node_modules/', + '../app/assets/yarn.lock' ], { force: true }); // See if there are any bower packages. @@ -224,10 +225,8 @@ gulp.task('bundle-build', () => { // Copy sprinkle assets paths = []; for (let sprinkle of sprinkles) { - paths.push(`../app/sprinkles/${sprinkle}/assets/`); - } - for (let path of paths) { - fs.copySync(path, '../public/assets/', { overwrite: true }); + let path = `../app/sprinkles/${sprinkle}/assets/`; + if (fs.pathExistsSync(path)) fs.copySync(path, publicAssetsDir, { overwrite: true }); } return; }); From 27fc69ac6be8b3435764f088802ecf50c207d2d5 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 17 Jan 2018 20:53:28 -0500 Subject: [PATCH 034/237] Add basic seeder (Ref #778) --- app/sprinkles/core/src/Bakery/SeedCommand.php | 107 ++++++++++++++++++ .../core/src/Database/Seeder/Seeder.php | 42 +++++++ .../src/Database/Seeder/SeederInterface.php | 18 +++ app/sprinkles/core/src/Util/ClassFinder.php | 78 +++++++++++++ 4 files changed, 245 insertions(+) create mode 100644 app/sprinkles/core/src/Bakery/SeedCommand.php create mode 100644 app/sprinkles/core/src/Database/Seeder/Seeder.php create mode 100644 app/sprinkles/core/src/Database/Seeder/SeederInterface.php create mode 100644 app/sprinkles/core/src/Util/ClassFinder.php diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php new file mode 100644 index 000000000..5a32dbd08 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -0,0 +1,107 @@ +setName('seed') + ->setDescription('Seed the database with records') + ->setHelp('This command runs a seed to populate the database with default, random and/or test data.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') + ->addOption('class', null, InputOption::VALUE_REQUIRED, 'The class name of the seeder'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title("UserFrosting's Seeder"); + + // Get options + $className = $input->getOption('class'); + + // If there's no class in option, we abort + if (is_null($className) || $className == "") { + $this->io->error('No class selected. You must use the `--class` option.'); + exit(1); + } + + // Get the class instance + $seed = $this->getSeed($className); + + // Display the class we are going to use as info + $this->io->writeln("Seeding class `".get_class($seed)."`"); + + // Confirm action when in production mode + if (!$this->confirmToProceed($input->getOption('force'))) { + exit(1); + } + + // Run seed + try { + $seed->run(); + } catch (\Exception $e) { + $this->io->error($e->getMessage()); + exit(1); + } + + // Success + $this->io->success('Seed successful !'); + } + + /** + * Setup migrator and the shared options between other command + * + * @param string $name The seeder name + * @return mixed The seeder class instance + */ + protected function getSeed($name) + { + $finder = new ClassFinder($this->ci->sprinkleManager); + + try { + $class = $finder->getClass("Database\\Seeder\\$name"); + } catch (\Exception $e) { + $this->io->error($e->getMessage()); + exit(1); + } + + $seedClass = new $class($this->ci); + + // Class must be an instance of `SeederInterface` + if (!$seedClass instanceof SeederInterface) { + $this->io->error('Seed class must be an instance of `SeederInterface`'); + exit(1); + } + + return $seedClass; + } +} diff --git a/app/sprinkles/core/src/Database/Seeder/Seeder.php b/app/sprinkles/core/src/Database/Seeder/Seeder.php new file mode 100644 index 000000000..75ad9b24e --- /dev/null +++ b/app/sprinkles/core/src/Database/Seeder/Seeder.php @@ -0,0 +1,42 @@ +ci = $ci; + } + + /** + * Function used to execute the seed + * + * @return void + */ + abstract public function run(); +} diff --git a/app/sprinkles/core/src/Database/Seeder/SeederInterface.php b/app/sprinkles/core/src/Database/Seeder/SeederInterface.php new file mode 100644 index 000000000..bbcc13bc7 --- /dev/null +++ b/app/sprinkles/core/src/Database/Seeder/SeederInterface.php @@ -0,0 +1,18 @@ +sprinkleManager = $sprinkleManager; + } + + /** + * Finds a class across sprinkles. Will return the first instance found + * while respecting the sprinkle load order. Search is done after the `src/` + * dir. So to find `UserFrosting\Sprinkle\Core\Database\Models\Users`, + * search for `\Database\Models\Users` + * + * @param string $className The class name to find, including path inside `src/` + * @return string The fully qualified classname + * @throws \Exception If class not found + */ + public function getClass($className) + { + $sprinkles = $this->getSprinkles(); + foreach ($sprinkles as $sprinkle) { + + // Format the sprinkle name for the namespace + $sprinkle = Str::studly($sprinkle); + + // Build the class name and namespace + $class = "\\UserFrosting\\Sprinkle\\$sprinkle\\$className"; + + // Check if class exist. + if (class_exists($class)) { + return $class; + } + } + + //No class if found. Throw Exception + $sprinklesString = implode(", ", $sprinkles); + throw new \Exception("Class $className not found in sprinkles [$sprinklesString]"); + } + + /** + * Return an array of sprinkles respecting the load order + * + * @return array + */ + protected function getSprinkles() + { + $sprinkles = $this->sprinkleManager->getSprinkleNames(); + return array_reverse($sprinkles); + } +} From 7e037936ed38a508b91aa9604939c987a41044b2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 17 Jan 2018 22:39:29 -0500 Subject: [PATCH 035/237] [SeedCommand] Changed class option for array argument --- app/sprinkles/core/src/Bakery/SeedCommand.php | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index 5a32dbd08..14d424aa6 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -34,8 +34,8 @@ protected function configure() $this->setName('seed') ->setDescription('Seed the database with records') ->setHelp('This command runs a seed to populate the database with default, random and/or test data.') - ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') - ->addOption('class', null, InputOption::VALUE_REQUIRED, 'The class name of the seeder'); + ->addArgument('class', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'The class name of the seeder. Separate multiple seeder with a space.') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.'); } /** @@ -46,14 +46,25 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->title("UserFrosting's Seeder"); // Get options - $className = $input->getOption('class'); + $classes = $input->getArgument('class'); - // If there's no class in option, we abort - if (is_null($className) || $className == "") { - $this->io->error('No class selected. You must use the `--class` option.'); - exit(1); + foreach ($classes as $className) { + $this->runSeed($className, $input); } + // Success + $this->io->success('Seed successful !'); + } + + /** + * Run seed + * + * @param string $className Seed classname (argument from console) + * @param InputInterface $input + * @return void + */ + protected function runSeed($className, InputInterface $input) + { // Get the class instance $seed = $this->getSeed($className); @@ -65,6 +76,11 @@ protected function execute(InputInterface $input, OutputInterface $output) exit(1); } + // TODO :: + // - Disable Model guarded policy + // - Create seeder:list command/options + // - Create default seeds list/service + // Run seed try { $seed->run(); @@ -72,9 +88,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->error($e->getMessage()); exit(1); } - - // Success - $this->io->success('Seed successful !'); } /** From 03a72a7b0cabdbeedd89e247511803ce14082f0e Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 17 Jan 2018 23:01:38 -0500 Subject: [PATCH 036/237] Warning was at the wrong place. --- app/sprinkles/core/src/Bakery/SeedCommand.php | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index 14d424aa6..cdf22d52c 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -48,28 +48,21 @@ protected function execute(InputInterface $input, OutputInterface $output) // Get options $classes = $input->getArgument('class'); + // Seeds list + $seeds = []; + + // Start by gettings seeds foreach ($classes as $className) { - $this->runSeed($className, $input); - } - // Success - $this->io->success('Seed successful !'); - } + // Get seed class and + $seed = $this->getSeed($className); - /** - * Run seed - * - * @param string $className Seed classname (argument from console) - * @param InputInterface $input - * @return void - */ - protected function runSeed($className, InputInterface $input) - { - // Get the class instance - $seed = $this->getSeed($className); + // Display the class we are going to use as info + $this->io->writeln("Seeding class `".get_class($seed)."`"); - // Display the class we are going to use as info - $this->io->writeln("Seeding class `".get_class($seed)."`"); + // Add seed class to list + $seeds[] = $seed; + } // Confirm action when in production mode if (!$this->confirmToProceed($input->getOption('force'))) { @@ -81,13 +74,18 @@ protected function runSeed($className, InputInterface $input) // - Create seeder:list command/options // - Create default seeds list/service - // Run seed - try { - $seed->run(); - } catch (\Exception $e) { - $this->io->error($e->getMessage()); - exit(1); + // Run seeds + foreach ($seeds as $seed) { + try { + $seed->run(); + } catch (\Exception $e) { + $this->io->error($e->getMessage()); + exit(1); + } } + + // Success + $this->io->success('Seed successful !'); } /** From 283166ac57329bd5a4ff623a3b4209417745f8ef Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 17 Jan 2018 23:24:51 -0500 Subject: [PATCH 037/237] Updated `fs-extra` dependency Avoid error in CLI when running `php bakery build-assets` twice in a row in production mode. --- build/package-lock.json | 21 +++++++++++++++++---- build/package.json | 2 +- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/build/package-lock.json b/build/package-lock.json index 7c46a2860..578b661b1 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -9,12 +9,25 @@ "dev": true, "requires": { "chalk": "2.3.0", - "fs-extra": "4.0.2", + "fs-extra": "4.0.3", "lodash": "4.17.4", "node-exceptions": "2.0.2", "package-json-validator": "0.6.2", "semver": "5.4.1", "semver-intersect": "1.1.2" + }, + "dependencies": { + "fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + } } }, "accord": { @@ -966,9 +979,9 @@ "dev": true }, "fs-extra": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", - "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", "dev": true, "requires": { "graceful-fs": "4.1.11", diff --git a/build/package.json b/build/package.json index 6cfae3c9b..8a2bbc80c 100755 --- a/build/package.json +++ b/build/package.json @@ -5,7 +5,7 @@ "bower": "^1.8.0", "del": "^2.2.2", "dotenv": "^4.0.0", - "fs-extra": "^4.0.0", + "fs-extra": "^5.0.0", "gulp": "^3.9.1", "gulp-load-plugins": "^1.4.0", "gulp-uf-bundle-assets": "^2.27.2", From 5710058f5f2687b6eb2ecebc475cef6b0ddfaaa8 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 21 Jan 2018 00:23:13 -0500 Subject: [PATCH 038/237] Hide table filter row and pager when printing --- .../core/assets/userfrosting/css/userfrosting.css | 7 +++++++ .../core/templates/tables/table-paginated.html.twig | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/assets/userfrosting/css/userfrosting.css b/app/sprinkles/core/assets/userfrosting/css/userfrosting.css index 38a92e29d..149688196 100644 --- a/app/sprinkles/core/assets/userfrosting/css/userfrosting.css +++ b/app/sprinkles/core/assets/userfrosting/css/userfrosting.css @@ -202,3 +202,10 @@ a .info-box { left: 0; } } + +/* Hide table filter row when printing */ +@media print { + .tablesorter-filter-row { + display: none !important; + } +} \ No newline at end of file diff --git a/app/sprinkles/core/templates/tables/table-paginated.html.twig b/app/sprinkles/core/templates/tables/table-paginated.html.twig index 5b9412052..cfe32e173 100644 --- a/app/sprinkles/core/templates/tables/table-paginated.html.twig +++ b/app/sprinkles/core/templates/tables/table-paginated.html.twig @@ -34,7 +34,7 @@ {% endblock %} {% block table_pager_controls %} -
+
{# this can be any element, including an input #} From 83b93573c3a0bc51343702b9af66b9821d2867c8 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 21 Jan 2018 01:28:22 -0500 Subject: [PATCH 039/237] Added `.ufTable('update')` method --- app/sprinkles/core/assets/userfrosting/js/uf-table.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/sprinkles/core/assets/userfrosting/js/uf-table.js b/app/sprinkles/core/assets/userfrosting/js/uf-table.js index 77aa30a42..06a186692 100644 --- a/app/sprinkles/core/assets/userfrosting/js/uf-table.js +++ b/app/sprinkles/core/assets/userfrosting/js/uf-table.js @@ -85,6 +85,7 @@ * == METHODS == * * `getTableStateVars( table )`: fetches the current page size, page number, sort order, sort field, and column filters. + * `refresh`: reload the table data * * UserFrosting https://www.userfrosting.com * @author Alexander Weissman @@ -414,6 +415,13 @@ return filterList; }; + /** + * Refresh the table + */ + Plugin.prototype.refresh = function() { + this.ts.trigger('pagerUpdate'); + }; + /** * Generate the AJAX url. * Used as the default callback for pager_customAjaxUrl @@ -433,6 +441,7 @@ return url; }; + /** * Process data returned from the AJAX request and rendering the table cells. * Used as the default callback for pager_ajaxProcessing From 7e59ba45c2457b4b6e16d2991cb8d0e40328efd6 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 2 Feb 2018 15:45:27 +1100 Subject: [PATCH 040/237] Usable error duplicate frontend dependencies --- build/gulpfile.js | 22 +++++++++--- build/package-lock.json | 78 ++++++++++++++++++++--------------------- build/package.json | 2 +- 3 files changed, 58 insertions(+), 44 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 995d6fac2..372ffca25 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -66,8 +66,7 @@ gulp.task('assets-install', () => { // Generate package.json let yarnTemplate = {// Private makes sure it isn't published, and cuts out a lot of unnecessary fields. - private: true, - flat: true + private: true }; logger('\nMerging packages...\n'); mergePkg.yarn(yarnTemplate, yarnPaths, '../app/assets/', doILog); @@ -76,14 +75,29 @@ gulp.task('assets-install', () => { // Yarn automatically removes extraneous packages. // Perform installation. + // --flat switch cannot be used due to spotty support of --non-interactive switch + // Thankfully, "resolutions" works outside flat mode. logger('Installing npm/yarn assets...'); - let childProcess = require('child_process'); - childProcess.execSync('yarn install --flat --no-lockfile --non-interactive', { + require('child_process').execSync('yarn install --non-interactive', { cwd: '../app/assets', preferLocal: true,// Local over PATH. localDir: './node_modules/.bin', stdio: doILog ? 'inherit' : '' }); + + // Ensure dependency tree is flat manually because Yarn errors out with a TTY error. + logger('\nInspecting dependency tree...\n') + + if (!mergePkg.yarnIsFlat('../app/assets/', doILog)) { + logger(` +Dependency tree is not flat! Dependencies must be flat to prevent abnormal behavior. +Recommended solution is to adjust dependency versions until issue is resolved to ensure 100% compatibility. +Alternatively, resolutions can be used as an override, as documented at https://yarnpkg.com/en/docs/selective-version-resolutions +`); + throw 'Dependency tree is not flat!'; + } else { + logger('\nDependency tree is flat and usable.\n') + } } else del.sync([ '../app/assets/package.json', diff --git a/build/package-lock.json b/build/package-lock.json index 578b661b1..cdcebb263 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -3,33 +3,57 @@ "lockfileVersion": 1, "dependencies": { "@userfrosting/merge-package-dependencies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.1.0.tgz", - "integrity": "sha512-xgJ95NM2uhDWIzXMb6AjxIU9tJaclE5HhQEOArqSGQ34p1JqtuMzLNdESW+5vzqrenJvoToqp1a5wV4Oym1f4g==", + "version": "1.2.0-rc.1", + "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.0-rc.1.tgz", + "integrity": "sha512-slNx8WLIQXFtXQtxEQ6toG72dlk0Yb9kPSkLWvZ3LEMyHpnvAUHNgCkPmEHB0dttt8woQIXfYCG1+dxNbcxV9A==", "dev": true, "requires": { + "@yarnpkg/lockfile": "file:node_modules/@userfrosting/merge-package-dependencies/node_modules_bundled/@yarnpkg/lockfile", "chalk": "2.3.0", - "fs-extra": "4.0.3", + "fs-extra": "5.0.0", "lodash": "4.17.4", - "node-exceptions": "2.0.2", - "package-json-validator": "0.6.2", - "semver": "5.4.1", - "semver-intersect": "1.1.2" + "node-exceptions": "3.0.0", + "package-json-validator": "0.6.3", + "semver": "5.5.0", + "semver-intersect": "1.3.0" }, "dependencies": { - "fs-extra": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", - "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "node-exceptions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-3.0.0.tgz", + "integrity": "sha512-pFhMAqdN1avrFwtZs66HxYiVnbnH9wjXB4m8IKs5Z9+r7U5voqxT+EDbVkRfge+V7JnkOgKhN4HfKBn1o5g9Wg==", + "dev": true + }, + "package-json-validator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.3.tgz", + "integrity": "sha512-juKiFboV4UKUvWQ+OSxstnyukhuluyuEoFmgZw1Rx21XzmwlgDWLcbl3qzjA3789IRORYhVFs7cmAO0YFGwHCg==", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.1" + "optimist": "0.6.1" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "semver-intersect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.0.tgz", + "integrity": "sha512-923f1TGXGb2+OCkLvsmNPijmurMQxEMFOhC80N4NL8/Jo5rBKufHZ3sBtJJ7GNhh4RhdsB6+vj+6W68kmr43Lg==", + "dev": true, + "requires": { + "semver": "5.5.0" } } } }, + "@yarnpkg/lockfile": { + "version": "file:node_modules/@userfrosting/merge-package-dependencies/node_modules_bundled/@yarnpkg/lockfile", + "dev": true + }, "accord": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/accord/-/accord-0.23.0.tgz", @@ -3191,12 +3215,6 @@ "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", "dev": true }, - "node-exceptions": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-2.0.2.tgz", - "integrity": "sha512-nILccFLvnaOBoKZZtWfZipn/hlThZOT6UJOLX6SA3yLMYPcvLTIF26PXx73sPnAg45p05iYFYw2jvayNHz4rDA==", - "dev": true - }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -3335,15 +3353,6 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "package-json-validator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.2.tgz", - "integrity": "sha512-B4eikrIIhxheXKkIW7GR6Se4mtqegZ/x8jUDh6hHW4jYBz9HFXUejpPEUAsuplxpDtVdPsXT3ZMRTH1HizJV1Q==", - "dev": true, - "requires": { - "optimist": "0.6.1" - } - }, "parse-filepath": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", @@ -3861,15 +3870,6 @@ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, - "semver-intersect": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.1.2.tgz", - "integrity": "sha1-sLKLV1Ggf/3QAuXsYGyS1XbMtWE=", - "dev": true, - "requires": { - "semver": "5.4.1" - } - }, "sequencify": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", diff --git a/build/package.json b/build/package.json index 8a2bbc80c..b69b313b0 100755 --- a/build/package.json +++ b/build/package.json @@ -1,7 +1,7 @@ { "private": true, "devDependencies": { - "@userfrosting/merge-package-dependencies": "^1.1.0", + "@userfrosting/merge-package-dependencies": "^1.2.0-rc.1", "bower": "^1.8.0", "del": "^2.2.2", "dotenv": "^4.0.0", From 768b20fecd10c985679381ded6bff84ac1fcb765 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 2 Feb 2018 16:37:49 +1100 Subject: [PATCH 041/237] Backported important fixes from develop - 7e59ba45c2457b4b6e16d2991cb8d0e40328efd6 - f34240bd730e5fa434d121e146ac72222f9741 - 283166ac57329bd5a4ff623a3b4209417745f8ef - e634c5da0f11625e4400f38bc6babafc7a872903 - a296034a5be6ce80910054f60bffa428be448cc7 --- app/sprinkles/core/package.json | 2 +- .../core/src/Util/RawAssetBundles.php | 2 +- .../core/templates/layouts/basic.html.twig | 2 +- build/gulpfile.js | 35 ++++-- build/package-lock.json | 118 +++++++++++------- build/package.json | 4 +- 6 files changed, 100 insertions(+), 63 deletions(-) diff --git a/app/sprinkles/core/package.json b/app/sprinkles/core/package.json index 992922482..09d2c6e72 100644 --- a/app/sprinkles/core/package.json +++ b/app/sprinkles/core/package.json @@ -5,7 +5,7 @@ "clipboard": "^1.5.16", "font-awesome": "^4.7.0", "handlebars": "^3.0.3", - "jquery": "^2.2.4", + "jquery": "^3.3.1", "jquery-ui": "^1.12.0", "jquery-validation": "~1.14.0", "select2": "^4.0.3", diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index 0ed207774..b4017de01 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -41,7 +41,7 @@ public function extend($filePath) if (isset($bundlesFile->bundle)) { foreach ($bundlesFile->bundle as $bundleName => $bundle) { // Get collision setting. - $collisionRule = (isset($bundle->options->sprinkle->onCollision) ?: 'replace'); + $collisionRule = ($bundle->options->sprinkle->onCollision ?: 'replace'); // Handle CSS bundle if specified. if (isset($bundle->styles)) { diff --git a/app/sprinkles/core/templates/layouts/basic.html.twig b/app/sprinkles/core/templates/layouts/basic.html.twig index dac8195bd..d1f5329ab 100644 --- a/app/sprinkles/core/templates/layouts/basic.html.twig +++ b/app/sprinkles/core/templates/layouts/basic.html.twig @@ -81,7 +81,7 @@ {# Override this block in a child layout template or page template to override site-level scripts. #} {% block scripts_site %} - + diff --git a/build/gulpfile.js b/build/gulpfile.js index 7d6fba7c9..86b49ba67 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -61,13 +61,12 @@ gulp.task('assets-install', () => { if (yarnPaths.length > 0) { // Yes there are! - // Delete old package.json - del.sync('../app/assets/package.json', { force: true }); + // Delete old package.json and yarn.lock + del.sync(['../app/assets/package.json', '../app/assets/yarn.lock'], { force: true }); // Generate package.json let yarnTemplate = {// Private makes sure it isn't published, and cuts out a lot of unnecessary fields. - private: true, - flat: true + private: true }; logger('\nMerging packages...\n'); mergePkg.yarn(yarnTemplate, yarnPaths, '../app/assets/', doILog); @@ -76,16 +75,32 @@ gulp.task('assets-install', () => { // Yarn automatically removes extraneous packages. // Perform installation. + // --flat switch cannot be used due to spotty support of --non-interactive switch + // Thankfully, "resolutions" works outside flat mode. logger('Installing npm/yarn assets...'); - let childProcess = require('child_process'); - childProcess.execSync('yarn install --flat --no-lockfile --non-interactive', { + require('child_process').execSync('yarn install --non-interactive', { cwd: '../app/assets', stdio: doILog ? 'inherit' : '' }); + + // Ensure dependency tree is flat manually because Yarn errors out with a TTY error. + logger('\nInspecting dependency tree...\n'); + + if (!mergePkg.yarnIsFlat('../app/assets/', doILog)) { + logger(` +Dependency tree is not flat! Dependencies must be flat to prevent abnormal behavior. +Recommended solution is to adjust dependency versions until issue is resolved to ensure 100% compatibility. +Alternatively, resolutions can be used as an override, as documented at https://yarnpkg.com/en/docs/selective-version-resolutions +`); + throw 'Dependency tree is not flat!'; + } else { + logger('\nDependency tree is flat and usable.\n'); + } } else del.sync([ '../app/assets/package.json', - '../app/assets/node_modules/**' + '../app/assets/node_modules/', + '../app/assets/yarn.lock' ], { force: true }); // See if there are any bower packages. @@ -217,10 +232,8 @@ gulp.task('bundle-build', () => { // Copy sprinkle assets paths = []; for (let sprinkle of sprinkles) { - paths.push(`../app/sprinkles/${sprinkle}/assets/`); - } - for (let path of paths) { - fs.copySync(path, '../public/assets/', { overwrite: true }); + let path = `../app/sprinkles/${sprinkle}/assets/`; + if (fs.pathExistsSync(path)) fs.copySync(path, publicAssetsDir, { overwrite: true }); } return; }); diff --git a/build/package-lock.json b/build/package-lock.json index 7d20b25e0..51e1b875a 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -3,20 +3,68 @@ "lockfileVersion": 1, "dependencies": { "@userfrosting/merge-package-dependencies": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.1.0.tgz", - "integrity": "sha512-xgJ95NM2uhDWIzXMb6AjxIU9tJaclE5HhQEOArqSGQ34p1JqtuMzLNdESW+5vzqrenJvoToqp1a5wV4Oym1f4g==", + "version": "1.2.0-rc.1", + "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.0-rc.1.tgz", + "integrity": "sha512-slNx8WLIQXFtXQtxEQ6toG72dlk0Yb9kPSkLWvZ3LEMyHpnvAUHNgCkPmEHB0dttt8woQIXfYCG1+dxNbcxV9A==", "dev": true, "requires": { + "@yarnpkg/lockfile": "file:node_modules/@userfrosting/merge-package-dependencies/node_modules_bundled/@yarnpkg/lockfile", "chalk": "2.3.0", - "fs-extra": "4.0.2", + "fs-extra": "5.0.0", "lodash": "4.17.4", - "node-exceptions": "2.0.2", - "package-json-validator": "0.6.2", - "semver": "5.4.1", - "semver-intersect": "1.1.2" + "node-exceptions": "3.0.0", + "package-json-validator": "0.6.3", + "semver": "5.5.0", + "semver-intersect": "1.3.0" + }, + "dependencies": { + "fs-extra": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "jsonfile": "4.0.0", + "universalify": "0.1.1" + } + }, + "node-exceptions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-3.0.0.tgz", + "integrity": "sha512-pFhMAqdN1avrFwtZs66HxYiVnbnH9wjXB4m8IKs5Z9+r7U5voqxT+EDbVkRfge+V7JnkOgKhN4HfKBn1o5g9Wg==", + "dev": true + }, + "package-json-validator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.3.tgz", + "integrity": "sha512-juKiFboV4UKUvWQ+OSxstnyukhuluyuEoFmgZw1Rx21XzmwlgDWLcbl3qzjA3789IRORYhVFs7cmAO0YFGwHCg==", + "dev": true, + "requires": { + "optimist": "0.6.1" + } + }, + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true + }, + "semver-intersect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.0.tgz", + "integrity": "sha512-923f1TGXGb2+OCkLvsmNPijmurMQxEMFOhC80N4NL8/Jo5rBKufHZ3sBtJJ7GNhh4RhdsB6+vj+6W68kmr43Lg==", + "dev": true, + "requires": { + "semver": "5.5.0" + } + } } }, + "@yarnpkg/lockfile": { + "version": "file:node_modules/@userfrosting/merge-package-dependencies/node_modules_bundled/@yarnpkg/lockfile", + "dev": true + }, "accord": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/accord/-/accord-0.23.0.tgz", @@ -966,9 +1014,9 @@ "dev": true }, "fs-extra": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", - "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", "dev": true, "requires": { "graceful-fs": "4.1.11", @@ -1029,7 +1077,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", "dev": true, "requires": { "fs.realpath": "1.0.0", @@ -2222,7 +2270,7 @@ "hosted-git-info": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha1-bWDjSzq7yDEwYsO3mO+NkBoHrzw=", + "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", "dev": true }, "http-signature": { @@ -3128,7 +3176,7 @@ "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { "brace-expansion": "1.1.8" @@ -3178,16 +3226,10 @@ "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", "dev": true }, - "node-exceptions": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-2.0.2.tgz", - "integrity": "sha512-nILccFLvnaOBoKZZtWfZipn/hlThZOT6UJOLX6SA3yLMYPcvLTIF26PXx73sPnAg45p05iYFYw2jvayNHz4rDA==", - "dev": true - }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { "hosted-git-info": "2.5.0", @@ -3322,15 +3364,6 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, - "package-json-validator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.2.tgz", - "integrity": "sha512-B4eikrIIhxheXKkIW7GR6Se4mtqegZ/x8jUDh6hHW4jYBz9HFXUejpPEUAsuplxpDtVdPsXT3ZMRTH1HizJV1Q==", - "dev": true, - "requires": { - "optimist": "0.6.1" - } - }, "parse-filepath": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", @@ -3489,7 +3522,7 @@ "promise": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha1-BktyYCsY+Q8pGSuLG8QY/9Hr078=", + "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "dev": true, "requires": { "asap": "2.0.6" @@ -3518,7 +3551,7 @@ "randomatic": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", + "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", "dev": true, "requires": { "is-number": "3.0.0", @@ -3839,7 +3872,7 @@ "safe-buffer": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, "semver": { @@ -3848,15 +3881,6 @@ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, - "semver-intersect": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.1.2.tgz", - "integrity": "sha1-sLKLV1Ggf/3QAuXsYGyS1XbMtWE=", - "dev": true, - "requires": { - "semver": "5.4.1" - } - }, "sequencify": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", @@ -4094,7 +4118,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -4109,7 +4133,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -4142,7 +4166,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "dev": true, "requires": { "core-util-is": "1.0.2", @@ -4157,7 +4181,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "dev": true, "requires": { "safe-buffer": "5.1.1" @@ -4292,7 +4316,7 @@ "uuid": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", "dev": true, "optional": true }, diff --git a/build/package.json b/build/package.json index 6cfae3c9b..b69b313b0 100755 --- a/build/package.json +++ b/build/package.json @@ -1,11 +1,11 @@ { "private": true, "devDependencies": { - "@userfrosting/merge-package-dependencies": "^1.1.0", + "@userfrosting/merge-package-dependencies": "^1.2.0-rc.1", "bower": "^1.8.0", "del": "^2.2.2", "dotenv": "^4.0.0", - "fs-extra": "^4.0.0", + "fs-extra": "^5.0.0", "gulp": "^3.9.1", "gulp-load-plugins": "^1.4.0", "gulp-uf-bundle-assets": "^2.27.2", From 84e28694dd29f93458ec5cd9b3ad02e14b4513db Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 3 Feb 2018 15:25:19 +1100 Subject: [PATCH 042/237] Force userfrosting/merge-package-dependencies dependency up --- build/package-lock.json | 59 +++++++++++++++++++---------------------- build/package.json | 2 +- 2 files changed, 28 insertions(+), 33 deletions(-) diff --git a/build/package-lock.json b/build/package-lock.json index cdcebb263..d9ae5c5f5 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -3,12 +3,11 @@ "lockfileVersion": 1, "dependencies": { "@userfrosting/merge-package-dependencies": { - "version": "1.2.0-rc.1", - "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.0-rc.1.tgz", - "integrity": "sha512-slNx8WLIQXFtXQtxEQ6toG72dlk0Yb9kPSkLWvZ3LEMyHpnvAUHNgCkPmEHB0dttt8woQIXfYCG1+dxNbcxV9A==", + "version": "1.2.0-rc.2", + "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.0-rc.2.tgz", + "integrity": "sha512-+hDTJMa3PzWqqdXAJ8dRvNNmAFZ2mIQaoFXIJzO6+BvXcRuUciMvw3+HAX60c9O77YhKfLAjnyhkMtHHYtaUTQ==", "dev": true, "requires": { - "@yarnpkg/lockfile": "file:node_modules/@userfrosting/merge-package-dependencies/node_modules_bundled/@yarnpkg/lockfile", "chalk": "2.3.0", "fs-extra": "5.0.0", "lodash": "4.17.4", @@ -18,42 +17,14 @@ "semver-intersect": "1.3.0" }, "dependencies": { - "node-exceptions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-3.0.0.tgz", - "integrity": "sha512-pFhMAqdN1avrFwtZs66HxYiVnbnH9wjXB4m8IKs5Z9+r7U5voqxT+EDbVkRfge+V7JnkOgKhN4HfKBn1o5g9Wg==", - "dev": true - }, - "package-json-validator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.3.tgz", - "integrity": "sha512-juKiFboV4UKUvWQ+OSxstnyukhuluyuEoFmgZw1Rx21XzmwlgDWLcbl3qzjA3789IRORYhVFs7cmAO0YFGwHCg==", - "dev": true, - "requires": { - "optimist": "0.6.1" - } - }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", "dev": true - }, - "semver-intersect": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.0.tgz", - "integrity": "sha512-923f1TGXGb2+OCkLvsmNPijmurMQxEMFOhC80N4NL8/Jo5rBKufHZ3sBtJJ7GNhh4RhdsB6+vj+6W68kmr43Lg==", - "dev": true, - "requires": { - "semver": "5.5.0" - } } } }, - "@yarnpkg/lockfile": { - "version": "file:node_modules/@userfrosting/merge-package-dependencies/node_modules_bundled/@yarnpkg/lockfile", - "dev": true - }, "accord": { "version": "0.23.0", "resolved": "https://registry.npmjs.org/accord/-/accord-0.23.0.tgz", @@ -3215,6 +3186,12 @@ "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", "dev": true }, + "node-exceptions": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-3.0.0.tgz", + "integrity": "sha512-pFhMAqdN1avrFwtZs66HxYiVnbnH9wjXB4m8IKs5Z9+r7U5voqxT+EDbVkRfge+V7JnkOgKhN4HfKBn1o5g9Wg==", + "dev": true + }, "normalize-package-data": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", @@ -3353,6 +3330,15 @@ "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", "dev": true }, + "package-json-validator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.3.tgz", + "integrity": "sha512-juKiFboV4UKUvWQ+OSxstnyukhuluyuEoFmgZw1Rx21XzmwlgDWLcbl3qzjA3789IRORYhVFs7cmAO0YFGwHCg==", + "dev": true, + "requires": { + "optimist": "0.6.1" + } + }, "parse-filepath": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", @@ -3870,6 +3856,15 @@ "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, + "semver-intersect": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.0.tgz", + "integrity": "sha512-923f1TGXGb2+OCkLvsmNPijmurMQxEMFOhC80N4NL8/Jo5rBKufHZ3sBtJJ7GNhh4RhdsB6+vj+6W68kmr43Lg==", + "dev": true, + "requires": { + "semver": "5.4.1" + } + }, "sequencify": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", diff --git a/build/package.json b/build/package.json index b69b313b0..7dda05b50 100755 --- a/build/package.json +++ b/build/package.json @@ -1,7 +1,7 @@ { "private": true, "devDependencies": { - "@userfrosting/merge-package-dependencies": "^1.2.0-rc.1", + "@userfrosting/merge-package-dependencies": "^1.2.0-rc.2", "bower": "^1.8.0", "del": "^2.2.2", "dotenv": "^4.0.0", From 77e17b424290bb070a2f484070fa5ef1d52218a2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 6 Feb 2018 21:34:58 -0500 Subject: [PATCH 043/237] Explain `locale.default` config and fix array issue. --- app/sprinkles/core/config/default.php | 3 +++ app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 91e384433..56064df04 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -156,6 +156,9 @@ ], // This can be a comma-separated list, to load multiple fallback locales. // Supported browser requested languages always have first preference. + // First locale is the base one and the other one are loaded on top. + // For example, 'en_US,es_ES' will use the English (en_US) + // translation as a base and load the Spanish (es_ES) translation on top. 'default' => 'en_US' ], 'title' => 'UserFrosting', diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index ab123ceb8..cf66c494d 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -448,7 +448,7 @@ public function register(ContainerInterface $container) // Format for UF's i18n $parts[0] = str_replace('-', '_', $parts[0]); // Ensure locale available - if (array_key_exists($parts[0], $config['site.locales.available'])) { + if (array_key_exists($parts[0], $locales)) { // Determine preference level, and add to $allowedLocales if (array_key_exists(1, $parts)) { $parts[1] = str_replace('q=', '', $parts[1]); From 0c59308110146d743c50aed14c8e262a07420b38 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 6 Feb 2018 21:43:09 -0500 Subject: [PATCH 044/237] That last commit was dumb. This is sliglty less dumb --- app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index cf66c494d..bc8d0ece8 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -436,6 +436,9 @@ public function register(ContainerInterface $container) // Get default locales as specified in configurations. $locales = explode(',', $config['site.locales.default']); + // Get available locales (removing null values) + $availableLocales = array_filter($config['site.locales.available']); + // Add supported browser preferred locales. if ($request->hasHeader('Accept-Language')) { $allowedLocales = []; @@ -448,7 +451,7 @@ public function register(ContainerInterface $container) // Format for UF's i18n $parts[0] = str_replace('-', '_', $parts[0]); // Ensure locale available - if (array_key_exists($parts[0], $locales)) { + if (array_key_exists($parts[0], $availableLocales)) { // Determine preference level, and add to $allowedLocales if (array_key_exists(1, $parts)) { $parts[1] = str_replace('q=', '', $parts[1]); From cc0a1e95c464b0d83795f65b9ec073f4ed43602f Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 16 Feb 2018 22:17:35 -0500 Subject: [PATCH 045/237] UserFristing !! --- app/system/Bakery/BaseCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/system/Bakery/BaseCommand.php b/app/system/Bakery/BaseCommand.php index 209178992..7add8188a 100644 --- a/app/system/Bakery/BaseCommand.php +++ b/app/system/Bakery/BaseCommand.php @@ -30,7 +30,7 @@ abstract class BaseCommand extends Command protected $io; /** - * @var ContainerInterface $ci The global container object, which holds all of UserFristing services. + * @var ContainerInterface $ci The global container object, which holds all of UserFrosting services. */ protected $ci; From 83b017454a46e23528daa5ae3abd01773155ba4e Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 17 Feb 2018 09:36:22 -0500 Subject: [PATCH 046/237] Typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25b77642c..646269f60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - The console IO instance is not available anymore in migrations. - Removed the `io` property from migration classes. - Removed Bakery `projectRoot` property. Use the `\UserFrosting\ROOT_DIR` constant instead. -- Removed `preted` option from Bakery `migrate:refresh` and `migrate:reset` commands. +- Removed `pretend` option from Bakery `migrate:refresh` and `migrate:reset` commands. ### Fixed From 95d20b6bd845afdd326754ebad09cb95caf6bbeb Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 24 Feb 2018 15:06:26 -0500 Subject: [PATCH 047/237] Added Twig blocks to login page for easier customisation --- app/sprinkles/account/templates/pages/sign-in.html.twig | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/sprinkles/account/templates/pages/sign-in.html.twig b/app/sprinkles/account/templates/pages/sign-in.html.twig index 2fb6e1c25..cd4341fb6 100644 --- a/app/sprinkles/account/templates/pages/sign-in.html.twig +++ b/app/sprinkles/account/templates/pages/sign-in.html.twig @@ -11,16 +11,20 @@ {% block content %} From ba3f55c1793a36748ecd2d92ecebd90282f292d2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 16 Mar 2018 18:11:50 -0400 Subject: [PATCH 048/237] Included Vagrant support directly inside UF (partially fix #829) --- .gitignore | 4 ++ Vagrantfile | 25 ++++++++ vagrant/after.sh | 30 ++++++++++ vagrant/bootstrap.yaml | 23 ++++++++ vagrant/doc.md | 130 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 212 insertions(+) create mode 100644 Vagrantfile create mode 100644 vagrant/after.sh create mode 100644 vagrant/bootstrap.yaml create mode 100644 vagrant/doc.md diff --git a/.gitignore b/.gitignore index 61266a064..5fe92c603 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,7 @@ app/database/userfrosting.db # Ignore vendor assets app/assets/* + +# Ignore Vagrant & Homestead VM +vagrant/Homestead/ +.vagrant/* diff --git a/Vagrantfile b/Vagrantfile new file mode 100644 index 000000000..919d30127 --- /dev/null +++ b/Vagrantfile @@ -0,0 +1,25 @@ +require 'json' +require 'yaml' + +VAGRANTFILE_API_VERSION ||= "2" +confDir = $confDir ||= File.expand_path("vagrant/homestead", File.dirname(__FILE__)) + +homesteadYamlPath = "vagrant/bootstrap.yaml" +afterScriptPath = "vagrant/after.sh" +aliasesPath = "vagrant/aliases" + +require File.expand_path(confDir + '/scripts/homestead.rb') + +Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| + if File.exists? aliasesPath then + config.vm.provision "file", source: aliasesPath, destination: "~/.bash_aliases" + end + + if File.exists? homesteadYamlPath then + Homestead.configure(config, YAML::load(File.read(homesteadYamlPath))) + end + + if File.exists? afterScriptPath then + config.vm.provision "shell", path: afterScriptPath + end +end \ No newline at end of file diff --git a/vagrant/after.sh b/vagrant/after.sh new file mode 100644 index 000000000..36f4a6a58 --- /dev/null +++ b/vagrant/after.sh @@ -0,0 +1,30 @@ +#!/bin/sh + +BASE_PATH="/home/vagrant/userfrosting" + +# Ensure composer deps are installed +cd ${BASE_PATH} +composer install + +# Setup .env +echo 'UF_MODE=""' > app/.env +echo 'DB_DRIVER="mysql"' >> app/.env +echo 'DB_HOST="localhost"' >> app/.env +echo 'DB_PORT="3306"' >> app/.env +echo 'DB_NAME="UserFrosting"' >> app/.env +echo 'DB_USER="homestead"' >> app/.env +echo 'DB_PASSWORD="secret"' >> app/.env +echo 'SMTP_HOST="host.example.com"' >> app/.env +echo 'SMTP_USER="relay@example.com"' >> app/.env +echo 'SMTP_PASSWORD="password"' >> app/.env + +# Setup sprinkles.json +cp app/sprinkles.example.json app/sprinkles.json + +# Install UserFrosting +php bakery debug +php bakery migrate +# php bakery create-admin !!! Requires fix for #808 https://github.com/userfrosting/UserFrosting/issues/808 +php bakery build-assets + +echo "\n\nUserFrosting is ready at http://192.168.10.10/" \ No newline at end of file diff --git a/vagrant/bootstrap.yaml b/vagrant/bootstrap.yaml new file mode 100644 index 000000000..dd44db7b9 --- /dev/null +++ b/vagrant/bootstrap.yaml @@ -0,0 +1,23 @@ +--- +ip: "192.168.10.10" +memory: 2048 +cpus: 1 +hostname: userfrosting +name: userfrosting +provider: virtualbox + +authorize: ~/.ssh/id_rsa.pub + +keys: + - ~/.ssh/id_rsa + +folders: + - map: "." + to: "/home/vagrant/userfrosting" + +sites: + - map: userfrosting.test + to: "/home/vagrant/userfrosting/public" + +databases: + - UserFrosting diff --git a/vagrant/doc.md b/vagrant/doc.md new file mode 100644 index 000000000..dde4b41f4 --- /dev/null +++ b/vagrant/doc.md @@ -0,0 +1,130 @@ +## Using Vagrant with UserFrosting + +UserFrosting includes support for Vagrant. This allows you to run UserFrosting without the need to set up your own local web server with traditional WAMP/MAMP stacks. It also provides a consistent environment between developers for writing and debugging code changes more productively. + +UserFrosting uses the [Laravel/Homestead](https://laravel.com/docs/5.6/homestead) Vagrant box. It runs a Linux server with Ubuntu 14.04, PHP 5.6, Nginx, SQLite3, MySQL, and a whole lot more (complete specs below). + +## Get Started + +* Download and Install [Vagrant](https://www.vagrantup.com/downloads.html) +* Download and Install [VirtualBox](https://www.virtualbox.org/wiki/Downloads) + +* Clone Homestead from the root of your cloned fork of the UserFrosting Git repository + +```sh +git clone https://github.com/laravel/homestead.git vagrant/Homestead +``` + +* Run `vagrant up` from the root of your cloned fork of the UserFrosting Git repository + +```sh +$ vagrant up +``` + +* Access UserFrosting at `http://192.168.10.10/` +* Username: **admin** +* Password: **adminadmin** + +## Additional commands: +* Access your Linux server from the command line: + +```sh +$ vagrant ssh +``` + +* Pause your server: + +```sh +$ vagrant suspend +``` + +* Shut down your server: + +```sh +$ vagrant halt +``` + +* Delete and remove your server: + +```sh +$ vagrant destroy +``` + +> Note: destroying the vagrant server will remove all traces of the VM from your computer, reclaiming any disk space used by it. However, it also means the next time you vagrant up, you will be creating a brand new VM with a fresh install of UserFrosting and a new database. + +## Customising the UserFrosting configuration + +By default, UserFrosting is pre-configured to install with a MySQL database. You can, however, switch to PostegreSQL or SQLite3 by editing the `install-config.yml` file in the vagrant directory. The next time you run `vagrant up` (or `vagrant provision`) it will be installed under the new configuration. + +If you prefer to access UserFrosting from the more friendly URL `http://userfrosting.test` then you must update your computer's hosts file. This file is typically located at `/etc/hosts` for Mac/Linux or `C:\Windows\System32\drivers\etc\hosts` for Windows. Open this file and add the following line to it, at the very bottom, and save. + +``` +192.168.10.10 userfrosting.test +``` + +## How it all works + +When you vagrant up, the Laravel/Homestead box is transparently loaded as a Virtual Machine on your computer (this may take several minutes the very first time while it downloads the VM image to your computer). Your local UserFrosting repository clone is mirrored/shared with the VM, so you can work on the UserFrosting code on your computer, and see the changes immediately when you browse to UserFrosting at the URL provided by the VM. + +This is very similar to traditional methods of working with a local WAMP/MAMP stack, except the webserver is now being provided by a VM of a Linux server. The advantages here are the exact same Linux server environment is being used by everybody who uses Vagrant with UserFrosting, so there will be consist behaviour unlike when everybody is developing on different versions of PHP, server configurations, etc. + +The environment is also "sandboxed" from your system. This means you don't need to worry about adjusting your own computer's internal PHP settings, setting up databases, or doing damage to your system or to UserFrosting. Other than the UserFrosting codebase, which lives on your computer, all execution is taking place within the VM and you can at any time, halt or destroy the VM and start a brand new one. + +There are some caveats, however. You can only run one vagrant VM for the UserFrosting repository. And of course, the database will be destroyed when you vagrant destroy. If the database is important, you should SSH into your vagrant VM and export/import the DB as needed using SSH commands. + +For example, to export/import a MySQL database (using UserFrosting's `store` directory): + +SSH into the VM + +```sh +$ vagrant ssh +``` + +Export MySQL: + +```sh +$ mysqldump -uhomestead -psecret UserFrosting > /home/vagrant/userfrosting/userfrosting.sql +``` + +Import MySQL: + +```sh +$ mysql -uhomestead -psecret UserFrosting < /home/vagrant/userfrosting/userfrosting.sql +``` + +--- + +## About the Laravel/Homestead box + +### Included Software + +* Ubuntu 14.04 +* Git +* PHP 5.6 +* HHVM +* Nginx +* MySQL +* Sqlite3 +* Postgres +* Composer +* Node (With PM2, Bower, Grunt, and Gulp) +* Redis +* Memcached +* Beanstalkd +* Blackfire Profiler + +### MySQL Access + +- Hostname: 127.0.0.1 +- Username: homestead +- Password: secret +- Database: UserFrosting +- Port: 3306 + +### PostgreSQL Access + +- Hostname: 127.0.0.1 +- Username: homestead +- Password: secret +- Database: UserFrosting +- Port: 5432 \ No newline at end of file From 0ad00927faf5719f462061d5c86f212efb7cdb2b Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 17 Mar 2018 15:53:04 -0400 Subject: [PATCH 049/237] Added options to `create-admin` Bakery command (Ref #808) --- .../account/src/Bakery/CreateAdminUser.php | 169 ++++++++++-------- 1 file changed, 90 insertions(+), 79 deletions(-) diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index 01125a4fa..995e6b842 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -8,6 +8,7 @@ namespace UserFrosting\Sprinkle\Account\Bakery; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use UserFrosting\System\Bakery\BaseCommand; use UserFrosting\System\Bakery\DatabaseTest; @@ -38,8 +39,14 @@ class CreateAdminUser extends BaseCommand */ protected function configure() { - $this->setName("create-admin") - ->setDescription("Create the initial admin (root) user account"); + $this->setName('create-admin') + ->setDescription('Create the initial admin (root) user account') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'If admin user already exist, delete user and recreate it again') + ->addOption('username', null, InputOption::VALUE_OPTIONAL, 'The admin user username') + ->addOption('email', null, InputOption::VALUE_OPTIONAL, 'The admin user email') + ->addOption('password', null, InputOption::VALUE_OPTIONAL, 'The admin user password') + ->addOption('firstName', null, InputOption::VALUE_OPTIONAL, 'The admin user first name') + ->addOption('lastName', null, InputOption::VALUE_OPTIONAL, 'The admin user last name'); } /** @@ -47,26 +54,25 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Root account setup"); + $this->io->title('Root account setup'); + + // Get the options + $force = $input->getOption('force'); // Need the database try { - $this->io->writeln("Testing database connection", OutputInterface::VERBOSITY_VERBOSE); + $this->io->writeln('Testing database connection', OutputInterface::VERBOSITY_VERBOSE); $this->testDB(); - $this->io->writeln("Ok", OutputInterface::VERBOSITY_VERBOSE); + $this->io->writeln('Ok', OutputInterface::VERBOSITY_VERBOSE); } catch (\Exception $e) { $this->io->error($e->getMessage()); exit(1); } - /** - * @var \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator; - */ + /** @var \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator; */ $migrator = $this->ci->migrator; - /** - * @var \UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository; - */ + /** @var \UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository; */ $repository = $migrator->getRepository(); // Need migration table @@ -86,28 +92,27 @@ protected function execute(InputInterface $input, OutputInterface $output) // Make sure that there are no users currently in the user table // We setup the root account here so it can be done independent of the version check - if (User::count() > 0) { + if (User::count() > 0 && !$force) { $this->io->note("Table 'users' is not empty. Skipping root account setup. To set up the root account again, please truncate or drop the table and try again."); } else { $this->io->writeln("Please answer the following questions to create the root account:\n"); // Get the account details - $userName = $this->askUsername(); - $email = $this->askEmail(); - $firstName = $this->askFirstName(); - $lastName = $this->askLastName(); - $password = $this->askPassword(); + $username = $this->askUsername($input->getOption('username')); + $email = $this->askEmail($input->getOption('email')); + $firstName = $this->askFirstName($input->getOption('firstName')); + $lastName = $this->askLastName($input->getOption('lastName')); + $password = $this->askPassword($input->getOption('password')); // Ok, now we've got the info and we can create the new user. $this->io->write("\nSaving the root user details..."); $rootUser = new User([ - "user_name" => $userName, - "email" => $email, - "first_name" => $firstName, - "last_name" => $lastName, - "password" => Password::hash($password) + 'user_name' => $username, + 'email' => $email, + 'first_name' => $firstName, + 'last_name' => $lastName, + 'password' => Password::hash($password) ]); - $rootUser->save(); $defaultRoles = [ @@ -122,34 +127,35 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - $this->io->success("Root user creation successful!"); + $this->io->success('Root user creation successful!'); } } /** - * Ask for the username + * Ask for the username and return a valid one * - * @return string + * @param string $username The base/default username + * @return string The validated username */ - protected function askUsername() + protected function askUsername($username = '') { - while (!isset($userName) || !$this->validateUsername($userName)) { - $userName = $this->io->ask("Choose a root username (1-50 characters, no leading or trailing whitespace)"); + while (!isset($username) || !$this->validateUsername($username)) { + $username = $this->io->ask('Choose a root username (1-50 characters, no leading or trailing whitespace)'); } - return $userName; + return $username; } /** - * Validate the username. + * Validate the username. * - * @param string $userName - * @return bool + * @param string $username The input + * @return bool Is the username validated ? */ - protected function validateUsername($userName) + protected function validateUsername($username) { // Validate length - if (strlen($userName) < 1 || strlen($userName) > 50) { - $this->io->error("Username must be between 1-50 characters"); + if (strlen($username) < 1 || strlen($username) > 50) { + $this->io->error('Username must be between 1-50 characters'); return false; } @@ -159,7 +165,7 @@ protected function validateUsername($userName) 'regexp' => "/^\S((.*\S)|)$/" ] ]; - $validate = filter_var($userName, FILTER_VALIDATE_REGEXP, $options); + $validate = filter_var($username, FILTER_VALIDATE_REGEXP, $options); if (!$validate) { $this->io->error("Username can't have any leading or trailing whitespace"); return false; @@ -169,35 +175,36 @@ protected function validateUsername($userName) } /** - * Ask for the email + * Ask for the email and return a valid one * - * @return string + * @param string $mail The base/default email + * @return string The validated email */ - protected function askEmail() + protected function askEmail($email = '') { while (!isset($email) || !$this->validateEmail($email)) { - $email = $this->io->ask("Enter a valid email address (1-254 characters, must be compatible with FILTER_VALIDATE_EMAIL)"); + $email = $this->io->ask('Enter a valid email address (1-254 characters, must be compatible with FILTER_VALIDATE_EMAIL)'); } return $email; } /** - * Validate the email. + * Validate the email. * - * @param string $email - * @return bool + * @param string $email The input + * @return bool Is the email validated ? */ protected function validateEmail($email) { // Validate length if (strlen($email) < 1 || strlen($email) > 254) { - $this->io->error("Email must be between 1-254 characters"); + $this->io->error('Email must be between 1-254 characters'); return false; } // Validate format if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { - $this->io->error("Email must be compatible with FILTER_VALIDATE_EMAIL"); + $this->io->error('Email must be compatible with FILTER_VALIDATE_EMAIL'); return false; } @@ -205,29 +212,30 @@ protected function validateEmail($email) } /** - * Ask for the first name + * Ask for the first name and return a valid one * - * @return string + * @param string $firstName The base/default first name + * @return string The validated first name */ - protected function askFirstName() + protected function askFirstName($firstName = '') { while (!isset($firstName) || !$this->validateFirstName($firstName)) { - $firstName = $this->io->ask("Enter the user first name (1-20 characters)"); + $firstName = $this->io->ask('Enter the user first name (1-20 characters)'); } return $firstName; } /** - * validateFirstName function. + * Validate the first name * - * @param string $firstName - * @return bool + * @param string $firstName The input + * @return bool Is the input validated ? */ protected function validateFirstName($firstName) { // Validate length if (strlen($firstName) < 1 || strlen($firstName) > 20) { - $this->io->error("First name must be between 1-20 characters"); + $this->io->error('First name must be between 1-20 characters'); return false; } @@ -235,29 +243,30 @@ protected function validateFirstName($firstName) } /** - * Ask for the last name + * Ask for the last name and return a valid one * - * @return string + * @param string $lastName The base/default last name + * @return string The validated last name */ - protected function askLastName() + protected function askLastName($lastName = '') { while (!isset($lastName) || !$this->validateLastName($lastName)) { - $lastName = $this->io->ask("Enter the user last name (1-30 characters)"); + $lastName = $this->io->ask('Enter the user last name (1-30 characters)'); } return $lastName; } /** - * validateLastName function. + * Validate the last name entered is valid * - * @param string $lastName - * @return bool + * @param string $lastName The lastname + * @return bool Input is valid or not */ protected function validateLastName($lastName) { // Validate length if (strlen($lastName) < 1 || strlen($lastName) > 30) { - $this->io->error("Last name must be between 1-30 characters"); + $this->io->error('Last name must be between 1-30 characters'); return false; } @@ -265,28 +274,30 @@ protected function validateLastName($lastName) } /** - * Ask for the password + * Ask for the password and return a valid one * - * @return string + * @param string $password The base/default password + * @return string The validated password */ - protected function askPassword() + protected function askPassword($password = '') { while (!isset($password) || !$this->validatePassword($password) || !$this->confirmPassword($password)) { - $password = $this->io->askHidden("Enter password (12-255 characters)"); + $password = $this->io->askHidden('Enter password (12-255 characters)'); } return $password; } /** - * validatePassword function. + * Validate password input * - * @param string $password - * @return bool + * @param string $password The input + * @return bool Is the password valid or not */ protected function validatePassword($password) { + //TODO Config for this ?? if (strlen($password) < 12 || strlen($password) > 255) { - $this->io->error("Password must be between 12-255 characters"); + $this->io->error('Password must be between 12-255 characters'); return false; } @@ -294,30 +305,30 @@ protected function validatePassword($password) } /** - * confirmPassword function. + * Ask for password confirmation * - * @param string $passwordToConfirm - * @return bool + * @param string $passwordToConfirm + * @return bool Is the password confirmed or not */ protected function confirmPassword($passwordToConfirm) { while (!isset($password)) { - $password = $this->io->askHidden("Please re-enter the chosen password"); + $password = $this->io->askHidden('Please re-enter the chosen password'); } return $this->validatePasswordConfirmation($password, $passwordToConfirm); } /** - * validatePasswordConfirmation function. + * Validate the confirmation password * - * @param string $password - * @param string $passwordToConfirm - * @return bool + * @param string $password The confirmation + * @param string $passwordToConfirm The password to confirm + * @return bool Is the confirmation password valid or not */ protected function validatePasswordConfirmation($password, $passwordToConfirm) { if ($password != $passwordToConfirm) { - $this->io->error("Passwords do not match, please try again."); + $this->io->error('Passwords do not match, please try again.'); return false; } From 74000a94fe6ddc98563e1ab2b309e3488406c39b Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 18 Mar 2018 19:37:28 -0400 Subject: [PATCH 050/237] Linting --- .../src/Controller/AccountController.php | 352 +++++++++++++----- .../account/src/Database/Models/User.php | 19 +- 2 files changed, 275 insertions(+), 96 deletions(-) diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 7365111bb..4f228c4da 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Controller; use Carbon\Carbon; -use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; @@ -17,19 +16,13 @@ use UserFrosting\Fortress\RequestSchema; use UserFrosting\Fortress\ServerSideValidator; use UserFrosting\Fortress\Adapter\JqueryValidationAdapter; -use UserFrosting\Sprinkle\Account\Authenticate\Authenticator; use UserFrosting\Sprinkle\Account\Controller\Exception\SpammyRequestException; -use UserFrosting\Sprinkle\Account\Database\Models\Group; -use UserFrosting\Sprinkle\Account\Database\Models\User; use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Account\Util\Util as AccountUtil; use UserFrosting\Sprinkle\Core\Controller\SimpleController; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Mail\EmailRecipient; use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage; -use UserFrosting\Sprinkle\Core\Throttle\Throttler; use UserFrosting\Sprinkle\Core\Util\Captcha; -use UserFrosting\Sprinkle\Core\Util\Util; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; use UserFrosting\Support\Exception\HttpException; @@ -43,15 +36,23 @@ class AccountController extends SimpleController { /** - * Check a username for availability. + * Check a username for availability. * - * This route is throttled by default, to discourage abusing it for account enumeration. - * This route is "public access". - * Request type: GET + * This route is throttled by default, to discourage abusing it for account enumeration. + * This route is "public access". + * + * AuthGuard: false + * Route: /account/check-username + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function checkUsername($request, $response, $args) + public function checkUsername(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // GET parameters @@ -77,7 +78,7 @@ public function checkUsername($request, $response, $args) throw $e; } - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ $throttler = $this->ci->throttler; $delay = $throttler->getDelay('check_username_request'); @@ -86,10 +87,10 @@ public function checkUsername($request, $response, $args) return $response->withStatus(429); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\I18n\MessageTranslator $translator */ + /** @var \UserFrosting\I18n\MessageTranslator $translator */ $translator = $this->ci->translator; // Log throttleable event @@ -104,22 +105,30 @@ public function checkUsername($request, $response, $args) } /** - * Processes a request to cancel a password reset request. + * Processes a request to cancel a password reset request. * - * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves. - * Processes the request from the password reset link, checking that: - * 1. The provided token is associated with an existing user account, who has a pending password reset request. - * Request type: GET + * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves. + * Processes the request from the password reset link, checking that: + * 1. The provided token is associated with an existing user account, who has a pending password reset request. + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function denyResetPassword($request, $response, $args) + public function denyResetPassword(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $loginPage = $this->ci->router->pathFor('login'); @@ -163,16 +172,25 @@ public function denyResetPassword($request, $response, $args) * Request type: POST * @todo require additional user information * @todo prevent password reset requests for root account? + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function forgotPassword($request, $response, $args) + public function forgotPassword(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get POST parameters @@ -194,7 +212,7 @@ public function forgotPassword($request, $response, $args) // Throttle requests - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ $throttler = $this->ci->throttler; $throttleData = [ @@ -249,8 +267,17 @@ public function forgotPassword($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages. * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function getModalAccountTos($request, $response, $args) + public function getModalAccountTos(Request $request, Response $response, $args) { return $this->ci->view->render($response, 'modals/tos.html.twig'); } @@ -259,8 +286,17 @@ public function getModalAccountTos($request, $response, $args) * Generate a random captcha, store it to the session, and return the captcha image. * * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function imageCaptcha($request, $response, $args) + public function imageCaptcha(Request $request, Response $response, $args) { $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']); $captcha->generateRandomCode(); @@ -282,16 +318,25 @@ public function imageCaptcha($request, $response, $args) * 6. The user entered a valid username/email and password. * This route, by definition, is "public access". * Request type: POST + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function login($request, $response, $args) + public function login(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $this->ci->authenticator; // Return 200 success if user is already logged in @@ -300,7 +345,7 @@ public function login($request, $response, $args) return $response->withStatus(200); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get POST parameters @@ -325,7 +370,7 @@ public function login($request, $response, $args) // Throttle requests - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ $throttler = $this->ci->throttler; $userIdentifier = $data['user_name']; @@ -353,7 +398,7 @@ public function login($request, $response, $args) } // Try to authenticate the user. Authenticator will throw an exception on failure. - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $this->ci->authenticator; $currentUser = $authenticator->attempt(($isEmail ? 'email' : 'user_name'), $userIdentifier, $data['password'], $data['rememberme']); @@ -370,6 +415,15 @@ public function login($request, $response, $args) * Log the user out completely, including destroying any "remember me" token. * * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function logout(Request $request, Response $response, $args) { @@ -387,8 +441,17 @@ public function logout(Request $request, Response $response, $args) * This creates a simple form to allow users who forgot their password to have a time-limited password reset link emailed to them. * By default, this is a "public page" (does not require authentication). * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function pageForgotPassword($request, $response, $args) + public function pageForgotPassword(Request $request, Response $response, $args) { // Load validation rules $schema = new RequestSchema('schema://requests/forgot-password.yaml'); @@ -410,19 +473,28 @@ public function pageForgotPassword($request, $response, $args) * This allows new (non-authenticated) users to create a new account for themselves on your website (if enabled). * By definition, this is a "public page" (does not require authentication). * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function pageRegister($request, $response, $args) + public function pageRegister(Request $request, Response $response, $args) { - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; - /** @var UserFrosting\I18n\LocalePathBuilder */ + /** @var \UserFrosting\I18n\LocalePathBuilder */ $localePathBuilder = $this->ci->localePathBuilder; if (!$config['site.registration.enabled']) { throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $this->ci->authenticator; // Redirect if user is already logged in @@ -458,8 +530,17 @@ public function pageRegister($request, $response, $args) * This is a form that allows users who lost their account verification link to have the link resent to their email address. * By default, this is a "public page" (does not require authentication). * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function pageResendVerification($request, $response, $args) + public function pageResendVerification(Request $request, Response $response, $args) { // Load validation rules $schema = new RequestSchema('schema://requests/resend-verification.yaml'); @@ -479,8 +560,17 @@ public function pageResendVerification($request, $response, $args) * * Renders the new password page for password reset requests. * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function pageResetPassword($request, $response, $args) + public function pageResetPassword(Request $request, Response $response, $args) { // Insert the user's secret token from the link into the password reset form $params = $request->getQueryParams(); @@ -505,8 +595,17 @@ public function pageResetPassword($request, $response, $args) * Renders the page where new users who have had accounts created for them by another user, can set their password. * By default, this is a "public page" (does not require authentication). * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function pageSetPassword($request, $response, $args) + public function pageSetPassword(Request $request, Response $response, $args) { // Insert the user's secret token from the link into the password set form $params = $request->getQueryParams(); @@ -532,13 +631,22 @@ public function pageSetPassword($request, $response, $args) * Any fields that the user does not have permission to modify will be automatically disabled. * This page requires authentication. * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function pageSettings($request, $response, $args) + public function pageSettings(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -553,7 +661,7 @@ public function pageSettings($request, $response, $args) $schema = new RequestSchema('schema://requests/profile-settings.yaml'); $validatorProfileSettings = new JqueryValidationAdapter($schema, $this->ci->translator); - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get a list of all locales @@ -577,13 +685,22 @@ public function pageSettings($request, $response, $args) * This allows existing users to sign in. * By definition, this is a "public page" (does not require authentication). * Request type: GET + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function pageSignIn($request, $response, $args) + public function pageSignIn(Request $request, Response $response, $args) { - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $this->ci->authenticator; // Redirect if user is already logged in @@ -614,16 +731,25 @@ public function pageSignIn($request, $response, $args) * 2. The submitted data is valid. * This route requires authentication. * Request type: POST + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function profile($request, $response, $args) + public function profile(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access control for entire resource - check that the current user has permission to modify themselves @@ -633,10 +759,10 @@ public function profile($request, $response, $args) return $response->withStatus(403); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // POST parameters @@ -700,16 +826,25 @@ public function profile($request, $response, $args) * This route is "public access". * Request type: POST * Returns the User Object for the user record that was created. + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function register(Request $request, Response $response, $args) { - /** @var MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get POST parameters: user_name, first_name, last_name, email, password, passwordc, captcha, spiderbro, csrf_token @@ -732,7 +867,7 @@ public function register(Request $request, Response $response, $args) return $response->withStatus(403); } - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $this->ci->authenticator; // Prevent the user from registering if he/she is already logged in @@ -757,7 +892,7 @@ public function register(Request $request, Response $response, $args) $error = true; } - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ $throttler = $this->ci->throttler; $delay = $throttler->getDelay('registration_attempt'); @@ -882,16 +1017,25 @@ public function register(Request $request, Response $response, $args) * 4. The submitted data is valid. * This route is "public access". * Request type: POST + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function resendVerification($request, $response, $args) + public function resendVerification(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get POST parameters @@ -913,7 +1057,7 @@ public function resendVerification($request, $response, $args) // Throttle requests - /** @var UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ + /** @var \UserFrosting\Sprinkle\Core\Throttle\Throttler $throttler */ $throttler = $this->ci->throttler; $throttleData = [ @@ -970,16 +1114,25 @@ public function resendVerification($request, $response, $args) * 4. The submitted data (new password) is valid. * This route is "public access". * Request type: POST + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function setPassword(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get POST parameters @@ -1013,7 +1166,7 @@ public function setPassword(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'PASSWORD.UPDATED'); - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $this->ci->authenticator; // Log out any existing user, and create a new session @@ -1038,16 +1191,25 @@ public function setPassword(Request $request, Response $response, $args) * 3. The submitted data is valid. * This route requires authentication. * Request type: POST + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function settings($request, $response, $args) + public function settings(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access control for entire resource - check that the current user has permission to modify themselves @@ -1057,10 +1219,10 @@ public function settings($request, $response, $args) return $response->withStatus(403); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // POST parameters @@ -1131,13 +1293,22 @@ public function settings($request, $response, $args) * This route is "public access". * Request type: GET * @todo Can this route be abused for account enumeration? If so we should throttle it as well. + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ - public function suggestUsername($request, $response, $args) + public function suggestUsername(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $suggestion = AccountUtil::randomUniqueUsername($classMapper, 50, 10); @@ -1156,17 +1327,26 @@ public function suggestUsername($request, $response, $args) * 1. The token provided matches a user in the database; * 2. The user account is not already verified; * This route is "public access". + * + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void * Request type: GET */ - public function verify($request, $response, $args) + public function verify(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; $loginPage = $this->ci->router->pathFor('login'); diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index 235f2efd3..a81db1680 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Models; use Carbon\Carbon; -use Illuminate\Database\Capsule\Manager as Capsule; use Illuminate\Database\Eloquent\SoftDeletes; use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Core\Database\Models\Model; @@ -130,7 +129,7 @@ public function __isset($name) * Get a property for this object. * * @param string $name the name of the property to retrieve. - * @throws Exception the property does not exist for this object. + * @throws \Exception the property does not exist for this object. * @return string the associated property. */ public function __get($name) @@ -153,7 +152,7 @@ public function __get($name) */ public function activities() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->hasMany($classMapper->getClassMapping('activity'), 'user_id'); @@ -167,7 +166,7 @@ public function activities() */ public function delete($hardDelete = false) { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; if ($hardDelete) { @@ -275,7 +274,7 @@ public function getSecondsSinceLastActivity($type) */ public function group() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsTo($classMapper->getClassMapping('group'), 'group_id'); @@ -301,7 +300,7 @@ public function isMaster() */ public function lastActivity() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsTo($classMapper->getClassMapping('activity'), 'last_activity_id'); @@ -315,7 +314,7 @@ public function lastActivity() */ public function lastActivityOfType($type = null) { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; $query = $this->hasOne($classMapper->getClassMapping('activity'), 'user_id'); @@ -402,7 +401,7 @@ public function onLogout($params = []) */ public function passwordResets() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->hasMany($classMapper->getClassMapping('password_reset'), 'user_id'); @@ -415,7 +414,7 @@ public function passwordResets() */ public function permissions() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsToManyThrough( @@ -437,7 +436,7 @@ public function permissions() */ public function roles() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsToMany($classMapper->getClassMapping('role'), 'role_users', 'user_id', 'role_id')->withTimestamps(); From 9b18851a9117b43da8c6f3fb40c44a3ea0f9a8c8 Mon Sep 17 00:00:00 2001 From: alexweissman Date: Mon, 19 Mar 2018 22:03:13 -0400 Subject: [PATCH 051/237] Add comment to explain jQuery Validation options --- app/sprinkles/core/assets/userfrosting/js/uf-form.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/sprinkles/core/assets/userfrosting/js/uf-form.js b/app/sprinkles/core/assets/userfrosting/js/uf-form.js index 313cba58e..54c396dc8 100644 --- a/app/sprinkles/core/assets/userfrosting/js/uf-form.js +++ b/app/sprinkles/core/assets/userfrosting/js/uf-form.js @@ -43,6 +43,8 @@ beforeSubmitCallback: null, binaryCheckboxes : true, // submit checked/unchecked checkboxes as 0/1 values keyupDelay : 0, + // These are options that will be passed to jQuery Validate + // See https://jqueryvalidation.org/validate/#-validate() validator: { rules : {}, messages : {} @@ -62,6 +64,8 @@ var lateDefaults = { submitButton : this.$element.find('button[type=submit]'), msgTarget : this.$element.find('.js-form-alerts:first'), + // These are options that will be passed to jQuery Validate + // See https://jqueryvalidation.org/validate/#-validate() validator : { submitHandler: $.proxy(this.defaultSubmitHandler, this), onkeyup : $.proxy(this._onKeyUp, this) From 356ffe9fb5d5726601791af46c71418d7a353e9b Mon Sep 17 00:00:00 2001 From: alexweissman Date: Mon, 19 Mar 2018 22:12:29 -0400 Subject: [PATCH 052/237] update to new ufForm syntax --- .../assets/userfrosting/js/pages/account-settings.js | 4 ++-- .../assets/userfrosting/js/pages/forgot-password.js | 2 +- .../account/assets/userfrosting/js/pages/register.js | 2 +- .../assets/userfrosting/js/pages/resend-verification.js | 2 +- .../assets/userfrosting/js/pages/set-or-reset-password.js | 2 +- .../account/assets/userfrosting/js/pages/sign-in.js | 2 +- .../admin/assets/userfrosting/js/widgets/groups.js | 2 +- .../admin/assets/userfrosting/js/widgets/roles.js | 6 +++--- .../admin/assets/userfrosting/js/widgets/users.js | 8 ++++---- 9 files changed, 15 insertions(+), 15 deletions(-) diff --git a/app/sprinkles/account/assets/userfrosting/js/pages/account-settings.js b/app/sprinkles/account/assets/userfrosting/js/pages/account-settings.js index 8d8d2e795..c68d4f2df 100644 --- a/app/sprinkles/account/assets/userfrosting/js/pages/account-settings.js +++ b/app/sprinkles/account/assets/userfrosting/js/pages/account-settings.js @@ -12,7 +12,7 @@ $(document).ready(function() { $('.js-select2').select2(); $("#account-settings").ufForm({ - validators: page.validators.account_settings, + validator: page.validators.account_settings, msgTarget: $("#alerts-page") }).on("submitSuccess.ufForm", function() { // Reload the page on success @@ -20,7 +20,7 @@ $(document).ready(function() { }); $("#profile-settings").ufForm({ - validators: page.validators.profile_settings, + validator: page.validators.profile_settings, msgTarget: $("#alerts-page") }).on("submitSuccess.ufForm", function() { // Reload the page on success diff --git a/app/sprinkles/account/assets/userfrosting/js/pages/forgot-password.js b/app/sprinkles/account/assets/userfrosting/js/pages/forgot-password.js index 3f24311fd..e72521e2c 100644 --- a/app/sprinkles/account/assets/userfrosting/js/pages/forgot-password.js +++ b/app/sprinkles/account/assets/userfrosting/js/pages/forgot-password.js @@ -10,7 +10,7 @@ $(document).ready(function() { // TODO: Process form $("#request-password-reset").ufForm({ - validators: page.validators.forgot_password, + validator: page.validators.forgot_password, msgTarget: $("#alerts-page") }).on("submitSuccess.ufForm", function() { // Forward to login page on success diff --git a/app/sprinkles/account/assets/userfrosting/js/pages/register.js b/app/sprinkles/account/assets/userfrosting/js/pages/register.js index d855bb97c..255bb287f 100644 --- a/app/sprinkles/account/assets/userfrosting/js/pages/register.js +++ b/app/sprinkles/account/assets/userfrosting/js/pages/register.js @@ -81,7 +81,7 @@ $(document).ready(function() { // Handles form submission $("#register").ufForm({ - validators: registrationValidators, + validator: registrationValidators, msgTarget: $("#alerts-page"), keyupDelay: 500 }).on("submitSuccess.ufForm", function() { diff --git a/app/sprinkles/account/assets/userfrosting/js/pages/resend-verification.js b/app/sprinkles/account/assets/userfrosting/js/pages/resend-verification.js index 5c3eaf88e..411cdfb57 100644 --- a/app/sprinkles/account/assets/userfrosting/js/pages/resend-verification.js +++ b/app/sprinkles/account/assets/userfrosting/js/pages/resend-verification.js @@ -10,7 +10,7 @@ $(document).ready(function() { // TODO: Process form $("#request-verification-email").ufForm({ - validators: page.validators.resend_verification, + validator: page.validators.resend_verification, msgTarget: $("#alerts-page") }).on("submitSuccess.ufForm", function() { // Forward to login page on success diff --git a/app/sprinkles/account/assets/userfrosting/js/pages/set-or-reset-password.js b/app/sprinkles/account/assets/userfrosting/js/pages/set-or-reset-password.js index 39cfd1683..74b675531 100644 --- a/app/sprinkles/account/assets/userfrosting/js/pages/set-or-reset-password.js +++ b/app/sprinkles/account/assets/userfrosting/js/pages/set-or-reset-password.js @@ -9,7 +9,7 @@ $(document).ready(function() { $("#set-or-reset-password").ufForm({ - validators: page.validators.set_password, + validator: page.validators.set_password, msgTarget: $("#alerts-page") }).on("submitSuccess.ufForm", function() { // Forward to home page on success diff --git a/app/sprinkles/account/assets/userfrosting/js/pages/sign-in.js b/app/sprinkles/account/assets/userfrosting/js/pages/sign-in.js index 40a862813..23396be1a 100644 --- a/app/sprinkles/account/assets/userfrosting/js/pages/sign-in.js +++ b/app/sprinkles/account/assets/userfrosting/js/pages/sign-in.js @@ -31,7 +31,7 @@ $(document).ready(function() { } $("#sign-in").ufForm({ - validators: page.validators.login, + validator: page.validators.login, msgTarget: $("#alerts-page") }).on("submitSuccess.ufForm", function(event, data, textStatus, jqXHR) { redirectOnLogin(jqXHR); diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js index d701d8145..b90121831 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js @@ -43,7 +43,7 @@ function attachGroupForm() { // Set up the form for submission form.ufForm({ - validators: page.validators + validator: page.validators }).on("submitSuccess.ufForm", function() { // Reload page on success window.location.reload(); diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js index 0e32651d9..2edff7172 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js @@ -34,7 +34,7 @@ function attachRoleForm() { // Set up the form for submission form.ufForm({ - validators: page.validators + validator: page.validators }).on("submitSuccess.ufForm", function() { // Reload page on success window.location.reload(); @@ -88,8 +88,8 @@ function bindRoleButtons(el) { }); // Set up form for submission - form.ufForm({ - }).on("submitSuccess.ufForm", function() { + form.ufForm() + .on("submitSuccess.ufForm", function() { // Reload page on success window.location.reload(); }); diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js index 2e153e51a..8668f44ef 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js @@ -17,7 +17,7 @@ function attachUserForm() { // Set up the form for submission form.ufForm({ - validators: page.validators + validator: page.validators }).on("submitSuccess.ufForm", function() { // Reload page on success window.location.reload(); @@ -182,8 +182,8 @@ function updateUser(userName, fieldName, fieldValue) { }); // Set up form for submission - form.ufForm({ - }).on("submitSuccess.ufForm", function() { + form.ufForm() + .on("submitSuccess.ufForm", function() { // Reload page on success window.location.reload(); }); @@ -207,7 +207,7 @@ function updateUser(userName, fieldName, fieldValue) { // Set up form for submission form.ufForm({ - validators: page.validators + validator: page.validators }).on("submitSuccess.ufForm", function() { // Reload page on success window.location.reload(); From bd30fa8469606f87ace9a8f46cc9cf3ab58c8932 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 20 Mar 2018 21:05:44 -0400 Subject: [PATCH 053/237] Move User registration out of the `AccountController` #793 --- CHANGELOG.md | 1 + .../account/src/Account/Registration.php | 332 +++++++++++++ .../account/src/Bakery/CreateAdminUser.php | 52 +- .../src/Controller/AccountController.php | 466 +++++++----------- .../account/tests/Unit/RegistrationTest.php | 131 +++++ 5 files changed, 680 insertions(+), 302 deletions(-) create mode 100644 app/sprinkles/account/src/Account/Registration.php create mode 100644 app/sprinkles/account/tests/Unit/RegistrationTest.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fb38f9bd..700446c2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle. - Re-written Migrator. The migrator is now detached from the console and Bakery. The migrator is now included in the ServicesProvider and included in the `Core` sprinkle. (#795) - Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace. +- Move User registration out of the `AccountController` (#793) ### Deprecated - Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration`. diff --git a/app/sprinkles/account/src/Account/Registration.php b/app/sprinkles/account/src/Account/Registration.php new file mode 100644 index 000000000..bdf3ea70c --- /dev/null +++ b/app/sprinkles/account/src/Account/Registration.php @@ -0,0 +1,332 @@ +userdata = $userdata; + $this->ci = $ci; + + $this->setDefaults(); + } + + /** + * Register a new user + * + * @return \UserFrosting\Sprinkle\Account\Database\Models\User The created user + */ + public function register() + { + // Validate the userdata + $this->validate(); + + // Set default group + $defaultGroup = $this->ci->classMapper->staticMethod('group', 'where', 'slug', $this->defaultGroup)->first(); + + if (!$defaultGroup) { + $e = new HttpException("Account registration is not working because the default group '{$this->defaultGroup}' does not exist."); + $e->addUserMessage('ACCOUNT.REGISTRATION_BROKEN'); + throw $e; + } + + $this->setUserProperty('group_id', $defaultGroup->id); + + // Hash password + $this->hashPassword(); + + // Set verified flag + $this->setUserProperty('flag_verified', !$this->getRequireEmailVerification()); + + // All checks passed! log events/activities, create user, and send verification email (if required) + // Begin transaction - DB will be rolled back if an exception occurs + $user = Capsule::transaction(function() { + // Log throttleable event + $this->ci->throttler->logEvent('registration_attempt'); + + // Create the user + $user = $this->ci->classMapper->createInstance('user', $this->userdata); + + // Store new user to database + $user->save(); + + // Create activity record + $this->ci->userActivityLogger->info("User {$user->user_name} registered for a new account.", [ + 'type' => 'sign_up', + 'user_id' => $user->id + ]); + + // Load default roles + $defaultRoles = $this->ci->classMapper->staticMethod('role', 'whereIn', 'slug', $this->defaultRoles)->get(); + $defaultRoleIds = $defaultRoles->pluck('id')->all(); + + // Attach default roles + $user->roles()->attach($defaultRoleIds); + + // Verification email + if ($this->requireEmailVerification) { + $this->sendVerificarionEmail($user); + } + + return $user; + }); + + return $user; + } + + /** + * Validate the user name and email is unique + * + * @throws HttpException If data doesn't validate + * @return bool Returns true if the data is valid + */ + public function validate() + { + // Make sure all required fields are defined + foreach ($this->requiredProperties as $property) { + if (!isset($this->userdata[$property])) { + $e = new HttpException("Account can't be registrated as '$property' is required to create a new user."); + $e->addUserMessage('USERNAME.IN_USE'); + throw $e; + } + } + + // Check if username is unique + if (!$this->usernameIsUnique($this->userdata['user_name'])) { + $e = new HttpException(); + $e->addUserMessage('USERNAME.IN_USE'); + throw $e; + } + + // Check if email is unique + if (!$this->emailIsUnique($this->userdata['email'])) { + $e = new HttpException(); + $e->addUserMessage('EMAIL.IN_USE'); + throw $e; + } + + // Validate password requirements + // !TODO + + return true; + } + + /** + * Check Unique Username + * Make sure the username is not already in use + * + * @param string $username + * @return bool Return true if username is unique + */ + public function usernameIsUnique($username) + { + return !($this->ci->classMapper->staticMethod('user', 'findUnique', $username, 'user_name')); + } + + /** + * Check Unique Email + * Make sure the email is not already in use + * + * @param string $email + * @return bool Return true if email is unique + */ + public function emailIsUnique($email) + { + return !($this->ci->classMapper->staticMethod('user', 'findUnique', $email, 'email')); + } + + /** + * Hash the user password in the userdata array + * @return void + */ + protected function hashPassword() + { + // Hash password + $this->userdata['password'] = Password::hash($this->userdata['password']); + } + + /** + * Set default value from config + */ + protected function setDefaults() + { + $this->verified = $this->ci->config['site.registration.require_email_verification']; + $this->requireEmailVerification = $this->ci->config['site.registration.require_email_verification']; + $this->defaultGroup = $this->ci->config['site.registration.user_defaults.group']; + $this->defaultRoles = $this->ci->classMapper->staticMethod('role', 'getDefaultSlugs'); + } + + /** + * Send verification email for specified user + * + * @param User $user The user to send the email for + * @return void + */ + protected function sendVerificarionEmail(User $user) + { + // Try to generate a new verification request + $verification = $this->ci->repoVerification->create($user, $this->ci->config['verification.timeout']); + + // Create and send verification email + $message = new TwigMailMessage($this->ci->view, 'mail/verify-account.html.twig'); + + $message->from($this->ci->config['address_book.admin']) + ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) + ->addParams([ + 'user' => $user, + 'token' => $verification->getToken() + ]); + + $this->ci->mailer->send($message); + } + + /** + * @return bool + */ + public function getRequireEmailVerification() + { + return $this->requireEmailVerification; + } + + /** + * @param bool $requireEmailVerification + * @return static + */ + public function setRequireEmailVerification($requireEmailVerification) + { + $this->requireEmailVerification = $requireEmailVerification; + return $this; + } + + /** + * @return string + */ + public function getDefaultGroup() + { + return $this->defaultGroup; + } + + /** + * @param string $defaultGroup + * @return static + */ + public function setDefaultGroup($defaultGroup) + { + $this->defaultGroup = $defaultGroup; + return $this; + } + + /** + * @return array + */ + public function getDefaultRoles() + { + return $this->defaultRoles; + } + + /** + * @param array $defaultRoles + * @return static + */ + public function setDefaultRoles($defaultRoles) + { + $this->defaultRoles = $defaultRoles; + return $this; + } + + /** + * @return array + */ + public function getUserdata() + { + return $this->userdata; + } + + /** + * @param array $userdata + * + * @return static + */ + public function setUserdata($userdata) + { + $this->userdata = $userdata; + return $this; + } + + /** + * Define a user property + * + * @param string $property The property to set + * @param mixed $value The property value + */ + public function setUserProperty($property, $value) + { + $this->userdata[$property] = $value; + } +} \ No newline at end of file diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index 995e6b842..efdb4e84d 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -12,9 +12,8 @@ use Symfony\Component\Console\Output\OutputInterface; use UserFrosting\System\Bakery\BaseCommand; use UserFrosting\System\Bakery\DatabaseTest; +use UserFrosting\Sprinkle\Account\Account\Registration; use UserFrosting\Sprinkle\Account\Database\Models\User; -use UserFrosting\Sprinkle\Account\Database\Models\Role; -use UserFrosting\Sprinkle\Account\Facades\Password; /** * Create root user CLI command. @@ -41,7 +40,6 @@ protected function configure() { $this->setName('create-admin') ->setDescription('Create the initial admin (root) user account') - ->addOption('force', 'f', InputOption::VALUE_NONE, 'If admin user already exist, delete user and recreate it again') ->addOption('username', null, InputOption::VALUE_OPTIONAL, 'The admin user username') ->addOption('email', null, InputOption::VALUE_OPTIONAL, 'The admin user email') ->addOption('password', null, InputOption::VALUE_OPTIONAL, 'The admin user password') @@ -56,9 +54,6 @@ protected function execute(InputInterface $input, OutputInterface $output) { $this->io->title('Root account setup'); - // Get the options - $force = $input->getOption('force'); - // Need the database try { $this->io->writeln('Testing database connection', OutputInterface::VERBOSITY_VERBOSE); @@ -92,39 +87,38 @@ protected function execute(InputInterface $input, OutputInterface $output) // Make sure that there are no users currently in the user table // We setup the root account here so it can be done independent of the version check - if (User::count() > 0 && !$force) { + if (User::count() > 0) { $this->io->note("Table 'users' is not empty. Skipping root account setup. To set up the root account again, please truncate or drop the table and try again."); } else { $this->io->writeln("Please answer the following questions to create the root account:\n"); + // Don't need password confirmation if it's defined as an option + $requireConfirmation = ($input->getOption('password') == '') ? true : false; + // Get the account details $username = $this->askUsername($input->getOption('username')); $email = $this->askEmail($input->getOption('email')); $firstName = $this->askFirstName($input->getOption('firstName')); $lastName = $this->askLastName($input->getOption('lastName')); - $password = $this->askPassword($input->getOption('password')); + $password = $this->askPassword($input->getOption('password'), $requireConfirmation); // Ok, now we've got the info and we can create the new user. $this->io->write("\nSaving the root user details..."); - $rootUser = new User([ + $registration = new Registration($this->ci, [ 'user_name' => $username, 'email' => $email, 'first_name' => $firstName, 'last_name' => $lastName, - 'password' => Password::hash($password) + 'password' => $password ]); - $rootUser->save(); - - $defaultRoles = [ - 'user' => Role::where('slug', 'user')->first(), - 'group-admin' => Role::where('slug', 'group-admin')->first(), - 'site-admin' => Role::where('slug', 'site-admin')->first() - ]; - - foreach ($defaultRoles as $slug => $role) { - if ($role) { - $rootUser->roles()->attach($role->id); - } + $registration->setRequireEmailVerification(false); + $registration->setDefaultRoles(['user', 'group-admin', 'site-admin']); + + try { + $rootUser = $registration->register(); + } catch (\Exception $e) { + $this->io->error($e->getMessage()); + exit(1); } $this->io->success('Root user creation successful!'); @@ -177,7 +171,7 @@ protected function validateUsername($username) /** * Ask for the email and return a valid one * - * @param string $mail The base/default email + * @param string $email The base/default email * @return string The validated email */ protected function askEmail($email = '') @@ -277,11 +271,12 @@ protected function validateLastName($lastName) * Ask for the password and return a valid one * * @param string $password The base/default password + * @param bool $requireConfirmation (default true) * @return string The validated password */ - protected function askPassword($password = '') + protected function askPassword($password = '', $requireConfirmation = true) { - while (!isset($password) || !$this->validatePassword($password) || !$this->confirmPassword($password)) { + while (!isset($password) || !$this->validatePassword($password) || !$this->confirmPassword($password, $requireConfirmation)) { $password = $this->io->askHidden('Enter password (12-255 characters)'); } return $password; @@ -308,10 +303,15 @@ protected function validatePassword($password) * Ask for password confirmation * * @param string $passwordToConfirm + * @param bool $requireConfirmation (default true) * @return bool Is the password confirmed or not */ - protected function confirmPassword($passwordToConfirm) + protected function confirmPassword($passwordToConfirm, $requireConfirmation = true) { + if (!$requireConfirmation) { + return true; + } + while (!isset($password)) { $password = $this->io->askHidden('Please re-enter the chosen password'); } diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 4f228c4da..fb15d45c0 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -16,6 +16,7 @@ use UserFrosting\Fortress\RequestSchema; use UserFrosting\Fortress\ServerSideValidator; use UserFrosting\Fortress\Adapter\JqueryValidationAdapter; +use UserFrosting\Sprinkle\Account\Account\Registration; use UserFrosting\Sprinkle\Account\Controller\Exception\SpammyRequestException; use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Account\Util\Util as AccountUtil; @@ -25,7 +26,6 @@ use UserFrosting\Sprinkle\Core\Util\Captcha; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; -use UserFrosting\Support\Exception\HttpException; /** * Controller class for /account/* URLs. Handles account-related activities, including login, registration, password recovery, and account settings. @@ -36,19 +36,19 @@ class AccountController extends SimpleController { /** - * Check a username for availability. + * Check a username for availability. * - * This route is throttled by default, to discourage abusing it for account enumeration. - * This route is "public access". + * This route is throttled by default, to discourage abusing it for account enumeration. + * This route is "public access". * - * AuthGuard: false - * Route: /account/check-username - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/check-username + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function checkUsername(Request $request, Response $response, $args) { @@ -105,20 +105,20 @@ public function checkUsername(Request $request, Response $response, $args) } /** - * Processes a request to cancel a password reset request. + * Processes a request to cancel a password reset request. * - * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves. - * Processes the request from the password reset link, checking that: - * 1. The provided token is associated with an existing user account, who has a pending password reset request. + * This is provided so that users can cancel a password reset request, if they made it in error or if it was not initiated by themselves. + * Processes the request from the password reset link, checking that: + * 1. The provided token is associated with an existing user account, who has a pending password reset request. * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/set-password/deny + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function denyResetPassword(Request $request, Response $response, $args) { @@ -169,18 +169,17 @@ public function denyResetPassword(Request $request, Response $response, $args) * Note that we have removed the requirement that a password reset request not already be in progress. * This is because we need to allow users to re-request a reset, even if they lose the first reset email. * This route is "public access". - * Request type: POST * @todo require additional user information * @todo prevent password reset requests for root account? * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/forgot-password + * Route Name: {none} + * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function forgotPassword(Request $request, Response $response, $args) { @@ -266,16 +265,15 @@ public function forgotPassword(Request $request, Response $response, $args) * Returns a modal containing account terms of service. * * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages. - * Request type: GET * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /modals/account/tos + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function getModalAccountTos(Request $request, Response $response, $args) { @@ -285,16 +283,14 @@ public function getModalAccountTos(Request $request, Response $response, $args) /** * Generate a random captcha, store it to the session, and return the captcha image. * + * AuthGuard: false + * Route: /account/captcha + * Route Name: {none} * Request type: GET - * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function imageCaptcha(Request $request, Response $response, $args) { @@ -317,16 +313,15 @@ public function imageCaptcha(Request $request, Response $response, $args) * 5. The user account is enabled and verified. * 6. The user entered a valid username/email and password. * This route, by definition, is "public access". - * Request type: POST * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/login + * Route Name: {none} + * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function login(Request $request, Response $response, $args) { @@ -414,16 +409,14 @@ public function login(Request $request, Response $response, $args) /** * Log the user out completely, including destroying any "remember me" token. * + * AuthGuard: true + * Route: /account/logout + * Route Name: {none} * Request type: GET - * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function logout(Request $request, Response $response, $args) { @@ -440,16 +433,15 @@ public function logout(Request $request, Response $response, $args) * * This creates a simple form to allow users who forgot their password to have a time-limited password reset link emailed to them. * By default, this is a "public page" (does not require authentication). - * Request type: GET * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/forgot-password + * Route Name: forgot-password + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function pageForgotPassword(Request $request, Response $response, $args) { @@ -472,16 +464,16 @@ public function pageForgotPassword(Request $request, Response $response, $args) * * This allows new (non-authenticated) users to create a new account for themselves on your website (if enabled). * By definition, this is a "public page" (does not require authentication). - * Request type: GET * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * checkEnvironment + * Route: /account/register + * Route Name: register + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function pageRegister(Request $request, Response $response, $args) { @@ -529,16 +521,15 @@ public function pageRegister(Request $request, Response $response, $args) * * This is a form that allows users who lost their account verification link to have the link resent to their email address. * By default, this is a "public page" (does not require authentication). - * Request type: GET * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/resend-verification + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function pageResendVerification(Request $request, Response $response, $args) { @@ -559,16 +550,15 @@ public function pageResendVerification(Request $request, Response $response, $ar * Reset password page. * * Renders the new password page for password reset requests. - * Request type: GET * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/set-password/confirm + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function pageResetPassword(Request $request, Response $response, $args) { @@ -594,16 +584,15 @@ public function pageResetPassword(Request $request, Response $response, $args) * * Renders the page where new users who have had accounts created for them by another user, can set their password. * By default, this is a "public page" (does not require authentication). - * Request type: GET * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function pageSetPassword(Request $request, Response $response, $args) { @@ -630,16 +619,15 @@ public function pageSetPassword(Request $request, Response $response, $args) * Provides a form for users to modify various properties of their account, such as name, email, locale, etc. * Any fields that the user does not have permission to modify will be automatically disabled. * This page requires authentication. - * Request type: GET * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: true + * Route: /account/settings + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function pageSettings(Request $request, Response $response, $args) { @@ -684,16 +672,16 @@ public function pageSettings(Request $request, Response $response, $args) * * This allows existing users to sign in. * By definition, this is a "public page" (does not require authentication). - * Request type: GET * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * checkEnvironment + * Route: /account/sign-in + * Route Name: login + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function pageSignIn(Request $request, Response $response, $args) { @@ -730,16 +718,15 @@ public function pageSignIn(Request $request, Response $response, $args) * 1. They have the necessary permissions to update the posted field(s); * 2. The submitted data is valid. * This route requires authentication. - * Request type: POST * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: true + * Route: /account/settings/profile + * Route Name: {none} + * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function profile(Request $request, Response $response, $args) { @@ -824,17 +811,16 @@ public function profile(Request $request, Response $response, $args) * 7. The username and email are not already taken. * Automatically sends an activation link upon success, if account activation is enabled. * This route is "public access". - * Request type: POST * Returns the User Object for the user record that was created. * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/register + * Route Name: {none} + * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function register(Request $request, Response $response, $args) { @@ -901,17 +887,6 @@ public function register(Request $request, Response $response, $args) return $response->withStatus(429); } - // Check if username or email already exists - if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) { - $ms->addMessageTranslated('danger', 'USERNAME.IN_USE', $data); - $error = true; - } - - if ($classMapper->staticMethod('user', 'findUnique', $data['email'], 'email')) { - $ms->addMessageTranslated('danger', 'EMAIL.IN_USE', $data); - $error = true; - } - // Check captcha, if required if ($config['site.registration.captcha']) { $captcha = new Captcha($this->ci->session, $this->ci->config['session.keys.captcha']); @@ -929,80 +904,24 @@ public function register(Request $request, Response $response, $args) unset($data['captcha']); unset($data['passwordc']); - if ($config['site.registration.require_email_verification']) { - $data['flag_verified'] = false; - } else { - $data['flag_verified'] = true; - } - - // Load default group - $groupSlug = $config['site.registration.user_defaults.group']; - $defaultGroup = $classMapper->staticMethod('group', 'where', 'slug', $groupSlug)->first(); + // Now that we check the form, we can register the actual user + $registration = new Registration($this->ci, $data); - if (!$defaultGroup) { - $e = new HttpException("Account registration is not working because the default group '$groupSlug' does not exist."); - $e->addUserMessage('ACCOUNT.REGISTRATION_BROKEN'); - throw $e; + try { + $user = $registration->register(); + } catch (\Exception $e) { + $ms->addMessageTranslated('danger', $e->getMessage(), $data); + $error = true; } - // Set default group - $data['group_id'] = $defaultGroup->id; - - // Set locale - $data['locale'] = $data['locale']; - - // Hash password - $data['password'] = Password::hash($data['password']); - - // All checks passed! log events/activities, create user, and send verification email (if required) - // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $ms, $config, $throttler) { - // Log throttleable event - $throttler->logEvent('registration_attempt'); - - // Create the user - $user = $classMapper->createInstance('user', $data); - - // Store new user to database - $user->save(); - - // Create activity record - $this->ci->userActivityLogger->info("User {$user->user_name} registered for a new account.", [ - 'type' => 'sign_up', - 'user_id' => $user->id - ]); - - // Load default roles - $defaultRoleSlugs = $classMapper->staticMethod('role', 'getDefaultSlugs'); - $defaultRoles = $classMapper->staticMethod('role', 'whereIn', 'slug', $defaultRoleSlugs)->get(); - $defaultRoleIds = $defaultRoles->pluck('id')->all(); - - // Attach default roles - $user->roles()->attach($defaultRoleIds); - - // Verification email - if ($config['site.registration.require_email_verification']) { - // Try to generate a new verification request - $verification = $this->ci->repoVerification->create($user, $config['verification.timeout']); - - // Create and send verification email - $message = new TwigMailMessage($this->ci->view, 'mail/verify-account.html.twig'); - - $message->from($config['address_book.admin']) - ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) - ->addParams([ - 'user' => $user, - 'token' => $verification->getToken() - ]); - - $this->ci->mailer->send($message); - - $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE2', $user->toArray()); - } else { - // No verification required - $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE1'); - } - }); + // Success message + if ($config['site.registration.require_email_verification']) { + // Verification required + $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE2', $user->toArray()); + } else { + // No verification required + $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE1'); + } return $response->withStatus(200); } @@ -1016,16 +935,15 @@ public function register(Request $request, Response $response, $args) * 3. The user account is not already verified; * 4. The submitted data is valid. * This route is "public access". - * Request type: POST * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/resend-verification + * Route Name: {none} + * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function resendVerification(Request $request, Response $response, $args) { @@ -1113,16 +1031,15 @@ public function resendVerification(Request $request, Response $response, $args) * 3. The token has not expired; * 4. The submitted data (new password) is valid. * This route is "public access". - * Request type: POST * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/set-password + * Route Name: {none} + * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function setPassword(Request $request, Response $response, $args) { @@ -1190,16 +1107,15 @@ public function setPassword(Request $request, Response $response, $args) * 2. They have the necessary permissions to update the posted field(s); * 3. The submitted data is valid. * This route requires authentication. - * Request type: POST * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: true + * Route: /account/settings + * Route Name: settings + * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function settings(Request $request, Response $response, $args) { @@ -1291,17 +1207,16 @@ public function settings(Request $request, Response $response, $args) * Suggest an available username for a specified first/last name. * * This route is "public access". - * Request type: GET * @todo Can this route be abused for account enumeration? If so we should throttle it as well. * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/suggest-username + * Route Name: {none} + * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function suggestUsername(Request $request, Response $response, $args) { @@ -1328,15 +1243,14 @@ public function suggestUsername(Request $request, Response $response, $args) * 2. The user account is not already verified; * This route is "public access". * - * AuthGuard: false - * Route: /account/set-password/deny - * Route Name: {none} - * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args - * @return void + * AuthGuard: false + * Route: /account/verify + * Route Name: {none} * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args + * @return void */ public function verify(Request $request, Response $response, $args) { diff --git a/app/sprinkles/account/tests/Unit/RegistrationTest.php b/app/sprinkles/account/tests/Unit/RegistrationTest.php new file mode 100644 index 000000000..75ce994a6 --- /dev/null +++ b/app/sprinkles/account/tests/Unit/RegistrationTest.php @@ -0,0 +1,131 @@ +setupTestDatabase(); + $this->refreshDatabase(); + } + + /** + * testNormalRegistration + */ + public function testNormalRegistration() + { + // userActivityLogger will receive something, but won't be able to handle it since there's no session. So we mock it + $this->ci->userActivityLogger = m::mock('\Monolog\Logger'); + $this->ci->userActivityLogger->shouldReceive('info')->once(); + + // Tests can't mail properly + $this->ci->config['site.registration.require_email_verification'] = false; + + // Genereate user data + $fakeUserData = [ + 'user_name' => 'FooBar', + 'first_name' => 'Foo', + 'last_name' => 'Bar', + 'email' => 'Foo@Bar.com', + 'password' => 'FooBarFooBar123' + ]; + + // Get class + $registration = new Registration($this->ci, $fakeUserData); + $this->assertInstanceOf(Registration::class, $registration); + + // Register user + $user = $registration->register(); + + // Registration should return a valid user + $this->assertInstanceOf(User::class, $user); + $this->assertEquals('FooBar', $user->user_name); + + // We try to register the same user again. Should throw an error + $registration = new Registration($this->ci, $fakeUserData); + $this->expectException(HttpException::class); + $validation = $registration->validate(); + + // Should throw email error if we change the username + $fakeUserData['user_name'] = 'BarFoo'; + $registration = new Registration($this->ci, $fakeUserData); + $this->expectException(HttpException::class); + $validation = $registration->validate(); + } + + /** + * Test validation works + */ + public function testValidation() + { + // Reset database + $this->refreshDatabase(); + + $registration = new Registration($this->ci, [ + 'user_name' => 'FooBar', + 'first_name' => 'Foo', + 'last_name' => 'Bar', + 'email' => 'Foo@Bar.com', + 'password' => 'FooBarFooBar123' + ]); + + // Validate user. Shouldn't tell us the username is already in use since we reset the database + $validation = $registration->validate(); + $this->assertTrue($validation); + } + + /** + * Test the $requiredProperties property + */ + public function testMissingFields() + { + // Reset database + $this->refreshDatabase(); + + $registration = new Registration($this->ci, [ + 'user_name' => 'FooBar', + //'first_name' => 'Foo', + 'last_name' => 'Bar', + 'email' => 'Foo@Bar.com', + 'password' => 'FooBarFooBar123' + ]); + + // Validate user. Shouldn't tell us the username is already in use since we reset the database + $this->expectException(HttpException::class); + $validation = $registration->validate(); + } +} \ No newline at end of file From 3f5e9c51a5d755fa4f35e4e6fb345ae9c99e1c44 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 20 Mar 2018 21:09:39 -0400 Subject: [PATCH 054/237] Include Vagrant integration directly inside UF #829 --- CHANGELOG.md | 1 + vagrant/after.sh | 2 +- vagrant/doc.md | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 700446c2b..9abe3aefa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `RefreshDatabase` test Trait to use a fresh database for a test - Added `TestDatabase` test Trait to use the in memory database for a test - Implement `withRaw`, `withSum`, `withAvg`, `withMin`, `withMax` (see https://github.com/laravel/framework/pull/16815) +- Include Vagrant integration directly inside UF (#829) ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle. diff --git a/vagrant/after.sh b/vagrant/after.sh index 36f4a6a58..b5d0ace42 100644 --- a/vagrant/after.sh +++ b/vagrant/after.sh @@ -24,7 +24,7 @@ cp app/sprinkles.example.json app/sprinkles.json # Install UserFrosting php bakery debug php bakery migrate -# php bakery create-admin !!! Requires fix for #808 https://github.com/userfrosting/UserFrosting/issues/808 +php bakery create-admin --username="admin" --email="admin@userfrosting.test" --password="adminadmin12" --firstName="Admin" --lastName="istrator" php bakery build-assets echo "\n\nUserFrosting is ready at http://192.168.10.10/" \ No newline at end of file diff --git a/vagrant/doc.md b/vagrant/doc.md index dde4b41f4..1f5b30e6c 100644 --- a/vagrant/doc.md +++ b/vagrant/doc.md @@ -23,7 +23,7 @@ $ vagrant up * Access UserFrosting at `http://192.168.10.10/` * Username: **admin** -* Password: **adminadmin** +* Password: **adminadmin12** ## Additional commands: * Access your Linux server from the command line: From ae6f47637ec90c1ae0ac1527d14edd35b470b5e7 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 28 Mar 2018 21:36:29 -0400 Subject: [PATCH 055/237] Add batch number to `migrate:status` command (ref #795) --- .../account/src/Bakery/CreateAdminUser.php | 2 +- .../core/src/Bakery/MigrateStatusCommand.php | 23 +++++++++++-------- .../Migrator/DatabaseMigrationRepository.php | 23 ++++++++++++------- .../Migrator/MigrationRepositoryInterface.php | 13 +++++++---- .../core/src/Database/Migrator/Migrator.php | 6 ++--- .../BakeryMigrateStatusCommandTest.php | 16 +++++++++---- .../DatabaseMigratorIntegrationTest.php | 2 +- .../Integration/DatabaseMigratorTest.php | 10 ++++---- .../Integration/MigrationRepositoryTest.php | 6 +++-- 9 files changed, 62 insertions(+), 39 deletions(-) diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index efdb4e84d..913954be1 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -77,7 +77,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } // Make sure the required migrations have been run - $ranMigrations = $repository->getRan(); + $ranMigrations = $repository->getMigrationsList(); foreach ($this->dependencies as $migration) { if (!in_array($migration, $ranMigrations)) { $this->io->error("Migration `$migration` doesn't appear to have been run! Make sure all migrations are up to date by using the `php bakery migrate` command."); diff --git a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php index 8718c8711..6169f1898 100644 --- a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php @@ -7,6 +7,7 @@ */ namespace UserFrosting\Sprinkle\Core\Bakery; +use Illuminate\Support\Collection; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; @@ -47,20 +48,21 @@ protected function execute(InputInterface $input, OutputInterface $output) // Get ran migrations. If repository doesn't exist, there's no ran if (!$migrator->repositoryExists()) { - $ran = []; + $ranArray = []; } else { - $ran = $migrator->getRepository()->getRan(); + $ran = $migrator->getRepository()->getMigrations(); + $ranArray = $ran->pluck('migration')->all(); } // Get available migrations and calculate pending one $available = $migrator->getAvailableMigrations(); - $pending = $migrator->pendingMigrations($available, $ran); + $pending = $migrator->pendingMigrations($available, $ranArray); // Display ran migrations $this->io->section("Installed migrations"); - if (count($ran) > 0) { + if (count($ranArray) > 0) { $this->io->table( - ['Migration', 'Available?'], + ['Migration', 'Available?', 'Batch'], $this->getStatusFor($ran, $available) ); } else { @@ -80,18 +82,19 @@ protected function execute(InputInterface $input, OutputInterface $output) * Return an array of [migration, available] association. * A migration is available if it's in the available stack (class is in the Filesystem) * - * @param array $ran The ran migrations + * @param Collection $ran The ran migrations * @param array $available The available migrations * @return array An array of [migration, available] association */ - protected function getStatusFor(array $ran, array $available) + protected function getStatusFor(Collection $ran, array $available) { return collect($ran)->map(function ($migration) use ($available) { - if (in_array($migration, $available)) { - return [$migration, 'Y']; + if (in_array($migration->migration, $available)) { + $available = 'Yes'; } else { - return [$migration, 'N']; + $available = 'No'; } + return [$migration->migration, $available, $migration->batch]; })->toArray(); } } diff --git a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php index fbce88977..fe1d6d76d 100644 --- a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php +++ b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php @@ -49,27 +49,34 @@ public function __construct(Capsule $db, $table = "migrations") } /** - * Get the ran migrations. + * Get the list of ran migrations * + * @param int $steps Number of batch to return + * @param string $order asc|desc * @return array An array of migration class names in the order they where ran */ - public function getRan() + public function getMigrationsList($steps = -1, $order = 'asc') { - return $this->table() - ->orderBy('id', 'asc') - ->pluck('migration')->all(); + return $this->getMigrations($steps, $order)->pluck('migration')->all(); } /** * Get list of migrations. * * @param int $steps Number of batch to return + * @param string $order asc|desc * @return array */ - public function getMigrations($steps) + public function getMigrations($steps = -1, $order = 'asc') { - $batch = max($this->getNextBatchNumber() - $steps, 1); - return $this->table()->where('batch', '>=', $batch)->orderBy('id', 'desc')->get()->pluck('migration')->all(); + $query = $this->table(); + + if ($steps > 0) { + $batch = max($this->getNextBatchNumber() - $steps, 1); + $query = $query->where('batch', '>=', $batch); + } + + return $query->orderBy('id', $order)->get(); } /** diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php index 1fcbaf272..e2dac954c 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php @@ -15,19 +15,22 @@ interface MigrationRepositoryInterface { /** - * Get the ran migrations. + * Get the list of ran migrations * - * @return array An array of migration class names + * @param int $steps Number of batch to return + * @param string $order asc|desc + * @return array An array of migration class names in the order they where ran */ - public function getRan(); + public function getMigrationsList($steps = -1, $order = 'asc'); /** * Get list of migrations. * - * @param int $steps + * @param int $steps Number of batch to return + * @param string $order asc|desc * @return array */ - public function getMigrations($steps); + public function getMigrations($steps = -1, $order = 'asc'); /** * Get the last migration batch. diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index c10f56a22..164f6552b 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -76,7 +76,7 @@ public function run(array $options = []) $availableMigrations = $this->getAvailableMigrations(); // Get ran migrations - $ranMigrations = $this->repository->getRan(); + $ranMigrations = $this->repository->getMigrationsList(); // Get outstanding migrations classes that requires to be run up $pendingMigrations = $this->pendingMigrations($availableMigrations, $ranMigrations); @@ -213,7 +213,7 @@ protected function getMigrationsForRollback(array $options) { $steps = Arr::get($options, 'steps', 0); if ($steps > 0) { - return $this->repository->getMigrations($steps); + return $this->repository->getMigrationsList($steps, 'desc'); } else { return $this->repository->getLast(); } @@ -273,7 +273,7 @@ public function reset($pretend = false) // "empty" state and ready to be migrated "up" again. // // !TODO :: Should compare to the install list to make sure no outstanding migration (ran, but with no migraiton class anymore) still exist in the db - $migrations = array_reverse($this->repository->getRan()); + $migrations = array_reverse($this->repository->getMigrationsList()); if (count($migrations) === 0) { return []; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php index 95f1a6e24..05078c486 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php @@ -28,7 +28,7 @@ public function testBasicMigrationsCallMigratorWithProperArguments() // Define dummy data $available = ['foo', 'bar', 'oof', 'rab']; - $installed = ['foo', 'bar']; + $installed = $this->getInstalledMigrationStub()->pluck('migration')->all(); $pending = ['oof', 'rab']; // Set expectations @@ -38,7 +38,7 @@ public function testBasicMigrationsCallMigratorWithProperArguments() $migrator->shouldReceive('getAvailableMigrations')->once()->andReturn($available); $migrator->shouldReceive('pendingMigrations')->once()->with($available, $installed)->andReturn($pending); - $repository->shouldReceive('getRan')->once()->andReturn($installed); + $repository->shouldReceive('getMigrations')->once()->andReturn($this->getInstalledMigrationStub()); // Run command $commandTester = $this->runCommand($migrator, []); @@ -52,7 +52,7 @@ public function testDatabaseMayBeSet() // Define dummy data $available = ['foo', 'bar', 'oof', 'rab']; - $installed = ['foo', 'bar']; + $installed = $this->getInstalledMigrationStub()->pluck('migration')->all(); $pending = ['oof', 'rab']; // Set expectations @@ -62,7 +62,7 @@ public function testDatabaseMayBeSet() $migrator->shouldReceive('getAvailableMigrations')->once()->andReturn($available); $migrator->shouldReceive('pendingMigrations')->once()->with($available, $installed)->andReturn($pending); - $repository->shouldReceive('getRan')->once()->andReturn($installed); + $repository->shouldReceive('getMigrations')->once()->andReturn($this->getInstalledMigrationStub()); // Run command $commandTester = $this->runCommand($migrator, ['--database' => 'test']); @@ -91,4 +91,12 @@ protected function runCommand($migrator, $input = []) return $commandTester; } + + protected function getInstalledMigrationStub() + { + return collect([ + (object)['migration' => 'foo', 'batch' => 1, 'sprinkle' => 'foo'], + (object)['migration' => 'bar', 'batch' => 2, 'sprinkle' => 'bar'] + ]); + } } diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php index f37e5e516..8bbc5bdaa 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php @@ -93,7 +93,7 @@ public function testRepository() // N.B.: getLast return the migrations in reverse order (last ran first) $this->assertEquals($this->locator->getMigrations(), $ran); $this->assertEquals(array_reverse($this->locator->getMigrations()), $this->repository->getLast()); - $this->assertEquals($this->locator->getMigrations(), $this->repository->getRan()); + $this->assertEquals($this->locator->getMigrations(), $this->repository->getMigrationsList()); } public function testMigrationsCanBeRolledBack() diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php index cae4cb2d5..5345bb105 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php @@ -91,7 +91,7 @@ public function testMigratorUpWithNoMigrations() $this->locator->shouldReceive('getMigrations')->once()->andReturn([]); // Repository will be asked to return the ran migrations - $this->repository->shouldReceive('getRan')->once()->andReturn([]); + $this->repository->shouldReceive('getMigrationsList')->once()->andReturn([]); $migrations = $this->migrator->run(); $this->assertEmpty($migrations); @@ -113,7 +113,7 @@ public function testMigratorUpWithOnlyPendingMigrations() $this->locator->shouldReceive('getMigrations')->andReturn($testMigrations); // Repository will be asked to return the ran migrations, the next batch number and will log 3 new migrations - $this->repository->shouldReceive('getRan')->andReturn([]); + $this->repository->shouldReceive('getMigrationsList')->andReturn([]); $this->repository->shouldReceive('getNextBatchNumber')->andReturn(1); $this->repository->shouldReceive('log')->times(3)->andReturn(null); @@ -145,7 +145,7 @@ public function testMigratorUpWithOneInstalledMigrations() ]); // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations - $this->repository->shouldReceive('getRan')->andReturn([ + $this->repository->shouldReceive('getMigrationsList')->andReturn([ '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable' ]); $this->repository->shouldReceive('getNextBatchNumber')->andReturn(2); @@ -185,7 +185,7 @@ public function testMigratorUpWithNoPendingMigrations() $this->locator->shouldReceive('getMigrations')->andReturn($testMigrations); // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations - $this->repository->shouldReceive('getRan')->andReturn($testMigrations); + $this->repository->shouldReceive('getMigrationsList')->andReturn($testMigrations); $this->repository->shouldNotReceive('getNextBatchNumber'); $this->repository->shouldNotReceive('log'); @@ -303,7 +303,7 @@ public function testMigratorResetAllInstalledMigrations() $this->locator->shouldReceive('getMigrations')->once()->andReturn($testMigrations); // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations - $this->repository->shouldReceive('getRan')->once()->andReturn($testMigrations); + $this->repository->shouldReceive('getMigrationsList')->once()->andReturn($testMigrations); $this->repository->shouldReceive('delete')->times(3)->andReturn([]); // SchemaBuilder will only create 2 tables diff --git a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php index b1fda8aa2..66e1f7f79 100644 --- a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php @@ -45,14 +45,16 @@ public function setUp() public function testGetRanMigrationsListMigrationsByPackage() { $query = m::mock('stdClass'); + $sortedQuery = m::mock('stdClass'); // Set expectations for the Connection mock $this->repository->getConnection()->shouldReceive('table')->once()->with('migrations')->andReturn($query); // When getRan is called, the $query should be orderedBy batch, then migration and pluck. - $query->shouldReceive('orderBy')->once()->with('id', 'asc')->andReturn(new Collection([['migration' => 'bar']])); + $query->shouldReceive('orderBy')->once()->with('id', 'asc')->andReturn($sortedQuery); + $sortedQuery->shouldReceive('get')->once()->andReturn(new Collection([['migration' => 'bar']])); - $this->assertEquals(['bar'], $this->repository->getRan()); + $this->assertEquals(['bar'], $this->repository->getMigrationsList()); } public function testGetLastBatchNumberReturnsMaxBatch() From 4f29c0b6ebd21a0a2c173ec57a252925d6fea87f Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 29 Mar 2018 17:14:20 -0400 Subject: [PATCH 056/237] Re-added old `seed` method for Migrations, but deprecated it. --- .../core/src/Database/Migrator/Migrator.php | 11 +++++++++++ .../Integration/DatabaseMigratorIntegrationTest.php | 6 +++++- .../Integration/Migrations/DeprecatedClassTable.php | 12 ++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index 164f6552b..0c7ab5dbd 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -12,6 +12,7 @@ use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocatorInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRepositoryInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationDependencyAnalyser as Analyser; +use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Util\BadClassNameException; /** @@ -179,6 +180,16 @@ protected function runUp($migrationClass, $batch, $pretend) $this->repository->log($migrationClass, $batch); $this->note("Migrated: {$migrationClass}"); + + /** + * If the migration has a `seed` method, run it + * @deprecated Since 4.2.0. Use a seeder instead + */ + if (method_exists($migration, 'seed')) { + Debug::debug("Migration `seed` method has been deprecated and will be removed in future versions. Please use a Seeder instead."); + $this->runMigration($migration, 'seed'); + $this->note("Seeded: {$migrationClass}"); + } } /** diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php index 8bbc5bdaa..d391fef22 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php @@ -175,10 +175,14 @@ public function testChangeRepositoryAndDeprecatedClass() $locator = new DeprecatedMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); $this->migrator->setLocator($locator); - // Run up + // Run up. Should also run the seeder $this->migrator->run(); $this->assertTrue($this->schema->hasTable('deprecated_table')); + // Make sure the seeder ran. + // Easiest way to do so it asking the seeder to change the table structure + $this->assertTrue($this->schema->hasColumn('deprecated_table', 'foo')); + // Rollback $this->migrator->rollback(); $this->assertFalse($this->schema->hasTable('deprecated_table')); diff --git a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php index 0b8bb1d5b..c84194dc5 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php @@ -30,4 +30,16 @@ public function down() { $this->schema->dropIfExists('deprecated_table'); } + + /** + * Seed the database. + * + * @return void + */ + public function seed() + { + $this->schema->table('deprecated_table', function (Blueprint $table) { + $table->string('foo')->nullable(); + }); + } } From f5d0913c76d87e883ae7e13876b9e74f2baa9ff3 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 29 Mar 2018 17:19:52 -0400 Subject: [PATCH 057/237] Updated Changelog with latest fix --- CHANGELOG.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 970a19c31..b1bb96f72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,8 +11,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Use locale requested by browser when possible for guests (#718) - Add locale drop down to registration page, with the currently applied locale selected (#718) - Integrated improvements from [v4.0.25-Alpha](#v4025-alpha) -- Added tests for migrator and it's components. -- Added tests for `migrate` Bakery command and sub-commands. - Added `database` option for `migrate` and `migrate:*` Bakery commands - New `isProduction` method for Bakery command to test if app is in production mode - `migrate` and `migrate:*` Bakery command now require confirmation before execution when in production mode. @@ -21,23 +19,27 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `TestDatabase` test Trait to use the in memory database for a test - Implement `withRaw`, `withSum`, `withAvg`, `withMin`, `withMax` (see https://github.com/laravel/framework/pull/16815) - Include Vagrant integration directly inside UF (#829) +- Added arguments to the `create-admin` Bakery command so it can be used in a non-interactive way (#808) +- Added tests for migrator and it's components +- Added tests for `migrate` Bakery command and sub-commands ### Changed -- Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle. -- Re-written Migrator. The migrator is now detached from the console and Bakery. The migrator is now included in the ServicesProvider and included in the `Core` sprinkle. (#795) -- Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace. +- Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle +- Re-written Migrator. The migrator is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider (#795) +- Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace - Move User registration out of the `AccountController` (#793) ### Deprecated -- Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration`. -- Migrations dependencies property should now be a static property. +- Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration` +- Migrations dependencies property should now be a static property +- Deprecated migration `seed` method. Database seeding should now be done using the new Seeder - Trait `\UserFrosting\Tests\DatabaseTransactions` has been deprecated. Tests should now use the `\UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` trait instead. (#826) ### Removed -- The console IO instance is not available anymore in migrations. -- Removed the `io` property from migration classes. -- Removed Bakery `projectRoot` property. Use the `\UserFrosting\ROOT_DIR` constant instead. -- Removed `pretend` option from Bakery `migrate:refresh` and `migrate:reset` commands. +- The console IO instance is not available anymore in migrations +- Removed the `io` property from migration classes +- Removed Bakery `projectRoot` property. Use the `\UserFrosting\ROOT_DIR` constant instead +- Removed `pretend` option from Bakery `migrate:refresh` and `migrate:reset` commands ### Fixed From 32cf37194d4fb2ee56a6b6d36de2f629a551be1a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 29 Mar 2018 18:16:21 -0400 Subject: [PATCH 058/237] Implement #808 - Add arguments to Bakery Setup Also rewrote most of the command. --- CHANGELOG.md | 2 +- .../src/Bakery/{Bake.php => BakeCommand.php} | 2 +- .../{ClearCache.php => ClearCacheCommand.php} | 2 +- .../Bakery/{Debug.php => DebugCommand.php} | 2 +- .../Bakery/{Setup.php => SetupCommand.php} | 180 +++++++++++++----- 5 files changed, 140 insertions(+), 48 deletions(-) rename app/sprinkles/core/src/Bakery/{Bake.php => BakeCommand.php} (98%) rename app/sprinkles/core/src/Bakery/{ClearCache.php => ClearCacheCommand.php} (98%) rename app/sprinkles/core/src/Bakery/{Debug.php => DebugCommand.php} (99%) rename app/sprinkles/core/src/Bakery/{Setup.php => SetupCommand.php} (51%) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1bb96f72..c3c7222e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,7 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `TestDatabase` test Trait to use the in memory database for a test - Implement `withRaw`, `withSum`, `withAvg`, `withMin`, `withMax` (see https://github.com/laravel/framework/pull/16815) - Include Vagrant integration directly inside UF (#829) -- Added arguments to the `create-admin` Bakery command so it can be used in a non-interactive way (#808) +- Added arguments to the `create-admin` and `setup` Bakery commands so it can be used in a non-interactive way (#808) - Added tests for migrator and it's components - Added tests for `migrate` Bakery command and sub-commands diff --git a/app/sprinkles/core/src/Bakery/Bake.php b/app/sprinkles/core/src/Bakery/BakeCommand.php similarity index 98% rename from app/sprinkles/core/src/Bakery/Bake.php rename to app/sprinkles/core/src/Bakery/BakeCommand.php index 9e89fbded..7b5324833 100644 --- a/app/sprinkles/core/src/Bakery/Bake.php +++ b/app/sprinkles/core/src/Bakery/BakeCommand.php @@ -19,7 +19,7 @@ * * @author Alex Weissman (https://alexanderweissman.com) */ -class Bake extends BaseCommand +class BakeCommand extends BaseCommand { /** * @var string Path to the build/ directory diff --git a/app/sprinkles/core/src/Bakery/ClearCache.php b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php similarity index 98% rename from app/sprinkles/core/src/Bakery/ClearCache.php rename to app/sprinkles/core/src/Bakery/ClearCacheCommand.php index 1ca1b809b..c40ea8502 100644 --- a/app/sprinkles/core/src/Bakery/ClearCache.php +++ b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php @@ -19,7 +19,7 @@ * * @author Alex Weissman (https://alexanderweissman.com) */ -class ClearCache extends BaseCommand +class ClearCacheCommand extends BaseCommand { /** * {@inheritDoc} diff --git a/app/sprinkles/core/src/Bakery/Debug.php b/app/sprinkles/core/src/Bakery/DebugCommand.php similarity index 99% rename from app/sprinkles/core/src/Bakery/Debug.php rename to app/sprinkles/core/src/Bakery/DebugCommand.php index 3c731d736..5fddcd701 100644 --- a/app/sprinkles/core/src/Bakery/Debug.php +++ b/app/sprinkles/core/src/Bakery/DebugCommand.php @@ -19,7 +19,7 @@ * * @author Alex Weissman (https://alexanderweissman.com) */ -class Debug extends BaseCommand +class DebugCommand extends BaseCommand { use DatabaseTest; diff --git a/app/sprinkles/core/src/Bakery/Setup.php b/app/sprinkles/core/src/Bakery/SetupCommand.php similarity index 51% rename from app/sprinkles/core/src/Bakery/Setup.php rename to app/sprinkles/core/src/Bakery/SetupCommand.php index 142b89c41..75c7ce8c7 100644 --- a/app/sprinkles/core/src/Bakery/Setup.php +++ b/app/sprinkles/core/src/Bakery/SetupCommand.php @@ -20,7 +20,7 @@ * * @author Alex Weissman (https://alexanderweissman.com) */ -class Setup extends BaseCommand +class SetupCommand extends BaseCommand { /** * @var string Path to the .env file @@ -35,7 +35,16 @@ protected function configure() $this->setName("setup") ->setDescription("UserFrosting configuration wizard") ->setHelp("Helper command to setup the database and email configuration. This can also be done manually by editing the app/.env file or using global server environment variables.") - ->addOption("force", "f", InputOption::VALUE_NONE, "If `.env` file exist, force setup to run again"); + ->addOption("force", "f", InputOption::VALUE_NONE, "If `.env` file exist, force setup to run again") + ->addOption('db_driver', null, InputOption::VALUE_OPTIONAL, "The database driver {$this->getDatabaseDriversList()}") + ->addOption('db_name', null, InputOption::VALUE_OPTIONAL, "The database name") + ->addOption('db_host', null, InputOption::VALUE_OPTIONAL, "The database hostname") + ->addOption('db_port', null, InputOption::VALUE_OPTIONAL, "The database port") + ->addOption('db_user', null, InputOption::VALUE_OPTIONAL, "The database user") + ->addOption('db_password', null, InputOption::VALUE_OPTIONAL, "The database password") + ->addOption('smtp_host', null, InputOption::VALUE_OPTIONAL, "The SMTP server hostname") + ->addOption('smtp_user', null, InputOption::VALUE_OPTIONAL, "The SMTP server user") + ->addOption('smtp_password', null, InputOption::VALUE_OPTIONAL, "The SMTP server password"); } /** @@ -66,63 +75,108 @@ protected function execute(InputInterface $input, OutputInterface $output) } //Goto setup - $this->setupEnv(); + $this->setupEnv($input); } /** * Setup the `.env` file. * + * @param InputInterface $args Command arguments * @return void */ - public function setupEnv() + public function setupEnv(InputInterface $args) { - // Get config - $config = $this->ci->config; + $this->io->note("Database and SMTP credentials will be saved in `{$this->envPath}`"); - // Get the db driver choices - $drivers = $this->databaseDrivers(); + // Get database info + $dbParams = $this->askForDatabase($args); + + // Test database + $this->testDatabase($dbParams); + + // Ask for SMTP info + $smtpParams = $this->askForSmtp($args); + + // Save env file + $this->saveFile($dbParams, $smtpParams); + // At this point, `$this->uf` is still using the old configs. + // We need to refresh the `db.default` config values + $newConfig = array_merge($this->ci->config['db.default'], $dbParams); + $this->ci->config->set("db.default", $newConfig); + } - // Ask the questions + /** + * Ask for database crendentials + * + * @param InputInterface $args Command arguments + * @return array The databse credentials + */ + protected function askForDatabase(InputInterface $args) + { $this->io->section("Setting up database"); - $this->io->note("Database credentials will be saved in `app/.env`"); - $driver = $this->io->choice("Database type", $drivers->pluck('name')->toArray()); - $driver = $drivers->where('name', $driver)->first(); + // Get the db driver choices + $drivers = $this->databaseDrivers(); + $driversList = $drivers->pluck('name')->toArray(); - $driverName = $driver['driver']; - $defaultDBName = $driver['defaultDBName']; + // Ask for database type if not defined in command arguments + if ($args->getOption('db_driver')) { + $selectedDriver = $args->getOption('db_driver'); + $driver = $drivers->where('driver', $selectedDriver)->first(); + } else { + $selectedDriver = $this->io->choice("Database type", $driversList); + $driver = $drivers->where('name', $selectedDriver)->first(); + } - if ($driverName == 'sqlite') { - $name = $this->io->ask("Database name", $defaultDBName); + // Get the selected driver. Make sure driver was found + if (!$driver) { + $this->io->error("Invalid database driver: $selectedDriver"); + exit(1); + } - $dbParams = [ - 'driver' => $driverName, + // Ask further questions based on driver + if ($driver['driver'] == 'sqlite') { + + $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); + + return [ + 'driver' => $driver['driver'], 'database' => $name ]; + } else { $defaultPort = $driver['defaultPort']; - $host = $this->io->ask("Hostname", "localhost"); - $port = $this->io->ask("Port", $defaultPort); - $name = $this->io->ask("Database name", $defaultDBName); - $user = $this->io->ask("Username", "userfrosting"); - $password = $this->io->askHidden("Password", function ($password) { + $host = ($args->getOption('db_host')) ?: $this->io->ask("Hostname", "localhost"); + $port = ($args->getOption('db_port')) ?: $this->io->ask("Port", $defaultPort); + $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); + $user = ($args->getOption('db_user')) ?: $this->io->ask("Username", "userfrosting"); + $password = ($args->getOption('db_password')) ?: $this->io->askHidden("Password", function ($password) { // Use custom validator to accept empty password return $password; }); - $dbParams = [ - 'driver' => $driverName, + return [ + 'driver' => $driver['driver'], 'host' => $host, 'port' => $port, 'database' => $name, 'username' => $user, 'password' => $password, - 'charset' => $config['db.default.charset'] + 'charset' => $this->ci->config['db.default.charset'] ]; } + } + /** + * Test new database connecion + * + * @param array $dbParams Database params + * @return void (Exit if fails) + */ + protected function testDatabase($dbParams) + { // Setup a new db connection $capsule = new Capsule; $capsule->addConnection($dbParams); @@ -132,7 +186,6 @@ public function setupEnv() $conn = $capsule->getConnection(); $conn->getPdo(); $this->io->success("Database connection successful"); - $success = true; } catch (\PDOException $e) { $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; $message .= "Exception: " . $e->getMessage() . PHP_EOL.PHP_EOL; @@ -140,25 +193,54 @@ public function setupEnv() $this->io->error($message); exit(1); } + } + /** + * Ask for SMTP credential + * + * @param InputInterface $args Command arguments + * @return array The SMTP connection info + */ + protected function askForSmtp(InputInterface $args) + { // Ask for the smtp values now - $this->io->section("Enter your SMTP credentials"); - $this->io->write("This is used to send emails from the system. Edit `app/.env` if you have problems with this later."); - $smtpHost = $this->io->ask("SMTP Host", "host.example.com"); - $smtpUser = $this->io->ask("SMTP User", "relay@example.com"); - $smtpPassword = $this->io->askHidden("SMTP Password", function ($password) { + $this->io->section("Email setup"); + $this->io->write("Enter your SMTP server credentials. This is the server used to send emails from the system. Edit `{$this->envPath}` if you have problems sending email later."); + + $smtpHost = ($args->getOption('smtp_host')) ?: $this->io->ask("SMTP Host", "host.example.com"); + $smtpUser = ($args->getOption('smtp_user')) ?: $this->io->ask("SMTP User", "relay@example.com"); + $smtpPassword = ($args->getOption('smtp_password')) ?: $this->io->askHidden("SMTP Password", function ($password) { // Use custom validator to accept empty password return $password; }); - if ($driverName == 'sqlite') { + return [ + 'host' => $smtpHost, + 'user' => $smtpUser, + 'password' => $smtpPassword + ]; + } + + /** + * Write the env file + * + * @param array $dbParams Database params + * @param array $smtpParams SMTP params + * @return void + */ + protected function saveFile($dbParams, $smtpParams) + { + $this->io->section("Saving data"); + + // Prepare file content + if ($dbParams['driver'] == 'sqlite') { $fileContent = [ "UF_MODE=\"\"\n", "DB_DRIVER=\"{$dbParams['driver']}\"\n", "DB_NAME=\"{$dbParams['database']}\"\n", - "SMTP_HOST=\"$smtpHost\"\n", - "SMTP_USER=\"$smtpUser\"\n", - "SMTP_PASSWORD=\"$smtpPassword\"\n" + "SMTP_HOST=\"{$smtpParams['host']}\"\n", + "SMTP_USER=\"{$smtpParams['user']}\"\n", + "SMTP_PASSWORD=\"{$smtpParams['password']}\"\n" ]; } else { $fileContent = [ @@ -169,25 +251,23 @@ public function setupEnv() "DB_NAME=\"{$dbParams['database']}\"\n", "DB_USER=\"{$dbParams['username']}\"\n", "DB_PASSWORD=\"{$dbParams['password']}\"\n", - "SMTP_HOST=\"$smtpHost\"\n", - "SMTP_USER=\"$smtpUser\"\n", - "SMTP_PASSWORD=\"$smtpPassword\"\n" + "SMTP_HOST=\"{$smtpParams['host']}\"\n", + "SMTP_USER=\"{$smtpParams['user']}\"\n", + "SMTP_PASSWORD=\"{$smtpParams['password']}\"\n" ]; } // Let's save this config file_put_contents($this->envPath, $fileContent); - // At this point, `$this->uf` is still using the old configs. - // We need to refresh the `db.default` config values - $newConfig = array_merge($config['db.default'], $dbParams); - $this->ci->config->set("db.default", $newConfig); + // Success + $this->io->success("Database and SMTP credentials saved to `{$this->envPath}`"); } /** * Return the database choices for the env setup. * - * @return void + * @return \Illuminate\Support\Collection */ protected function databaseDrivers() { @@ -218,4 +298,16 @@ protected function databaseDrivers() ] ]); } + + /** + * Returns a list of available drivers + * + * @return array + */ + protected function getDatabaseDriversList() + { + $dbDriverList = $this->databaseDrivers(); + $dbDriverList = $dbDriverList->pluck('driver'); + return $dbDriverList; + } } From db57e3ee3019c4454462c5aaa7de1f6cb5bcf8c0 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 30 Mar 2018 15:09:53 -0400 Subject: [PATCH 059/237] Added `seed:list` Bakery command Also changed the seeds location to `UserFrosting\Sprinkle\{sprinkleName}\Database\Seeds` instead of `UserFrosting\Sprinkle\{sprinkleName}\Database\Seeder` --- app/sprinkles/core/src/Bakery/SeedCommand.php | 3 +- .../core/src/Bakery/SeedListCommand.php | 44 ++++++ .../src/Database/Seeder/SeederLocator.php | 134 ++++++++++++++++++ 3 files changed, 179 insertions(+), 2 deletions(-) create mode 100644 app/sprinkles/core/src/Bakery/SeedListCommand.php create mode 100644 app/sprinkles/core/src/Database/Seeder/SeederLocator.php diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index cdf22d52c..dbfa878c9 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -71,7 +71,6 @@ protected function execute(InputInterface $input, OutputInterface $output) // TODO :: // - Disable Model guarded policy - // - Create seeder:list command/options // - Create default seeds list/service // Run seeds @@ -99,7 +98,7 @@ protected function getSeed($name) $finder = new ClassFinder($this->ci->sprinkleManager); try { - $class = $finder->getClass("Database\\Seeder\\$name"); + $class = $finder->getClass("Database\\Seeds\\$name"); } catch (\Exception $e) { $this->io->error($e->getMessage()); exit(1); diff --git a/app/sprinkles/core/src/Bakery/SeedListCommand.php b/app/sprinkles/core/src/Bakery/SeedListCommand.php new file mode 100644 index 000000000..1bd91e5de --- /dev/null +++ b/app/sprinkles/core/src/Bakery/SeedListCommand.php @@ -0,0 +1,44 @@ +setName('seed:list') + ->setDescription('List all database seeds available') + ->setHelp('This command returns a list of database seeds that can be called using the `seed` command.'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title("Database Seeds List"); + $locator = new SeederLocator($this->ci->sprinkleManager, new Filesystem); + $seeds = $locator->getSeeders(); + $this->io->table(['Name', 'Namespace', 'Sprinkle'], $seeds->toArray()); + } +} diff --git a/app/sprinkles/core/src/Database/Seeder/SeederLocator.php b/app/sprinkles/core/src/Database/Seeder/SeederLocator.php new file mode 100644 index 000000000..8127e946f --- /dev/null +++ b/app/sprinkles/core/src/Database/Seeder/SeederLocator.php @@ -0,0 +1,134 @@ +sprinkleManager = $sprinkleManager; + $this->files = $files; + } + + /** + * Returm a list of all available seeds for a specific sprinkle + * + * @param string $sprinkleName The sprinkle name + * @return array The list of available seed classes + */ + public function getSeedersForSprinkle($sprinkleName) + { + $seeds = new Collection; + + // Get the sprinkle seed path and get all files in that path recursively + $path = $this->seederDirectoryPath($sprinkleName); + + // If directory diesn't exist, stop + if (!$this->files->exists($path)) { + return $seeds; + } + + // Get files + $files = $this->files->allFiles($path); + + // Transform the path into the mgiration full class name + $seeds = collect($files)->transform(function ($file) use ($sprinkleName, $path) { + return $this->getSeedDetails($file, $path, $sprinkleName); + }); + + // Return as array + return $seeds; + } + + /** + * Loop all the available sprinkles and return a list of their seeds + * + * @return Collection A collection of all the seed classes found for every sprinkle + */ + public function getSeeders() + { + $seeds = new Collection; + foreach ($this->sprinkleManager->getSprinkleNames() as $sprinkle) { + $sprinkleSeeds = $this->getSeedersForSprinkle($sprinkle); + $seeds = $seeds->merge($sprinkleSeeds); + } + + return $seeds; + } + + /** + * Returns the path of the seed directory for a sprinkle. + * + * @param string $sprinkleName + * @return string The sprinkle seed dir path + */ + protected function seederDirectoryPath($sprinkleName) + { + return \UserFrosting\SPRINKLES_DIR . + \UserFrosting\DS . + $sprinkleName . + \UserFrosting\DS . + \UserFrosting\SRC_DIR_NAME . + "/Database/Seeds"; + } + + /** + * Get the full classname of a seed based on the absolute file path, + * the initial search path and the SprinkleName + * + * @param string $file The seed file absolute path + * @param string $path The initial search path + * @param string $sprinkleName The sprinkle name + * @return array The details about a seed file [name, class, sprinkle] + */ + protected function getSeedDetails($file, $path, $sprinkleName) + { + // Format the sprinkle name for the namespace + $sprinkleName = Str::studly($sprinkleName); + + // Extract the class name from the path and file + $relativePath = str_replace($path, '', $file); + $className = str_replace('.php', '', $relativePath); + $className = str_replace('/', '', $className); + + // Build the class name and namespace + return [ + 'name' => $className, + 'class' => "\\UserFrosting\\Sprinkle\\".$sprinkleName."\\Database\\Seeds\\" . $className, + 'sprinkle' => $sprinkleName + ]; + } +} From 710c1555b77f257a7c63bcc4ea31f68afcf11a19 Mon Sep 17 00:00:00 2001 From: Jose Vasconcellos Date: Sat, 31 Mar 2018 15:18:41 -0500 Subject: [PATCH 060/237] Add support for other config['mailer'] options. Tested with sendmail. --- app/sprinkles/core/src/Mail/Mailer.php | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) mode change 100755 => 100644 app/sprinkles/core/src/Mail/Mailer.php diff --git a/app/sprinkles/core/src/Mail/Mailer.php b/app/sprinkles/core/src/Mail/Mailer.php old mode 100755 new mode 100644 index 5b346b46d..99d2dc6a1 --- a/app/sprinkles/core/src/Mail/Mailer.php +++ b/app/sprinkles/core/src/Mail/Mailer.php @@ -47,8 +47,23 @@ public function __construct($logger, $config = []) if (!in_array($config['mailer'], ['smtp', 'mail', 'qmail', 'sendmail'])) { throw new \phpmailerException("'mailer' must be one of 'smtp', 'mail', 'qmail', or 'sendmail'."); } - - if ($config['mailer'] == 'smtp') { +--- a/app/sprinkles/core/src/Mail/Mailer.php ++++ b/app/sprinkles/core/src/Mail/Mailer.php +@@ -44,11 +44,17 @@ class Mailer + + // Configuration options + if (isset($config['mailer'])) { + switch ($config['mailer']) { + case 'mail': + $this->phpMailer->isMail(); + break; + case 'qmail': + $this->phpMailer->isQmail(); + break; + case 'sendmail': + $this->phpMailer->isSendmail(); + break; + case 'smtp': $this->phpMailer->isSMTP(true); $this->phpMailer->Host = $config['host']; $this->phpMailer->Port = $config['port']; @@ -61,6 +76,9 @@ public function __construct($logger, $config = []) if (isset($config['smtp_options'])) { $this->phpMailer->SMTPOptions = $config['smtp_options']; } + break; + default: + throw new \phpmailerException("'mailer' must be one of 'smtp', 'mail', 'qmail', or 'sendmail'."); } // Set any additional message-specific options From 62dd15cca56cf2c171168bfd12380e8808b6589e Mon Sep 17 00:00:00 2001 From: alexweissman Date: Sun, 1 Apr 2018 21:31:12 -0400 Subject: [PATCH 061/237] missing check in ufForm --- app/sprinkles/core/assets/userfrosting/js/uf-form.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/core/assets/userfrosting/js/uf-form.js b/app/sprinkles/core/assets/userfrosting/js/uf-form.js index 54c396dc8..c5352e757 100644 --- a/app/sprinkles/core/assets/userfrosting/js/uf-form.js +++ b/app/sprinkles/core/assets/userfrosting/js/uf-form.js @@ -13,7 +13,7 @@ * $('#myForm').ufForm(options); * * `options` is an object containing any of the following parameters: - * @param {JSON} validators An object containing two keys, "rules" and "messages", which specify the jQueryvalidation rules to use. + * @param {JSON} validator An object containing two keys, "rules" and "messages", which specify the jQueryvalidation rules to use. * @param {Object} msgTarget a jQuery selector specifying the element where any error messages should be inserted. Defaults to looking for a container with class .js-form-alerts inside this form. * @param {Callback} beforeSubmitCallback a callback function to execute immediately after form validation, before the form is submitted. * @param {bool} binaryCheckboxes specify whether to submit checkboxes as binary values 0 and 1, instead of omitting unchecked checkboxes from submission. @@ -85,7 +85,7 @@ }; // Legacy options - if ('validators' in options) { + if ((typeof options !== 'undefined') && 'validators' in options) { options.validator = options.validators; } @@ -236,6 +236,12 @@ return jqXHR; }; + /** + * Default parser for text/json ajax response from server. + * + * @param {string} result + * @return {object} + */ Plugin.prototype._defaultResponseParser = function(result) { try { // First try to use native browser parsing From 5ecc8762653404cf881e842e2c17d1b02c5ba6b4 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 5 Apr 2018 21:01:46 -0400 Subject: [PATCH 062/237] Typo --- app/sprinkles/account/src/Account/Registration.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/account/src/Account/Registration.php b/app/sprinkles/account/src/Account/Registration.php index bdf3ea70c..2b4d26427 100644 --- a/app/sprinkles/account/src/Account/Registration.php +++ b/app/sprinkles/account/src/Account/Registration.php @@ -131,7 +131,7 @@ public function register() // Verification email if ($this->requireEmailVerification) { - $this->sendVerificarionEmail($user); + $this->sendVerificationEmail($user); } return $user; @@ -228,7 +228,7 @@ protected function setDefaults() * @param User $user The user to send the email for * @return void */ - protected function sendVerificarionEmail(User $user) + protected function sendVerificationEmail(User $user) { // Try to generate a new verification request $verification = $this->ci->repoVerification->create($user, $this->ci->config['verification.timeout']); From 99b50561bd4f96433a3c5cead0a3844cc974bf20 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 6 Apr 2018 20:24:40 -0400 Subject: [PATCH 063/237] Initialize `Stream` Only `ReadOnlyStream` was initilized --- app/system/ServicesProvider.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 7bd1c5f32..18ba423a9 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -11,6 +11,7 @@ use RocketTheme\Toolbox\Event\EventDispatcher; use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use RocketTheme\Toolbox\StreamWrapper\ReadOnlyStream; +use RocketTheme\Toolbox\StreamWrapper\Stream; use RocketTheme\Toolbox\StreamWrapper\StreamBuilder; use UserFrosting\System\Sprinkle\SprinkleManager; @@ -54,6 +55,7 @@ public function register(ContainerInterface $container) // Use locator to initialize streams ReadOnlyStream::setLocator($locator); + Stream::setLocator($locator); // Fire up StreamBuilder $c->streamBuilder; From e987be07bb27edb2a4bdf6fd22b4845174f01a2c Mon Sep 17 00:00:00 2001 From: alexweissman Date: Sat, 7 Apr 2018 13:23:22 -0400 Subject: [PATCH 064/237] Add Config facade --- app/sprinkles/core/src/Facades/Config.php | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 app/sprinkles/core/src/Facades/Config.php diff --git a/app/sprinkles/core/src/Facades/Config.php b/app/sprinkles/core/src/Facades/Config.php new file mode 100644 index 000000000..d0436e7c2 --- /dev/null +++ b/app/sprinkles/core/src/Facades/Config.php @@ -0,0 +1,28 @@ + Date: Sat, 7 Apr 2018 13:33:24 -0400 Subject: [PATCH 065/237] Temporarily undeprecate and rewrite the assetLoader service until Assets can be refactored --- CHANGELOG.md | 2 ++ app/sprinkles/core/routes/routes.php | 2 +- .../core/src/Controller/CoreController.php | 23 +++++++++++- .../src/ServicesProvider/ServicesProvider.php | 31 +++++++++++++--- app/sprinkles/core/src/Util/AssetLoader.php | 35 ++++--------------- 5 files changed, 58 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c3c7222e7..860228f6b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Re-written Migrator. The migrator is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider (#795) - Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace - Move User registration out of the `AccountController` (#793) +- Temporarily undeprecate `AssetLoader` until the new asset system can be refactored (https://github.com/userfrosting/assets/issues/4) +- Rewrite `AssetLoader` to act as a wrapper for `Assets` ### Deprecated - Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration` diff --git a/app/sprinkles/core/routes/routes.php b/app/sprinkles/core/routes/routes.php index a4bfc42d4..3598b7ea7 100755 --- a/app/sprinkles/core/routes/routes.php +++ b/app/sprinkles/core/routes/routes.php @@ -21,4 +21,4 @@ $app->get('/privacy', 'UserFrosting\Sprinkle\Core\Controller\CoreController:pagePrivacy'); -$app->get('/' . $config['assets.raw.path'] . '/{url:.+}', 'UserFrosting\Assets\ServeAsset\SlimServeAsset:serveAsset'); +$app->get('/' . $config['assets.raw.path'] . '/{url:.+}', 'UserFrosting\Sprinkle\Core\Controller\CoreController:getAsset'); diff --git a/app/sprinkles/core/src/Controller/CoreController.php b/app/sprinkles/core/src/Controller/CoreController.php index bc1556be4..4980808ea 100644 --- a/app/sprinkles/core/src/Controller/CoreController.php +++ b/app/sprinkles/core/src/Controller/CoreController.php @@ -9,7 +9,7 @@ use Psr\Http\Message\ServerRequestInterface as Request; use Psr\Http\Message\ResponseInterface as Response; -use Slim\Exception\NotFoundException as NotFoundException; +use UserFrosting\Support\Exception\NotFoundException; /** * CoreController Class @@ -71,4 +71,25 @@ public function jsonAlerts($request, $response, $args) { return $response->withJson($this->ci->alerts->getAndClearMessages()); } + + /** + * Handle all requests for raw assets. + * Request type: GET + */ + public function getAsset($request, $response, $args) + { + // By starting this service, we ensure that the timezone gets set. + $config = $this->ci->config; + + $assetLoader = $this->ci->assetLoader; + + if (!$assetLoader->loadAsset($args['url'])) { + throw new NotFoundException; + } + + return $response + ->withHeader('Content-Type', $assetLoader->getType()) + ->withHeader('Content-Length', $assetLoader->getLength()) + ->write($assetLoader->getContent()); + } } diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index edf807c32..54e18ff10 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -98,14 +98,35 @@ public function register(ContainerInterface $container) * * Loads assets from a specified relative location. * Assets are Javascript, CSS, image, and other files used by your site. - * - * @deprecated 4.0.25-alpha This service was formerly used to serve frontend assets during development. + * This implementation is a temporary hack until Assets can be refactored. */ $container['assetLoader'] = function ($c) { - $basePath = \UserFrosting\SPRINKLES_DIR; - $pattern = "/^[A-Za-z0-9_\-]+\/assets\//"; + $config = $c->config; + $locator = $c->locator; + + // Hacky way to clean up locator paths. + $locatorPaths = []; + foreach ($locator->getPaths('assets') as $pathSet) { + foreach ($pathSet as $path) { + $locatorPaths[] = $path; + } + } + + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; + + $sprinkles = $c->sprinkleManager->getSprinkleNames(); + + $prefixTransformer = new PrefixTransformer(); + $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); + $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); + + foreach ($sprinkles as $sprinkle) { + $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); + } + + $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); - return new AssetLoader($basePath, $pattern); + return new AssetLoader($assets); }; /** diff --git a/app/sprinkles/core/src/Util/AssetLoader.php b/app/sprinkles/core/src/Util/AssetLoader.php index be76fd021..407dab2d6 100644 --- a/app/sprinkles/core/src/Util/AssetLoader.php +++ b/app/sprinkles/core/src/Util/AssetLoader.php @@ -8,6 +8,7 @@ */ namespace UserFrosting\Sprinkle\Core\Util; +use UserFrosting\Assets\Assets; use UserFrosting\Assets\Util\MimeType; use UserFrosting\Support\Util\Util; @@ -16,24 +17,18 @@ * * Loads an asset from the filesystem. * @author Alex Weissman (https://alexanderweissman.com) - * @deprecated */ class AssetLoader { - /** - * @var string The base filesystem path in which to look for the asset file. Can be an absolute path or stream. - */ - protected $basePath; - /** * @var string The fully constructed path to the file. */ protected $fullPath; /** - * @var string A regex pattern to represent the allowed subset of paths under basePath which are accessible. + * @var \UserFrosting\Assets\Assets */ - protected $pattern; + protected $assets; /** * Create a new AssetLoader object. @@ -41,13 +36,9 @@ class AssetLoader * @param string $basePath * @param string $pattern */ - public function __construct($basePath, $pattern) + public function __construct(Assets $assets) { - $this->basePath = rtrim($basePath, "/\\") . '/'; - - $this->pattern = $pattern; - - $this->fullPath = ''; + $this->assets = $assets; } /** @@ -59,19 +50,7 @@ public function __construct($basePath, $pattern) */ public function loadAsset($relativePath) { - // 1. Remove any query string - $relativePath = preg_replace('/\?.*/', '', $relativePath); - - // 2. Normalize path, to prevent directory traversal - $relativePath = Util::normalizePath($relativePath); - - // 3. Check that the beginning of the path matches the allowed paths pattern - if (!preg_match($this->pattern, $relativePath)) { - return false; - } - - // 4. Build full path to file - $this->fullPath = $this->basePath . $relativePath; + $this->fullPath = $this->assets->urlPathToAbsolutePath($relativePath); // Return false if file does not exist if (!file_exists($this->fullPath)) { @@ -110,4 +89,4 @@ public function getType() { return MimeType::detectByFilename($this->fullPath); } -} \ No newline at end of file +} From ccda4012456f0ea7aec6f6b110805c5736d0f622 Mon Sep 17 00:00:00 2001 From: Jose Vasconcellos Date: Mon, 9 Apr 2018 03:34:30 -0500 Subject: [PATCH 066/237] Fix patch --- app/sprinkles/core/src/Mail/Mailer.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/app/sprinkles/core/src/Mail/Mailer.php b/app/sprinkles/core/src/Mail/Mailer.php index 99d2dc6a1..04f308f61 100644 --- a/app/sprinkles/core/src/Mail/Mailer.php +++ b/app/sprinkles/core/src/Mail/Mailer.php @@ -44,15 +44,6 @@ public function __construct($logger, $config = []) // Configuration options if (isset($config['mailer'])) { - if (!in_array($config['mailer'], ['smtp', 'mail', 'qmail', 'sendmail'])) { - throw new \phpmailerException("'mailer' must be one of 'smtp', 'mail', 'qmail', or 'sendmail'."); - } ---- a/app/sprinkles/core/src/Mail/Mailer.php -+++ b/app/sprinkles/core/src/Mail/Mailer.php -@@ -44,11 +44,17 @@ class Mailer - - // Configuration options - if (isset($config['mailer'])) { switch ($config['mailer']) { case 'mail': $this->phpMailer->isMail(); From bbcf92177fca67c1e6ea63cc6617f25215d459af Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 6 May 2018 21:18:40 -0400 Subject: [PATCH 067/237] Should fix weird issue with composer plugin --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 28c3fe160..687ab555a 100755 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "ext-gd": "*", "composer/installers": "^1.4.0", "symfony/console": "^3.3", - "wikimedia/composer-merge-plugin": "dev-master" + "wikimedia/composer-merge-plugin": "^1.4.0" }, "require-dev": { "phpunit/phpunit": "^5.7", From c912918afe4cf39805ec271b065cdca08baa1bac Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 9 May 2018 22:15:55 -0400 Subject: [PATCH 068/237] Update `support` package for dev. Leave this in until a proper release can be done. FYI, can't be done in the `core` composer.json file as it's not the root composer file. --- composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/composer.json b/composer.json index 687ab555a..fe20d1ec9 100755 --- a/composer.json +++ b/composer.json @@ -19,6 +19,7 @@ "ext-gd": "*", "composer/installers": "^1.4.0", "symfony/console": "^3.3", + "userfrosting/support": "dev-develop as 4.1.2", "wikimedia/composer-merge-plugin": "^1.4.0" }, "require-dev": { From 0f6da95f904af85c2c068403192fe4f84700dd0e Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 10 May 2018 21:49:44 -0400 Subject: [PATCH 069/237] Bakery setup:env & setup:db command --- .../core/src/Bakery/SetupDbCommand.php | 258 ++++++++++++++++++ .../core/src/Bakery/SetupEnvCommand.php | 95 +++++++ 2 files changed, 353 insertions(+) create mode 100644 app/sprinkles/core/src/Bakery/SetupDbCommand.php create mode 100644 app/sprinkles/core/src/Bakery/SetupEnvCommand.php diff --git a/app/sprinkles/core/src/Bakery/SetupDbCommand.php b/app/sprinkles/core/src/Bakery/SetupDbCommand.php new file mode 100644 index 000000000..921d097f5 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/SetupDbCommand.php @@ -0,0 +1,258 @@ +setName("setup:db") + ->setDescription("UserFrosting Database Configuration Wizard") + ->setHelp("Helper command to setup the database configuration. This can also be done manually by editing the app/.env file or using global server environment variables.") + ->addOption('db_driver', null, InputOption::VALUE_OPTIONAL, "The database driver {$this->getDatabaseDriversList()}") + ->addOption('db_name', null, InputOption::VALUE_OPTIONAL, "The database name") + ->addOption('db_host', null, InputOption::VALUE_OPTIONAL, "The database hostname") + ->addOption('db_port', null, InputOption::VALUE_OPTIONAL, "The database port") + ->addOption('db_user', null, InputOption::VALUE_OPTIONAL, "The database user") + ->addOption('db_password', null, InputOption::VALUE_OPTIONAL, "The database password"); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + /** + * @var Config $config Get config + */ + $config = $this->ci->config; + + // Display header, + $this->io->title("UserFrosting's Database Setup Wizard"); + $this->io->note("Database credentials will be saved in `{$this->envPath}`"); + + // Get an instance of the DotenvEditor + $dotenvEditor = new DotenvEditor(\UserFrosting\APP_DIR, false); + $dotenvEditor->load($this->envPath); + $dotenvEditor->save(); // Save make sure empty file is created if none exist + + // Get keys + $keys = [ + 'DB_HOST' => ($dotenvEditor->keyExists('DB_HOST')) ? $dotenvEditor->getValue('DB_HOST') : '', + 'DB_NAME' => ($dotenvEditor->keyExists('DB_NAME')) ? $dotenvEditor->getValue('DB_NAME') : '', + 'DB_USER' => ($dotenvEditor->keyExists('DB_USER')) ? $dotenvEditor->getValue('DB_USER') : '', + 'DB_PASSWORD' => ($dotenvEditor->keyExists('DB_PASSWORD')) ? $dotenvEditor->getValue('DB_PASSWORD') : '' + ]; + + // There may be some custom config or global env values defined on the server. + // We'll check for that and ask for confirmation in this case. + if ($config["db.default.host"] != $keys['DB_HOST'] || + $config["db.default.database"] != $keys['DB_NAME'] || + $config["db.default.username"] != $keys['DB_USER'] || + $config["db.default.password"] != $keys['DB_PASSWORD']) { + + $this->io->warning("Current database configuration differ from the configuration defined in `{$this->envPath}`. Global system environment variables might be defined."); + + if (!$this->io->confirm('Continue?', false)) { + return; + } + } + + // Get database info + $dbParams = $this->askForDatabase($input); + + // Test database + $this->testDatabase($dbParams); + + // Time to save + $this->io->section("Saving data"); + + // Prepare file content + $fileContent = [ + "DB_DRIVER" => $dbParams['driver'], + "DB_HOST" => $dbParams['host'], + "DB_PORT" => $dbParams['port'], + "DB_NAME" => $dbParams['database'], + "DB_USER" => $dbParams['username'], + "DB_PASSWORD" => $dbParams['password'] + ]; + + foreach ($fileContent as $key => $value) { + $dotenvEditor->setKey($key, $value); + } + $dotenvEditor->save(); + + // At this point, `$this->uf` is still using the old configs. + // We need to refresh the `db.default` config values + $newConfig = array_merge($this->ci->config['db.default'], $dbParams); + $this->ci->config->set("db.default", $newConfig); + + // Success + $this->io->success("Database config successfully saved in `{$this->envPath}`"); + } + + /** + * Ask for database crendentials + * + * @param InputInterface $args Command arguments + * @return array The databse credentials + */ + protected function askForDatabase(InputInterface $args) + { + // Get the db driver choices + $drivers = $this->databaseDrivers(); + $driversList = $drivers->pluck('name')->toArray(); + + // Ask for database type if not defined in command arguments + if ($args->getOption('db_driver')) { + $selectedDriver = $args->getOption('db_driver'); + $driver = $drivers->where('driver', $selectedDriver)->first(); + } else { + $selectedDriver = $this->io->choice("Database type", $driversList); + $driver = $drivers->where('name', $selectedDriver)->first(); + } + + // Get the selected driver. Make sure driver was found + if (!$driver) { + $this->io->error("Invalid database driver: $selectedDriver"); + exit(1); + } + + // Ask further questions based on driver + if ($driver['driver'] == 'sqlite') { + + $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); + + return [ + 'driver' => $driver['driver'], + 'host' => '', + 'port' => '', + 'database' => $name, + 'username' => '', + 'password' => '' + ]; + + } else { + $defaultPort = $driver['defaultPort']; + + $host = ($args->getOption('db_host')) ?: $this->io->ask("Hostname", "localhost"); + $port = ($args->getOption('db_port')) ?: $this->io->ask("Port", $defaultPort); + $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); + $user = ($args->getOption('db_user')) ?: $this->io->ask("Username", "userfrosting"); + $password = ($args->getOption('db_password')) ?: $this->io->askHidden("Password", function ($password) { + // Use custom validator to accept empty password + return $password; + }); + + return [ + 'driver' => $driver['driver'], + 'host' => $host, + 'port' => $port, + 'database' => $name, + 'username' => $user, + 'password' => $password, + 'charset' => $this->ci->config['db.default.charset'] // Used when replacing config later + ]; + } + } + + /** + * Test new database connecion + * + * @param array $dbParams Database params + * @return void (Exit if fails) + */ + protected function testDatabase($dbParams) + { + // Setup a new db connection + $capsule = new Capsule; + $capsule->addConnection($dbParams); + + // Test the db connexion. + try { + $conn = $capsule->getConnection(); + $conn->getPdo(); + $this->io->success("Database connection successful"); + } catch (\PDOException $e) { + $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; + $message .= "Exception: " . $e->getMessage() . PHP_EOL.PHP_EOL; + $message .= "Please check your database configuration and/or google the exception shown above and run the command again."; + $this->io->error($message); + exit(1); + } + } + + /** + * Return the database choices for the env setup. + * + * @return \Illuminate\Support\Collection + */ + protected function databaseDrivers() + { + return collect([ + [ + "driver" => "mysql", + "name" => "MySQL / MariaDB", + "defaultDBName" => "userfrosting", + "defaultPort" => 3306 + ], + [ + "driver" => "pgsql", + "name" => "ProgreSQL", + "defaultDBName" => "userfrosting", + "defaultPort" => 5432 + ], + [ + "driver" => "sqlsrv", + "name" => "SQL Server", + "defaultDBName" => "userfrosting", + "defaultPort" => 1433 + ], + [ + "driver" => "sqlite", + "name" => "SQLite", + "defaultDBName" => \UserFrosting\DB_DIR . \UserFrosting\DS . 'userfrosting.db', + "defaultPort" => null + ] + ]); + } + + /** + * Returns a list of available drivers + * + * @return array + */ + protected function getDatabaseDriversList() + { + $dbDriverList = $this->databaseDrivers(); + $dbDriverList = $dbDriverList->pluck('driver'); + return $dbDriverList; + } +} diff --git a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php new file mode 100644 index 000000000..bc87e667c --- /dev/null +++ b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php @@ -0,0 +1,95 @@ +setName("setup:env") + ->setDescription("UserFrosting Environment Configuration Wizard") + ->setHelp("Helper command to setup environement mode. This can also be done manually by editing the app/.env file or using global server environment variables.") + ->addOption('mode', null, InputOption::VALUE_OPTIONAL, "The environment to use"); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + // Display header, + $this->io->title("UserFrosting's Environment Setup Wizard"); + $this->io->note("Environment mode will be saved in `{$this->envPath}`"); + + // Get an instance of the DotenvEditor + $dotenvEditor = new DotenvEditor(\UserFrosting\APP_DIR, false); + $dotenvEditor->load($this->envPath); + + // Ask for mode + $newEnvMode = $this->askForEnv($input); + + // Save new value + $dotenvEditor->setKey($this->modeKey, $newEnvMode); + $dotenvEditor->save(); + + // Success + $this->io->success("Environment mode successfully changed to `$newEnvMode` in `{$this->envPath}`"); + } + + /** + * Ask for env mode + * + * @param InputInterface $args Command arguments + * @return string The new env mode + */ + protected function askForEnv(InputInterface $args) + { + // Ask for mode if not defined in command arguments + if ($args->getOption('mode')) { + return $args->getOption('mode'); + } else { + $newEnvMode = $this->io->choice("Environment Mode", [ + 'default', + 'production', + 'Other...' + ], 'default'); + } + + // Ask for manual input if 'other' was chosen + if ($newEnvMode == 'Other...') { + $newEnvMode = $this->io->ask('Enter desired environment mode'); + } + + return $newEnvMode; + } +} From 111535b7dd5f4b58e21604cf6f762920742a638f Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 11 May 2018 21:14:43 -0400 Subject: [PATCH 070/237] Revert "Bakery setup:env & setup:db command" This reverts commit 0f6da95f904af85c2c068403192fe4f84700dd0e. --- .../core/src/Bakery/SetupDbCommand.php | 258 ------------------ .../core/src/Bakery/SetupEnvCommand.php | 95 ------- 2 files changed, 353 deletions(-) delete mode 100644 app/sprinkles/core/src/Bakery/SetupDbCommand.php delete mode 100644 app/sprinkles/core/src/Bakery/SetupEnvCommand.php diff --git a/app/sprinkles/core/src/Bakery/SetupDbCommand.php b/app/sprinkles/core/src/Bakery/SetupDbCommand.php deleted file mode 100644 index 921d097f5..000000000 --- a/app/sprinkles/core/src/Bakery/SetupDbCommand.php +++ /dev/null @@ -1,258 +0,0 @@ -setName("setup:db") - ->setDescription("UserFrosting Database Configuration Wizard") - ->setHelp("Helper command to setup the database configuration. This can also be done manually by editing the app/.env file or using global server environment variables.") - ->addOption('db_driver', null, InputOption::VALUE_OPTIONAL, "The database driver {$this->getDatabaseDriversList()}") - ->addOption('db_name', null, InputOption::VALUE_OPTIONAL, "The database name") - ->addOption('db_host', null, InputOption::VALUE_OPTIONAL, "The database hostname") - ->addOption('db_port', null, InputOption::VALUE_OPTIONAL, "The database port") - ->addOption('db_user', null, InputOption::VALUE_OPTIONAL, "The database user") - ->addOption('db_password', null, InputOption::VALUE_OPTIONAL, "The database password"); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - /** - * @var Config $config Get config - */ - $config = $this->ci->config; - - // Display header, - $this->io->title("UserFrosting's Database Setup Wizard"); - $this->io->note("Database credentials will be saved in `{$this->envPath}`"); - - // Get an instance of the DotenvEditor - $dotenvEditor = new DotenvEditor(\UserFrosting\APP_DIR, false); - $dotenvEditor->load($this->envPath); - $dotenvEditor->save(); // Save make sure empty file is created if none exist - - // Get keys - $keys = [ - 'DB_HOST' => ($dotenvEditor->keyExists('DB_HOST')) ? $dotenvEditor->getValue('DB_HOST') : '', - 'DB_NAME' => ($dotenvEditor->keyExists('DB_NAME')) ? $dotenvEditor->getValue('DB_NAME') : '', - 'DB_USER' => ($dotenvEditor->keyExists('DB_USER')) ? $dotenvEditor->getValue('DB_USER') : '', - 'DB_PASSWORD' => ($dotenvEditor->keyExists('DB_PASSWORD')) ? $dotenvEditor->getValue('DB_PASSWORD') : '' - ]; - - // There may be some custom config or global env values defined on the server. - // We'll check for that and ask for confirmation in this case. - if ($config["db.default.host"] != $keys['DB_HOST'] || - $config["db.default.database"] != $keys['DB_NAME'] || - $config["db.default.username"] != $keys['DB_USER'] || - $config["db.default.password"] != $keys['DB_PASSWORD']) { - - $this->io->warning("Current database configuration differ from the configuration defined in `{$this->envPath}`. Global system environment variables might be defined."); - - if (!$this->io->confirm('Continue?', false)) { - return; - } - } - - // Get database info - $dbParams = $this->askForDatabase($input); - - // Test database - $this->testDatabase($dbParams); - - // Time to save - $this->io->section("Saving data"); - - // Prepare file content - $fileContent = [ - "DB_DRIVER" => $dbParams['driver'], - "DB_HOST" => $dbParams['host'], - "DB_PORT" => $dbParams['port'], - "DB_NAME" => $dbParams['database'], - "DB_USER" => $dbParams['username'], - "DB_PASSWORD" => $dbParams['password'] - ]; - - foreach ($fileContent as $key => $value) { - $dotenvEditor->setKey($key, $value); - } - $dotenvEditor->save(); - - // At this point, `$this->uf` is still using the old configs. - // We need to refresh the `db.default` config values - $newConfig = array_merge($this->ci->config['db.default'], $dbParams); - $this->ci->config->set("db.default", $newConfig); - - // Success - $this->io->success("Database config successfully saved in `{$this->envPath}`"); - } - - /** - * Ask for database crendentials - * - * @param InputInterface $args Command arguments - * @return array The databse credentials - */ - protected function askForDatabase(InputInterface $args) - { - // Get the db driver choices - $drivers = $this->databaseDrivers(); - $driversList = $drivers->pluck('name')->toArray(); - - // Ask for database type if not defined in command arguments - if ($args->getOption('db_driver')) { - $selectedDriver = $args->getOption('db_driver'); - $driver = $drivers->where('driver', $selectedDriver)->first(); - } else { - $selectedDriver = $this->io->choice("Database type", $driversList); - $driver = $drivers->where('name', $selectedDriver)->first(); - } - - // Get the selected driver. Make sure driver was found - if (!$driver) { - $this->io->error("Invalid database driver: $selectedDriver"); - exit(1); - } - - // Ask further questions based on driver - if ($driver['driver'] == 'sqlite') { - - $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); - - return [ - 'driver' => $driver['driver'], - 'host' => '', - 'port' => '', - 'database' => $name, - 'username' => '', - 'password' => '' - ]; - - } else { - $defaultPort = $driver['defaultPort']; - - $host = ($args->getOption('db_host')) ?: $this->io->ask("Hostname", "localhost"); - $port = ($args->getOption('db_port')) ?: $this->io->ask("Port", $defaultPort); - $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); - $user = ($args->getOption('db_user')) ?: $this->io->ask("Username", "userfrosting"); - $password = ($args->getOption('db_password')) ?: $this->io->askHidden("Password", function ($password) { - // Use custom validator to accept empty password - return $password; - }); - - return [ - 'driver' => $driver['driver'], - 'host' => $host, - 'port' => $port, - 'database' => $name, - 'username' => $user, - 'password' => $password, - 'charset' => $this->ci->config['db.default.charset'] // Used when replacing config later - ]; - } - } - - /** - * Test new database connecion - * - * @param array $dbParams Database params - * @return void (Exit if fails) - */ - protected function testDatabase($dbParams) - { - // Setup a new db connection - $capsule = new Capsule; - $capsule->addConnection($dbParams); - - // Test the db connexion. - try { - $conn = $capsule->getConnection(); - $conn->getPdo(); - $this->io->success("Database connection successful"); - } catch (\PDOException $e) { - $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; - $message .= "Exception: " . $e->getMessage() . PHP_EOL.PHP_EOL; - $message .= "Please check your database configuration and/or google the exception shown above and run the command again."; - $this->io->error($message); - exit(1); - } - } - - /** - * Return the database choices for the env setup. - * - * @return \Illuminate\Support\Collection - */ - protected function databaseDrivers() - { - return collect([ - [ - "driver" => "mysql", - "name" => "MySQL / MariaDB", - "defaultDBName" => "userfrosting", - "defaultPort" => 3306 - ], - [ - "driver" => "pgsql", - "name" => "ProgreSQL", - "defaultDBName" => "userfrosting", - "defaultPort" => 5432 - ], - [ - "driver" => "sqlsrv", - "name" => "SQL Server", - "defaultDBName" => "userfrosting", - "defaultPort" => 1433 - ], - [ - "driver" => "sqlite", - "name" => "SQLite", - "defaultDBName" => \UserFrosting\DB_DIR . \UserFrosting\DS . 'userfrosting.db', - "defaultPort" => null - ] - ]); - } - - /** - * Returns a list of available drivers - * - * @return array - */ - protected function getDatabaseDriversList() - { - $dbDriverList = $this->databaseDrivers(); - $dbDriverList = $dbDriverList->pluck('driver'); - return $dbDriverList; - } -} diff --git a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php deleted file mode 100644 index bc87e667c..000000000 --- a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php +++ /dev/null @@ -1,95 +0,0 @@ -setName("setup:env") - ->setDescription("UserFrosting Environment Configuration Wizard") - ->setHelp("Helper command to setup environement mode. This can also be done manually by editing the app/.env file or using global server environment variables.") - ->addOption('mode', null, InputOption::VALUE_OPTIONAL, "The environment to use"); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - // Display header, - $this->io->title("UserFrosting's Environment Setup Wizard"); - $this->io->note("Environment mode will be saved in `{$this->envPath}`"); - - // Get an instance of the DotenvEditor - $dotenvEditor = new DotenvEditor(\UserFrosting\APP_DIR, false); - $dotenvEditor->load($this->envPath); - - // Ask for mode - $newEnvMode = $this->askForEnv($input); - - // Save new value - $dotenvEditor->setKey($this->modeKey, $newEnvMode); - $dotenvEditor->save(); - - // Success - $this->io->success("Environment mode successfully changed to `$newEnvMode` in `{$this->envPath}`"); - } - - /** - * Ask for env mode - * - * @param InputInterface $args Command arguments - * @return string The new env mode - */ - protected function askForEnv(InputInterface $args) - { - // Ask for mode if not defined in command arguments - if ($args->getOption('mode')) { - return $args->getOption('mode'); - } else { - $newEnvMode = $this->io->choice("Environment Mode", [ - 'default', - 'production', - 'Other...' - ], 'default'); - } - - // Ask for manual input if 'other' was chosen - if ($newEnvMode == 'Other...') { - $newEnvMode = $this->io->ask('Enter desired environment mode'); - } - - return $newEnvMode; - } -} From 0e72460b8c4432a466f17a99497c79b3742fc741 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 11 May 2018 21:14:46 -0400 Subject: [PATCH 071/237] Revert "Update `support` package for dev." This reverts commit c912918afe4cf39805ec271b065cdca08baa1bac. --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index fe20d1ec9..687ab555a 100755 --- a/composer.json +++ b/composer.json @@ -19,7 +19,6 @@ "ext-gd": "*", "composer/installers": "^1.4.0", "symfony/console": "^3.3", - "userfrosting/support": "dev-develop as 4.1.2", "wikimedia/composer-merge-plugin": "^1.4.0" }, "require-dev": { From 81dde1b17f6ecf6a3144f4f227d1b761951644a3 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 15 May 2018 20:36:55 -0400 Subject: [PATCH 072/237] Merge new Bakery setup commands --- .../core/src/Bakery/SetupCommand.php | 285 +----------------- .../core/src/Bakery/SetupDbCommand.php | 260 ++++++++++++++++ .../core/src/Bakery/SetupEnvCommand.php | 96 ++++++ .../core/src/Bakery/SetupSmtpCommand.php | 209 +++++++++++++ 4 files changed, 574 insertions(+), 276 deletions(-) create mode 100644 app/sprinkles/core/src/Bakery/SetupDbCommand.php create mode 100644 app/sprinkles/core/src/Bakery/SetupEnvCommand.php create mode 100644 app/sprinkles/core/src/Bakery/SetupSmtpCommand.php diff --git a/app/sprinkles/core/src/Bakery/SetupCommand.php b/app/sprinkles/core/src/Bakery/SetupCommand.php index 75c7ce8c7..7cbe41230 100644 --- a/app/sprinkles/core/src/Bakery/SetupCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupCommand.php @@ -7,11 +7,8 @@ */ namespace UserFrosting\Sprinkle\Core\Bakery; -use Illuminate\Database\Capsule\Manager as Capsule; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; /** @@ -22,29 +19,14 @@ */ class SetupCommand extends BaseCommand { - /** - * @var string Path to the .env file - */ - protected $envPath = \UserFrosting\APP_DIR. '/.env'; - /** * {@inheritDoc} */ protected function configure() { $this->setName("setup") - ->setDescription("UserFrosting configuration wizard") - ->setHelp("Helper command to setup the database and email configuration. This can also be done manually by editing the app/.env file or using global server environment variables.") - ->addOption("force", "f", InputOption::VALUE_NONE, "If `.env` file exist, force setup to run again") - ->addOption('db_driver', null, InputOption::VALUE_OPTIONAL, "The database driver {$this->getDatabaseDriversList()}") - ->addOption('db_name', null, InputOption::VALUE_OPTIONAL, "The database name") - ->addOption('db_host', null, InputOption::VALUE_OPTIONAL, "The database hostname") - ->addOption('db_port', null, InputOption::VALUE_OPTIONAL, "The database port") - ->addOption('db_user', null, InputOption::VALUE_OPTIONAL, "The database user") - ->addOption('db_password', null, InputOption::VALUE_OPTIONAL, "The database password") - ->addOption('smtp_host', null, InputOption::VALUE_OPTIONAL, "The SMTP server hostname") - ->addOption('smtp_user', null, InputOption::VALUE_OPTIONAL, "The SMTP server user") - ->addOption('smtp_password', null, InputOption::VALUE_OPTIONAL, "The SMTP server password"); + ->setDescription("UserFrosting Configuration Wizard") + ->setHelp("This command combine the setup:env, setup:db and setup:smtp commands."); } /** @@ -52,262 +34,13 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // Get config - $config = $this->ci->config; - - // Get options - $force = $input->getOption('force'); - - // Display header, - $this->io->title("UserFrosting's Setup Wizard"); - - // Check if the .env file exist. - if (!$force && file_exists($this->envPath)) { - $this->io->note("File `{$this->envPath}` already exist. Use the `php bakery setup -f` command to force setup to run again."); - return; - } - - // There might not be any `.env` file because there may be some custom config or global env values defined on the server. - // We'll check for that. If the configs are empty, we'll assume nothing is defined and go strait to setup. - if (!$force && $config["db.default.host"] != "" && $config["db.default.database"] != "" && $config["db.default.username"] != "") { - $this->io->note("File `{$this->envPath}` was not found, but some database configuration variables are present. Global system environment variables might be defined. If this is not right, use -f option to force setup to run."); - return; - } - - //Goto setup - $this->setupEnv($input); - } - - /** - * Setup the `.env` file. - * - * @param InputInterface $args Command arguments - * @return void - */ - public function setupEnv(InputInterface $args) - { - $this->io->note("Database and SMTP credentials will be saved in `{$this->envPath}`"); - - // Get database info - $dbParams = $this->askForDatabase($args); - - // Test database - $this->testDatabase($dbParams); - - // Ask for SMTP info - $smtpParams = $this->askForSmtp($args); + $command = $this->getApplication()->find('setup:db'); + $command->run($input, $output); - // Save env file - $this->saveFile($dbParams, $smtpParams); + $command = $this->getApplication()->find('setup:smtp'); + $command->run($input, $output); - // At this point, `$this->uf` is still using the old configs. - // We need to refresh the `db.default` config values - $newConfig = array_merge($this->ci->config['db.default'], $dbParams); - $this->ci->config->set("db.default", $newConfig); - } - - /** - * Ask for database crendentials - * - * @param InputInterface $args Command arguments - * @return array The databse credentials - */ - protected function askForDatabase(InputInterface $args) - { - $this->io->section("Setting up database"); - - // Get the db driver choices - $drivers = $this->databaseDrivers(); - $driversList = $drivers->pluck('name')->toArray(); - - // Ask for database type if not defined in command arguments - if ($args->getOption('db_driver')) { - $selectedDriver = $args->getOption('db_driver'); - $driver = $drivers->where('driver', $selectedDriver)->first(); - } else { - $selectedDriver = $this->io->choice("Database type", $driversList); - $driver = $drivers->where('name', $selectedDriver)->first(); - } - - // Get the selected driver. Make sure driver was found - if (!$driver) { - $this->io->error("Invalid database driver: $selectedDriver"); - exit(1); - } - - // Ask further questions based on driver - if ($driver['driver'] == 'sqlite') { - - $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); - - return [ - 'driver' => $driver['driver'], - 'database' => $name - ]; - - } else { - $defaultPort = $driver['defaultPort']; - - $host = ($args->getOption('db_host')) ?: $this->io->ask("Hostname", "localhost"); - $port = ($args->getOption('db_port')) ?: $this->io->ask("Port", $defaultPort); - $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); - $user = ($args->getOption('db_user')) ?: $this->io->ask("Username", "userfrosting"); - $password = ($args->getOption('db_password')) ?: $this->io->askHidden("Password", function ($password) { - // Use custom validator to accept empty password - return $password; - }); - - return [ - 'driver' => $driver['driver'], - 'host' => $host, - 'port' => $port, - 'database' => $name, - 'username' => $user, - 'password' => $password, - 'charset' => $this->ci->config['db.default.charset'] - ]; - } - } - - /** - * Test new database connecion - * - * @param array $dbParams Database params - * @return void (Exit if fails) - */ - protected function testDatabase($dbParams) - { - // Setup a new db connection - $capsule = new Capsule; - $capsule->addConnection($dbParams); - - // Test the db connexion. - try { - $conn = $capsule->getConnection(); - $conn->getPdo(); - $this->io->success("Database connection successful"); - } catch (\PDOException $e) { - $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; - $message .= "Exception: " . $e->getMessage() . PHP_EOL.PHP_EOL; - $message .= "Please check your database configuration and/or google the exception shown above and run the command again."; - $this->io->error($message); - exit(1); - } - } - - /** - * Ask for SMTP credential - * - * @param InputInterface $args Command arguments - * @return array The SMTP connection info - */ - protected function askForSmtp(InputInterface $args) - { - // Ask for the smtp values now - $this->io->section("Email setup"); - $this->io->write("Enter your SMTP server credentials. This is the server used to send emails from the system. Edit `{$this->envPath}` if you have problems sending email later."); - - $smtpHost = ($args->getOption('smtp_host')) ?: $this->io->ask("SMTP Host", "host.example.com"); - $smtpUser = ($args->getOption('smtp_user')) ?: $this->io->ask("SMTP User", "relay@example.com"); - $smtpPassword = ($args->getOption('smtp_password')) ?: $this->io->askHidden("SMTP Password", function ($password) { - // Use custom validator to accept empty password - return $password; - }); - - return [ - 'host' => $smtpHost, - 'user' => $smtpUser, - 'password' => $smtpPassword - ]; - } - - /** - * Write the env file - * - * @param array $dbParams Database params - * @param array $smtpParams SMTP params - * @return void - */ - protected function saveFile($dbParams, $smtpParams) - { - $this->io->section("Saving data"); - - // Prepare file content - if ($dbParams['driver'] == 'sqlite') { - $fileContent = [ - "UF_MODE=\"\"\n", - "DB_DRIVER=\"{$dbParams['driver']}\"\n", - "DB_NAME=\"{$dbParams['database']}\"\n", - "SMTP_HOST=\"{$smtpParams['host']}\"\n", - "SMTP_USER=\"{$smtpParams['user']}\"\n", - "SMTP_PASSWORD=\"{$smtpParams['password']}\"\n" - ]; - } else { - $fileContent = [ - "UF_MODE=\"\"\n", - "DB_DRIVER=\"{$dbParams['driver']}\"\n", - "DB_HOST=\"{$dbParams['host']}\"\n", - "DB_PORT=\"{$dbParams['port']}\"\n", - "DB_NAME=\"{$dbParams['database']}\"\n", - "DB_USER=\"{$dbParams['username']}\"\n", - "DB_PASSWORD=\"{$dbParams['password']}\"\n", - "SMTP_HOST=\"{$smtpParams['host']}\"\n", - "SMTP_USER=\"{$smtpParams['user']}\"\n", - "SMTP_PASSWORD=\"{$smtpParams['password']}\"\n" - ]; - } - - // Let's save this config - file_put_contents($this->envPath, $fileContent); - - // Success - $this->io->success("Database and SMTP credentials saved to `{$this->envPath}`"); - } - - /** - * Return the database choices for the env setup. - * - * @return \Illuminate\Support\Collection - */ - protected function databaseDrivers() - { - return collect([ - [ - "driver" => "mysql", - "name" => "MySQL / MariaDB", - "defaultDBName" => "userfrosting", - "defaultPort" => 3306 - ], - [ - "driver" => "pgsql", - "name" => "ProgreSQL", - "defaultDBName" => "userfrosting", - "defaultPort" => 5432 - ], - [ - "driver" => "sqlsrv", - "name" => "SQL Server", - "defaultDBName" => "userfrosting", - "defaultPort" => 1433 - ], - [ - "driver" => "sqlite", - "name" => "SQLite", - "defaultDBName" => \UserFrosting\DB_DIR . \UserFrosting\DS . 'userfrosting.db', - "defaultPort" => null - ] - ]); - } - - /** - * Returns a list of available drivers - * - * @return array - */ - protected function getDatabaseDriversList() - { - $dbDriverList = $this->databaseDrivers(); - $dbDriverList = $dbDriverList->pluck('driver'); - return $dbDriverList; + $command = $this->getApplication()->find('setup:env'); + $command->run($input, $output); } -} +} \ No newline at end of file diff --git a/app/sprinkles/core/src/Bakery/SetupDbCommand.php b/app/sprinkles/core/src/Bakery/SetupDbCommand.php new file mode 100644 index 000000000..8b0f2162c --- /dev/null +++ b/app/sprinkles/core/src/Bakery/SetupDbCommand.php @@ -0,0 +1,260 @@ +setName("setup:db") + ->setDescription("UserFrosting Database Configuration Wizard") + ->setHelp("Helper command to setup the database configuration. This can also be done manually by editing the app/.env file or using global server environment variables.") + ->addOption('db_driver', null, InputOption::VALUE_OPTIONAL, "The database driver {$this->getDatabaseDriversList()}") + ->addOption('db_name', null, InputOption::VALUE_OPTIONAL, "The database name") + ->addOption('db_host', null, InputOption::VALUE_OPTIONAL, "The database hostname") + ->addOption('db_port', null, InputOption::VALUE_OPTIONAL, "The database port") + ->addOption('db_user', null, InputOption::VALUE_OPTIONAL, "The database user") + ->addOption('db_password', null, InputOption::VALUE_OPTIONAL, "The database password"); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + /** + * @var Config $config Get config + */ + $config = $this->ci->config; + + // Display header, + $this->io->title("UserFrosting's Database Setup Wizard"); + $this->io->note("Database credentials will be saved in `{$this->envPath}`"); + + // Get an instance of the DotenvEditor + $dotenvEditor = new DotenvEditor(\UserFrosting\APP_DIR, false); + $dotenvEditor->load($this->envPath); + $dotenvEditor->save(); // Save make sure empty file is created if none exist before reading it + + // Get keys + $keys = [ + 'DB_HOST' => ($dotenvEditor->keyExists('DB_HOST')) ? $dotenvEditor->getValue('DB_HOST') : '', + 'DB_NAME' => ($dotenvEditor->keyExists('DB_NAME')) ? $dotenvEditor->getValue('DB_NAME') : '', + 'DB_USER' => ($dotenvEditor->keyExists('DB_USER')) ? $dotenvEditor->getValue('DB_USER') : '', + 'DB_PASSWORD' => ($dotenvEditor->keyExists('DB_PASSWORD')) ? $dotenvEditor->getValue('DB_PASSWORD') : '' + ]; + + // There may be some custom config or global env values defined on the server. + // We'll check for that and ask for confirmation in this case. + if ($config["db.default.host"] != $keys['DB_HOST'] || + $config["db.default.database"] != $keys['DB_NAME'] || + $config["db.default.username"] != $keys['DB_USER'] || + $config["db.default.password"] != $keys['DB_PASSWORD']) { + + $this->io->warning("Current database configuration differ from the configuration defined in `{$this->envPath}`. Global system environment variables might be defined."); + + if (!$this->io->confirm('Continue?', false)) { + return; + } + } + + // Get database info + $dbParams = $this->askForDatabase($input); + + // Test database + $this->testDatabase($dbParams); + + // Time to save + $this->io->section("Saving data"); + + // Prepare file content + // N.B.: Can't use the `$dbParams` keys directly since they differ from + // the config one later used to update the config + $fileContent = [ + "DB_DRIVER" => $dbParams['driver'], + "DB_HOST" => $dbParams['host'], + "DB_PORT" => $dbParams['port'], + "DB_NAME" => $dbParams['database'], + "DB_USER" => $dbParams['username'], + "DB_PASSWORD" => $dbParams['password'] + ]; + + foreach ($fileContent as $key => $value) { + $dotenvEditor->setKey($key, $value); + } + $dotenvEditor->save(); + + // At this point, `$this->uf` is still using the old configs. + // We need to refresh the `db.default` config values + $newConfig = array_merge($this->ci->config['db.default'], $dbParams); + $this->ci->config->set("db.default", $newConfig); + + // Success + $this->io->success("Database config successfully saved in `{$this->envPath}`"); + } + + /** + * Ask for database crendentials + * + * @param InputInterface $args Command arguments + * @return array The databse credentials + */ + protected function askForDatabase(InputInterface $args) + { + // Get the db driver choices + $drivers = $this->databaseDrivers(); + $driversList = $drivers->pluck('name')->toArray(); + + // Ask for database type if not defined in command arguments + if ($args->getOption('db_driver')) { + $selectedDriver = $args->getOption('db_driver'); + $driver = $drivers->where('driver', $selectedDriver)->first(); + } else { + $selectedDriver = $this->io->choice("Database type", $driversList); + $driver = $drivers->where('name', $selectedDriver)->first(); + } + + // Get the selected driver. Make sure driver was found + if (!$driver) { + $this->io->error("Invalid database driver: $selectedDriver"); + exit(1); + } + + // Ask further questions based on driver + if ($driver['driver'] == 'sqlite') { + + $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); + + return [ + 'driver' => $driver['driver'], + 'host' => '', + 'port' => '', + 'database' => $name, + 'username' => '', + 'password' => '' + ]; + + } else { + $defaultPort = $driver['defaultPort']; + + $host = ($args->getOption('db_host')) ?: $this->io->ask("Hostname", "localhost"); + $port = ($args->getOption('db_port')) ?: $this->io->ask("Port", $defaultPort); + $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); + $user = ($args->getOption('db_user')) ?: $this->io->ask("Username", "userfrosting"); + $password = ($args->getOption('db_password')) ?: $this->io->askHidden("Password", function ($password) { + // Use custom validator to accept empty password + return $password; + }); + + return [ + 'driver' => $driver['driver'], + 'host' => $host, + 'port' => $port, + 'database' => $name, + 'username' => $user, + 'password' => $password, + 'charset' => $this->ci->config['db.default.charset'] // Used when replacing config later + ]; + } + } + + /** + * Test new database connecion + * + * @param array $dbParams Database params + * @return void (Exit if fails) + */ + protected function testDatabase($dbParams) + { + // Setup a new db connection + $capsule = new Capsule; + $capsule->addConnection($dbParams); + + // Test the db connexion. + try { + $conn = $capsule->getConnection(); + $conn->getPdo(); + $this->io->success("Database connection successful"); + } catch (\PDOException $e) { + $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; + $message .= "Exception: " . $e->getMessage() . PHP_EOL.PHP_EOL; + $message .= "Please check your database configuration and/or google the exception shown above and run the command again."; + $this->io->error($message); + exit(1); + } + } + + /** + * Return the database choices for the env setup. + * + * @return \Illuminate\Support\Collection + */ + protected function databaseDrivers() + { + return collect([ + [ + "driver" => "mysql", + "name" => "MySQL / MariaDB", + "defaultDBName" => "userfrosting", + "defaultPort" => 3306 + ], + [ + "driver" => "pgsql", + "name" => "ProgreSQL", + "defaultDBName" => "userfrosting", + "defaultPort" => 5432 + ], + [ + "driver" => "sqlsrv", + "name" => "SQL Server", + "defaultDBName" => "userfrosting", + "defaultPort" => 1433 + ], + [ + "driver" => "sqlite", + "name" => "SQLite", + "defaultDBName" => \UserFrosting\DB_DIR . \UserFrosting\DS . 'userfrosting.db', + "defaultPort" => null + ] + ]); + } + + /** + * Returns a list of available drivers + * + * @return array + */ + protected function getDatabaseDriversList() + { + $dbDriverList = $this->databaseDrivers(); + $dbDriverList = $dbDriverList->pluck('driver'); + return $dbDriverList; + } +} diff --git a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php new file mode 100644 index 000000000..9db4c2aa2 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php @@ -0,0 +1,96 @@ +setName("setup:env") + ->setDescription("UserFrosting Environment Configuration Wizard") + ->setHelp("Helper command to setup environement mode. This can also be done manually by editing the app/.env file or using global server environment variables.") + ->addOption('mode', null, InputOption::VALUE_OPTIONAL, "The environment to use"); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + // Display header, + $this->io->title("UserFrosting's Environment Setup Wizard"); + $this->io->note("Environment mode will be saved in `{$this->envPath}`"); + $this->io->write("Select desired envrionement mode. Production should only be used when deploying a live app."); + + // Get an instance of the DotenvEditor + $dotenvEditor = new DotenvEditor(\UserFrosting\APP_DIR, false); + $dotenvEditor->load($this->envPath); + + // Ask for mode + $newEnvMode = $this->askForEnv($input); + + // Save new value + $dotenvEditor->setKey($this->modeKey, $newEnvMode); + $dotenvEditor->save(); + + // Success + $this->io->success("Environment mode successfully changed to `$newEnvMode` in `{$this->envPath}`"); + } + + /** + * Ask for env mode + * + * @param InputInterface $args Command arguments + * @return string The new env mode + */ + protected function askForEnv(InputInterface $args) + { + // Ask for mode if not defined in command arguments + if ($args->getOption('mode')) { + return $args->getOption('mode'); + } else { + $newEnvMode = $this->io->choice("Environment Mode", [ + 'default', + 'production', + 'Other...' + ], 'default'); + } + + // Ask for manual input if 'other' was chosen + if ($newEnvMode == 'Other...') { + $newEnvMode = $this->io->ask('Enter desired environment mode'); + } + + return $newEnvMode; + } +} diff --git a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php new file mode 100644 index 000000000..2cc52faf6 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php @@ -0,0 +1,209 @@ +setName('setup:smtp') + ->setDescription('UserFrosting SMTP Configuration Wizard') + ->setHelp('Helper command to setup outgoing email configuration. This can also be done manually by editing the app/.env file or using global server environment variables.') + ->addOption('smtp_host', null, InputOption::VALUE_OPTIONAL, 'The SMTP server hostname') + ->addOption('smtp_user', null, InputOption::VALUE_OPTIONAL, 'The SMTP server user') + ->addOption('smtp_password', null, InputOption::VALUE_OPTIONAL, 'The SMTP server password'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + /** + * @var Config $config Get config + */ + $config = $this->ci->config; + + // Display header, + $this->io->title("UserFrosting's SMTP Setup Wizard"); + $this->io->note("SMTP credentials will be saved in `{$this->envPath}`"); + + // Get an instance of the DotenvEditor + $dotenvEditor = new DotenvEditor(\UserFrosting\APP_DIR, false); + $dotenvEditor->load($this->envPath); + $dotenvEditor->save(); // Save make sure empty file is created if none exist before reading it + + // Get keys + $keys = [ + 'SMTP_HOST' => ($dotenvEditor->keyExists('SMTP_HOST')) ? $dotenvEditor->getValue('SMTP_HOST') : '', + 'SMTP_USER' => ($dotenvEditor->keyExists('SMTP_USER')) ? $dotenvEditor->getValue('SMTP_USER') : '', + 'SMTP_PASSWORD' => ($dotenvEditor->keyExists('SMTP_PASSWORD')) ? $dotenvEditor->getValue('SMTP_PASSWORD') : '' + ]; + + // There may be some custom config or global env values defined on the server. + // We'll check for that and ask for confirmation in this case. + if ($config['mail.host'] != $keys['SMTP_HOST'] || + $config['mail.username'] != $keys['SMTP_USER'] || + $config['mail.password'] != $keys['SMTP_PASSWORD']) { + + $this->io->warning("Current SMTP configuration differ from the configuration defined in `{$this->envPath}`. Global system environment variables might be defined."); + + if (!$this->io->confirm('Continue?', false)) { + return; + } + } + + // Ask for SMTP info + $smtpParams = $this->askForSmtpMethod($input); + + // Time to save + $this->io->section('Saving data'); + + foreach ($smtpParams as $key => $value) { + $dotenvEditor->setKey($key, $value); + } + $dotenvEditor->save(); + + // Success + $this->io->success("SMTP credentials saved to `{$this->envPath}`"); + } + + /** + * Ask with setup method to use + * + * @param InputInterface $input + * @return array The SMTP connection info + */ + protected function askForSmtpMethod(InputInterface $input) + { + // If the user defined any of the command input argument, skip right to SMTP method + if ($input->getOption('smtp_host') || $input->getOption('smtp_user') || $input->getOption('smtp_password')) { + return $this->askForSmtp($input); + } + + // Display nice explanation and ask wich method to use + $this->io->write("In order to send registration emails, UserFrosting requires an outgoing mail server. When using UserFrosting in a production environment, a SMTP server should be used. A Gmail account can be used if you're only playing with UserFrosting or on a local dev environment. You can also choose to not setup an outgoing mail server at the moment, but account registration won't work. You can always re-run this setup or edit `{$this->envPath}` if you have problems sending email later."); + + $choice = $this->io->choice('Select setup method', [self::Setup_SMTP, self::Setup_Gmail, self::Setup_None], self::Setup_SMTP); + + switch ($choice) { + case self::Setup_SMTP: + return $this->askForSmtp($input); + break; + case self::Setup_Gmail: + return $this->askForGmail($input); + break; + case self::Setup_None: + default: + return $this->askForNone($input); + break; + } + } + + /** + * Ask for SMTP credential + * + * @param InputInterface $input Command arguments + * @return array The SMTP connection info + */ + protected function askForSmtp(InputInterface $input) + { + // Ask for the smtp values now + $smtpHost = ($input->getOption('smtp_host')) ?: $this->io->ask('SMTP Server Host', 'host.example.com'); + $smtpUser = ($input->getOption('smtp_user')) ?: $this->io->ask('SMTP Server User', 'relay@example.com'); + $smtpPassword = ($input->getOption('smtp_password')) ?: $this->io->askHidden('SMTP Server Password', function ($password) { + // Use custom validator to accept empty password + return $password; + }); + + return [ + 'SMTP_HOST' => $smtpHost, + 'SMTP_USER' => $smtpUser, + 'SMTP_PASSWORD' => $smtpPassword + ]; + } + + /** + * Ask for Gmail + * + * @param InputInterface $input Command arguments + * @return array The SMTP connection info + */ + protected function askForGmail(InputInterface $input) + { + $smtpUser = ($input->getOption('smtp_user')) ?: $this->io->ask('Your full Gmail (e.g. example@gmail.com)'); + $smtpPassword = ($input->getOption('smtp_password')) ?: $this->io->askHidden('Your Gmail password', function ($password) { + // Use custom validator to accept empty password + return $password; + }); + + return [ + 'SMTP_HOST' => 'smtp.gmail.com', + 'SMTP_USER' => $smtpUser, + 'SMTP_PASSWORD' => $smtpPassword + ]; + } + + /** + * Process the "no email support" setup option + * + * @param InputInterface $input + * @return array The SMTP connection info + */ + protected function askForNone(InputInterface $input) + { + // Display big warning and confirmation + $this->io->warning("By not setting up any outgoing mail server, public account registration won't work."); + + if ($this->io->confirm('Continue ?', false)) { + return [ + 'SMTP_HOST' => '', + 'SMTP_USER' => '', + 'SMTP_PASSWORD' => '' + ]; + } else { + $this->askForSmtpMethod($input); + } + } +} From 4da78d0f2cd253cc2bdde9ce995831b1b87d80fe Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 May 2018 23:51:17 -0400 Subject: [PATCH 073/237] [Vagrant] Added the directory name to the VirtualBox VM name Helps preventing the `A VirtualBox machine with the name 'userfrosting' already exists.` error to show up. --- Vagrantfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Vagrantfile b/Vagrantfile index 919d30127..f86db1266 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -16,10 +16,17 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| end if File.exists? homesteadYamlPath then - Homestead.configure(config, YAML::load(File.read(homesteadYamlPath))) + settings = YAML::load(File.read(homesteadYamlPath)) + Homestead.configure(config, settings) end if File.exists? afterScriptPath then config.vm.provision "shell", path: afterScriptPath end + + config.vm.provider :virtualbox do |vb| + vb_name = settings["name"] ||= "homestead-7" + vb_name = vb_name + "_" + File.basename(Dir.pwd) + vb.name = vb_name + end end \ No newline at end of file From a96bcb0d67b013c576000897c044f77fd8875f5a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 14 Aug 2018 20:48:08 -0400 Subject: [PATCH 074/237] Prepare for alpha 1 release --- app/defines.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/defines.php b/app/defines.php index 0fb809245..81d23cf77 100755 --- a/app/defines.php +++ b/app/defines.php @@ -3,7 +3,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.2.0-alpha'); +define('UserFrosting\VERSION', '4.2.0-alpha.1'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\DEBUG_CONFIG', false); From 14a81fea6f6dc4771143c10cfd742254db30a39a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 14 Aug 2018 21:02:54 -0400 Subject: [PATCH 075/237] Implement New ResourceLocator Merging from `feature-locator` branch --- app/defines.php | 6 + .../src/ServicesProvider/ServicesProvider.php | 12 +- .../src/ServicesProvider/ServicesProvider.php | 4 +- app/sprinkles/core/composer.json | 15 +- app/sprinkles/core/defines.php | 7 + .../src/Bakery/MigrateRollbackCommand.php | 9 +- app/sprinkles/core/src/Bakery/SeedCommand.php | 56 ++--- .../core/src/Bakery/SeedListCommand.php | 9 +- app/sprinkles/core/src/Core.php | 15 ++ .../Migrator/DatabaseMigrationRepository.php | 11 + .../Migrator/MigrationDependencyAnalyser.php | 6 +- .../Database/Migrator/MigrationLocator.php | 103 +++------ .../Migrator/MigrationLocatorInterface.php | 8 - .../MigrationRollbackDependencyAnalyser.php | 75 +++++++ .../core/src/Database/Migrator/Migrator.php | 212 +++++++++++------- .../core/src/Database/Seeder/BaseSeed.php | 42 ++++ ...{SeederInterface.php => SeedInterface.php} | 2 +- .../core/src/Database/Seeder/Seeder.php | 127 ++++++++++- .../src/Database/Seeder/SeederLocator.php | 134 ----------- .../src/ServicesProvider/ServicesProvider.php | 48 +--- app/sprinkles/core/src/Util/ClassFinder.php | 78 ------- .../DatabaseMigratorIntegrationTest.php | 59 ++++- .../Integration/DatabaseMigratorTest.php | 111 +++++++-- .../Integration/MigrationLocatorTest.php | 178 ++++++--------- .../tests/Integration/Seeder/SeederTests.php | 172 ++++++++++++++ .../tests/Integration/Seeder/Seeds/Seed1.php | 18 ++ .../tests/Integration/Seeder/Seeds/Seed2.php | 16 ++ .../Integration/Seeder/Seeds/Test/Seed.php | 18 ++ app/system/Bakery/Bakery.php | 124 +++++----- app/system/ServicesProvider.php | 73 ++---- app/system/Sprinkle/SprinkleManager.php | 53 +---- 31 files changed, 1032 insertions(+), 769 deletions(-) create mode 100644 app/sprinkles/core/defines.php create mode 100644 app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php create mode 100644 app/sprinkles/core/src/Database/Seeder/BaseSeed.php rename app/sprinkles/core/src/Database/Seeder/{SeederInterface.php => SeedInterface.php} (93%) delete mode 100644 app/sprinkles/core/src/Database/Seeder/SeederLocator.php delete mode 100644 app/sprinkles/core/src/Util/ClassFinder.php create mode 100644 app/sprinkles/core/tests/Integration/Seeder/SeederTests.php create mode 100644 app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php create mode 100644 app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed2.php create mode 100644 app/sprinkles/core/tests/Integration/Seeder/Seeds/Test/Seed.php diff --git a/app/defines.php b/app/defines.php index 81d23cf77..f7f22a03e 100755 --- a/app/defines.php +++ b/app/defines.php @@ -53,6 +53,12 @@ define('UserFrosting\FACTORY_DIR_NAME', 'factories'); define('UserFrosting\PUBLIC_DIR_NAME', 'public'); +// Paths for the different class sources +define('UserFrosting\BAKERY_DIR', SRC_DIR_NAME . DS . 'Bakery'); + +// Path to system Bakery commands +define('UserFrosting\BAKERY_SYSTEM_DIR', APP_DIR_NAME . DS . 'system' . DS . 'Bakery' . DS . 'Command'); + // Full path to frontend vendor asset directories define('UserFrosting\ASSET_DIR', APP_DIR_NAME . DS . ASSET_DIR_NAME); define('UserFrosting\NPM_ASSET_DIR', ASSET_DIR . DS . 'node_modules'); diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index 77b636ec0..037d98269 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -50,7 +50,7 @@ public function register($container) // Register paths for user theme, if a user is logged in // We catch any authorization-related exceptions, so that error pages can be rendered. try { - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $c->authenticator; $currentUser = $c->currentUser; } catch (\Exception $e) { @@ -58,7 +58,7 @@ public function register($container) } if ($authenticator->check()) { - $c->sprinkleManager->addResource('assets', $currentUser->theme); + // TODO $c->sprinkleManager->addResource('assets', $currentUser->theme); } return $assets; @@ -103,7 +103,7 @@ public function register($container) // Add paths for user theme, if a user is logged in // We catch any authorization-related exceptions, so that error pages can be rendered. try { - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $c->authenticator; $currentUser = $c->currentUser; } catch (\Exception $e) { @@ -112,7 +112,7 @@ public function register($container) if ($authenticator->check()) { // Add paths to locale files for user theme - $themePath = $c->sprinkleManager->addResource('locale', $currentUser->theme); + // TODO $themePath = $c->sprinkleManager->addResource('locale', $currentUser->theme); // Add user locale $pathBuilder->addLocales($currentUser->locale); @@ -134,7 +134,7 @@ public function register($container) // Add paths for user theme, if a user is logged in // We catch any authorization-related exceptions, so that error pages can be rendered. try { - /** @var UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ + /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ $authenticator = $c->authenticator; $currentUser = $c->currentUser; } catch (\Exception $e) { @@ -143,7 +143,7 @@ public function register($container) if ($authenticator->check()) { $theme = $currentUser->theme; - $themePath = $c->sprinkleManager->addResource('templates', $theme); + // TODO $themePath = $c->sprinkleManager->addResource('templates', $theme); if ($themePath) { $loader = $twig->getLoader(); $loader->prependPath($themePath); diff --git a/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php index 061d90c51..c7ded2b12 100644 --- a/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php @@ -53,8 +53,8 @@ public function register($container) * This method is invoked when a user completes the login process. * * Returns a callback that handles setting the `UF-Redirect` header after a successful login. - * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Message\ResponseInterface $response * @param array $args * @return \Psr\Http\Message\ResponseInterface */ diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index 2c01b7093..cc660c4de 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -24,6 +24,13 @@ "name": "Srinivas Nukala" } ], + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/userfrosting/UniformResourceLocator", + "no-api": true + } + ], "require": { "doctrine/dbal": "^2.5", "filp/whoops": "^2.1", @@ -40,16 +47,20 @@ "slim/twig-view": "^1.2", "symfony/http-foundation": "*", "twig/twig": "^1.18", - "userfrosting/assets": ">=5", - "userfrosting/config": "~4.1.0", + "userfrosting/assets": "dev-feature-locator", + "userfrosting/config": "dev-feature-locator", "userfrosting/cache": "~4.1.0", "userfrosting/fortress": "~4.1.1", "userfrosting/i18n": "~4.1.0", + "userfrosting/uniformresourcelocator": "dev-develop", "userfrosting/session": "~4.1.0", "userfrosting/support": "~4.1.1", "vlucas/phpdotenv": "^2" }, "autoload": { + "files" : [ + "defines.php" + ], "psr-4": { "UserFrosting\\Sprinkle\\Core\\": "src/" } diff --git a/app/sprinkles/core/defines.php b/app/sprinkles/core/defines.php new file mode 100644 index 000000000..a71edcf75 --- /dev/null +++ b/app/sprinkles/core/defines.php @@ -0,0 +1,7 @@ +addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') + ->addOption('migration', 'm', InputOption::VALUE_REQUIRED, 'The specific migration to rollback.') ->addOption('steps', 's', InputOption::VALUE_REQUIRED, 'Number of batch to rollback.', 1); } @@ -44,13 +45,19 @@ protected function execute(InputInterface $input, OutputInterface $output) // Get options $steps = $input->getOption('steps'); $pretend = $input->getOption('pretend'); + $migration = $input->getOption('migration'); // Get migrator $migrator = $this->setupMigrator($input); // Rollback migrations try { - $migrated = $migrator->rollback(['pretend' => $pretend, 'steps' => $steps]); + // If we have a specific to rollback, do this. Otherwise, do a normal rollback + if ($migration) { + $migrated = $migrator->rollbackMigration($migration, ['pretend' => $pretend]); + } else { + $migrated = $migrator->rollback(['pretend' => $pretend, 'steps' => $steps]); + } } catch (\Exception $e) { $this->io->writeln($migrator->getNotes()); $this->io->error($e->getMessage()); diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index dbfa878c9..4d8988112 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -11,8 +11,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; -use UserFrosting\Sprinkle\Core\Database\Seeder\SeederInterface; -use UserFrosting\Sprinkle\Core\Util\ClassFinder; +use UserFrosting\Sprinkle\Core\Database\Seeder\Seeder; use UserFrosting\System\Bakery\BaseCommand; use UserFrosting\System\Bakery\ConfirmableTrait; @@ -26,6 +25,11 @@ class SeedCommand extends BaseCommand { use ConfirmableTrait; + /** + * @var Seeder $seeder + */ + protected $seeder; + /** * {@inheritDoc} */ @@ -45,6 +49,9 @@ protected function execute(InputInterface $input, OutputInterface $output) { $this->io->title("UserFrosting's Seeder"); + // Prepare seed locator + $this->seeder = new Seeder($this->ci); + // Get options $classes = $input->getArgument('class'); @@ -55,13 +62,18 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($classes as $className) { // Get seed class and - $seed = $this->getSeed($className); + try { + $seedClass = $this->seeder->getSeedClass($className); + } catch (\Exception $e) { + $this->io->error($e->getMessage()); + exit(1); + } // Display the class we are going to use as info - $this->io->writeln("Seeding class `".get_class($seed)."`"); + $this->io->writeln("Seeding class `".get_class($seedClass)."`"); // Add seed class to list - $seeds[] = $seed; + $seeds[] = $seedClass; } // Confirm action when in production mode @@ -69,14 +81,10 @@ protected function execute(InputInterface $input, OutputInterface $output) exit(1); } - // TODO :: - // - Disable Model guarded policy - // - Create default seeds list/service - // Run seeds foreach ($seeds as $seed) { try { - $seed->run(); + $this->seeder->executeSeed($seed); } catch (\Exception $e) { $this->io->error($e->getMessage()); exit(1); @@ -86,32 +94,4 @@ protected function execute(InputInterface $input, OutputInterface $output) // Success $this->io->success('Seed successful !'); } - - /** - * Setup migrator and the shared options between other command - * - * @param string $name The seeder name - * @return mixed The seeder class instance - */ - protected function getSeed($name) - { - $finder = new ClassFinder($this->ci->sprinkleManager); - - try { - $class = $finder->getClass("Database\\Seeds\\$name"); - } catch (\Exception $e) { - $this->io->error($e->getMessage()); - exit(1); - } - - $seedClass = new $class($this->ci); - - // Class must be an instance of `SeederInterface` - if (!$seedClass instanceof SeederInterface) { - $this->io->error('Seed class must be an instance of `SeederInterface`'); - exit(1); - } - - return $seedClass; - } } diff --git a/app/sprinkles/core/src/Bakery/SeedListCommand.php b/app/sprinkles/core/src/Bakery/SeedListCommand.php index 1bd91e5de..8a951bb34 100644 --- a/app/sprinkles/core/src/Bakery/SeedListCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedListCommand.php @@ -7,10 +7,9 @@ */ namespace UserFrosting\Sprinkle\Core\Bakery; -use Illuminate\Filesystem\Filesystem; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use UserFrosting\Sprinkle\Core\Database\Seeder\SeederLocator; +use UserFrosting\Sprinkle\Core\Database\Seeder\Seeder; use UserFrosting\System\Bakery\BaseCommand; /** @@ -37,8 +36,8 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $this->io->title("Database Seeds List"); - $locator = new SeederLocator($this->ci->sprinkleManager, new Filesystem); - $seeds = $locator->getSeeders(); - $this->io->table(['Name', 'Namespace', 'Sprinkle'], $seeds->toArray()); + $seeder = new Seeder($this->ci); + $seeds = $seeder->getSeeds(); + $this->io->table(['Name', 'Namespace', 'Sprinkle'], $seeds); } } diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index d7e1dcb57..6af67897d 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -12,6 +12,7 @@ use UserFrosting\Sprinkle\Core\Util\EnvironmentInfo; use UserFrosting\Sprinkle\Core\Util\ShutdownHandler; use UserFrosting\System\Sprinkle\Sprinkle; +use Interop\Container\ContainerInterface; /** * Bootstrapper class for the core sprinkle. @@ -20,6 +21,20 @@ */ class Core extends Sprinkle { + /** + * Create a new Sprinkle object. + * + * @param ContainerInterface $ci The global container object, which holds all your services. + */ + public function __construct(ContainerInterface $ci) + { + $this->ci = $ci; + + // Register core locator streams + $this->ci->locator->registerStream('migrations', '', \UserFrosting\MIGRATIONS_DIR); + $this->ci->locator->registerStream('seeds', '', \UserFrosting\SEEDS_DIR); + } + /** * Defines which events in the UF lifecycle our Sprinkle should hook into. */ diff --git a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php index fe1d6d76d..d80144c70 100644 --- a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php +++ b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php @@ -79,6 +79,17 @@ public function getMigrations($steps = -1, $order = 'asc') return $query->orderBy('id', $order)->get(); } + /** + * Get details about a specific migration + * + * @param string $migration The migration class + * @return \stdClass The migration info + */ + public function getMigration($migration) + { + return $this->table()->where('migration', $migration)->first(); + } + /** * Get the last migration batch in reserve order they were ran (last one first) * diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php index 230bc15fa..af337ab4b 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php @@ -93,9 +93,6 @@ public function analyse() */ protected function validateClassDependencies($migrationName) { - // Get migration dependencies - $dependencies = $this->getMigrationDependencies($migrationName); - // If it's already marked as fulfillable, it's fulfillable // Return true directly (it's already marked) if ($this->fulfillable->contains($migrationName)) { @@ -114,6 +111,9 @@ protected function validateClassDependencies($migrationName) return $this->markAsFulfillable($migrationName); } + // Get migration dependencies + $dependencies = $this->getMigrationDependencies($migrationName); + // Loop dependencies. If one is not fulfillable, then this migration is not either foreach ($dependencies as $dependency) { diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php index dd724a5ce..4a95ec83b 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php @@ -7,9 +7,9 @@ */ namespace UserFrosting\Sprinkle\Core\Database\Migrator; -use Illuminate\Filesystem\Filesystem; use Illuminate\Support\Str; -use UserFrosting\System\Sprinkle\SprinkleManager; +use UserFrosting\UniformResourceLocator\Resource; +use UserFrosting\UniformResourceLocator\ResourceLocator; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocatorInterface; /** @@ -22,106 +22,59 @@ class MigrationLocator implements MigrationLocatorInterface { /** - * @var SprinkleManager The Sprinkle manager service + * @var ResourceLocator The locator service */ - protected $sprinkleManager; + protected $locator; /** - * @var Filesystem The filesystem instance + * @var string The resource locator migration scheme */ - protected $files; + protected $scheme = 'migrations://'; /** - * Class Constructor + * Class Constructor * - * @param SprinkleManager $sprinkleManager The sprinkle manager services - * @param Filesystem $files The filesystem instance + * @param ResourceLocator $locator The locator services */ - public function __construct(SprinkleManager $sprinkleManager, Filesystem $files) + public function __construct(ResourceLocator $locator) { - $this->sprinkleManager = $sprinkleManager; - $this->files = $files; + $this->locator = $locator; } /** - * Returm a list of all available migration available for a specific sprinkle + * Loop all the available sprinkles and return a list of their migrations * - * @param string $sprinkleName The sprinkle name - * @return array The list of available migration classes - */ - public function getMigrationsForSprinkle($sprinkleName) - { - // Get the sprinkle migration path and get all files in that path recursively - $path = $this->migrationDirectoryPath($sprinkleName); - - // If directory diesn't exist, stop - if (!$this->files->exists($path)) { - return []; - } - - // Get files - $files = $this->files->allFiles($path); - - // Transform the path into the mgiration full class name - $migrations = collect($files)->transform(function ($file) use ($sprinkleName, $path) { - return $this->getMigrationClassName($file, $path, $sprinkleName); - }); - - // Return as array - return $migrations->all(); - } - - /** - * Loop all the available sprinkles and return a list of their migrations - * - * @return array A list of all the migration files found for every sprinkle + * @return array A list of all the migration files found for every sprinkle */ public function getMigrations() { - $migrationsFiles = []; - foreach ($this->sprinkleManager->getSprinkleNames() as $sprinkle) { - $migrationsFiles = array_merge($this->getMigrationsForSprinkle($sprinkle), $migrationsFiles); - } + $migrationFiles = $this->locator->listResources($this->scheme); - return $migrationsFiles; - } - - /** - * Returns the path of the Migration directory. - * - * @param string $sprinkleName - * @return string The sprinkle Migration dir path - */ - protected function migrationDirectoryPath($sprinkleName) - { - return \UserFrosting\SPRINKLES_DIR . - \UserFrosting\DS . - $sprinkleName . - \UserFrosting\DS . - \UserFrosting\SRC_DIR_NAME . - "/Database/Migrations"; + $migrations = []; + foreach ($migrationFiles as $migrationFile) { + $migrations[] = $this->getMigrationDetails($migrationFile); + } + return $migrations; } /** - * Get the full classname of a migration based on the absolute file path, - * the initial search path and the SprinkleName + * Return an array of migration details inclusing the classname and the sprinkle name * - * @param string $file The migration file absolute path - * @param string $path The initial search path - * @param string $sprinkleName The sprinkle name - * @return string The migration class name + * @param Resource $file The migration file + * @return string The migration full class path */ - protected function getMigrationClassName($file, $path, $sprinkleName) + protected function getMigrationDetails(Resource $file) { // Format the sprinkle name for the namespace + $sprinkleName = $file->getLocation()->getName(); $sprinkleName = Str::studly($sprinkleName); - // Extract the class name from the path and file - $relativePath = str_replace($path, '', $file); - $className = str_replace('.php', '', $relativePath); - $className = str_replace('/', '\\', $className); + // Getting base path, name and classname + $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); + $name = $basePath . $file->getFilename(); + $className = str_replace('/', '\\', $basePath) . $file->getFilename(); // Build the class name and namespace - return "\\UserFrosting\\Sprinkle\\".$sprinkleName."\\Database\\Migrations" . $className; + return "\\UserFrosting\\Sprinkle\\$sprinkleName\\Database\\Migrations\\$className"; } } diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php index b98ba0925..9907412dc 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php @@ -16,14 +16,6 @@ */ interface MigrationLocatorInterface { - /** - * Returm a list of all available migration available for a specific sprinkle - * - * @param string $sprinkleName The sprinkle name - * @return array The list of available migration classes - */ - public function getMigrationsForSprinkle($sprinkleName); - /** * Loop all the available sprinkles and return a list of their migrations * diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php new file mode 100644 index 000000000..231ed7b73 --- /dev/null +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php @@ -0,0 +1,75 @@ +pending = collect($installed); + $this->installed = collect($rollback); + } + + /** + * Received each installed migrations and determine if it depends on the + * migrations we want to delete (rollback). It can if no other installed + * migrations depends on it. In this context, fulfillable/unfulfillable + * represent the same thing as "up" dependencies. fulfillable can be + * rolledback, unfulfillable cannot. + * + * @param string $migrationName The migration classname + * @return bool True/False if the migration is fulfillable + */ + protected function validateClassDependencies($migrationName) + { + // If it's already marked as fulfillable, it's fulfillable + // Return true directly (it's already marked) + if ($this->fulfillable->contains($migrationName)) { + return true; + } + + // If it's already marked as unfulfillable, it's unfulfillable + // Return false directly (it's already marked) + if ($this->unfulfillable->contains($migrationName)) { + return false; + } + + // If it's in the list of migration to rollback (installed), it's ok to delete this one + if ($this->installed->contains($migrationName)) { + return $this->markAsFulfillable($migrationName); + } + + // Get migration dependencies + $dependencies = $this->getMigrationDependencies($migrationName); + + // If this migration has a dependencies for one of the migration to + // rollback (installed), we can't perform the rollback + if (array_intersect($this->installed->toArray(), $dependencies)) { + return $this->markAsUnfulfillable($migrationName); + } + + // If no dependencies returned false, it's fulfillable + return $this->markAsFulfillable($migrationName); + } +} diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index 0c7ab5dbd..c74f24522 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -12,6 +12,7 @@ use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocatorInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRepositoryInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationDependencyAnalyser as Analyser; +use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRollbackDependencyAnalyser as RollbackAnalyser; use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Util\BadClassNameException; @@ -40,7 +41,7 @@ class Migrator protected $locator; /** - * @var string The connection name + * @var string The connection name */ protected $connection; @@ -50,11 +51,11 @@ class Migrator protected $notes = []; /** - * Constructor + * Constructor * - * @param Capsule $db The database instance - * @param MigrationRepositoryInterface $repository The migration repository - * @param MigrationLocatorInterface $locator The Migration locator + * @param Capsule $db The database instance + * @param MigrationRepositoryInterface $repository The migration repository + * @param MigrationLocatorInterface $locator The Migration locator */ public function __construct(Capsule $db, MigrationRepositoryInterface $repository, MigrationLocatorInterface $locator) { @@ -64,10 +65,10 @@ public function __construct(Capsule $db, MigrationRepositoryInterface $repositor } /** - * Run all the specified migrations up. Check that dependencies are met before running + * Run all the specified migrations up. Check that dependencies are met before running * - * @param array $options Options for the current operations [step, pretend] - * @return array The list of ran migrations + * @param array $options Options for the current operations [step, pretend] + * @return array The list of ran migrations */ public function run(array $options = []) { @@ -106,11 +107,11 @@ public function run(array $options = []) } /** - * Get the migration classes that have not yet run. + * Get the migration classes that have not yet run. * - * @param array $available The available migrations returned by the migration locator - * @param array $ran The list of already ran migrations returned by the migration repository - * @return array The list of pending migrations, ie the available migrations not ran yet + * @param array $available The available migrations returned by the migration locator + * @param array $ran The list of already ran migrations returned by the migration repository + * @return array The list of pending migrations, ie the available migrations not ran yet */ public function pendingMigrations($available, $ran) { @@ -120,11 +121,11 @@ public function pendingMigrations($available, $ran) } /** - * Run an array of migrations. + * Run an array of migrations. * - * @param array $migrations An array of migrations classes names to be run (unsorted, unvalidated) - * @param array $options The options for the current operation [step, pretend] - * @return void + * @param array $migrations An array of migrations classes names to be run (unsorted, unvalidated) + * @param array $options The options for the current operation [step, pretend] + * @return void */ protected function runPending(array $migrations, array $options = []) { @@ -152,12 +153,12 @@ protected function runPending(array $migrations, array $options = []) } /** - * Run "up" a migration class + * Run "up" a migration class * - * @param string $migrationClass The migration class name - * @param int $batch The current bacth number - * @param bool $pretend If this operation should be pretended / faked - * @return void + * @param string $migrationClass The migration class name + * @param int $batch The current bacth number + * @param bool $pretend If this operation should be pretended / faked + * @return void */ protected function runUp($migrationClass, $batch, $pretend) { @@ -193,10 +194,10 @@ protected function runUp($migrationClass, $batch, $pretend) } /** - * Rollback the last migration operation. + * Rollback the last migration operation. * - * @param array $options The options for the current operation [steps, pretend] - * @return array The list of rolledback migration classes + * @param array $options The options for the current operation [steps, pretend] + * @return array The list of rolledback migration classes */ public function rollback(array $options = []) { @@ -214,6 +215,30 @@ public function rollback(array $options = []) } } + /** + * Rollback a specific migration + * + * @param string $migration The Migration to rollback + * @param array $options + * @return array The list of rolledback migration classes + */ + public function rollbackMigration($migration, array $options = []) + { + $this->notes = []; + + // Get the migration detail from the repository + $migrationObject = $this->repository->getMigration($migration); + + // Make sure the migration was found. If not, return same empty array + // as the main rollback method + if (!$migrationObject) { + return []; + } + + // Rollback the migration + return $this->rollbackMigrations([$migrationObject->migration], $options); + } + /** * Get the migrations for a rollback operation. * @@ -231,11 +256,11 @@ protected function getMigrationsForRollback(array $options) } /** - * Rollback the given migrations. + * Rollback the given migrations. * - * @param array $migrations An array of migrations to rollback formated as an eloquent collection - * @param array $options The options for the current operation - * @return array The list of rolledback migration classes + * @param array $migrations An array of migrations to rollback formated as an eloquent collection + * @param array $options The options for the current operation + * @return array The list of rolledback migration classes */ protected function rollbackMigrations(array $migrations, array $options) { @@ -244,6 +269,12 @@ protected function rollbackMigrations(array $migrations, array $options) // Get the available migration classes in the filesystem $availableMigrations = collect($this->getAvailableMigrations()); + // Extract some options + $pretend = Arr::get($options, 'pretend', false); + + // Check for dependencies + $this->checkRollbackDependencies($migrations); + // Next we will run through all of the migrations and call the "down" method // which will reverse each migration in order. This getLast method on the // repository already returns these migration's classenames in reverse order. @@ -251,16 +282,18 @@ protected function rollbackMigrations(array $migrations, array $options) // We have to make sure the class exist first if (!$availableMigrations->contains($migration)) { + // NOTE This next was commented because if a class doesn't exist, + // you'll get stuck and prevent futher classes to be rolledback + // until this class is put back in the system. Might wan't to + // display a warning instead of silently skipping it. See related "todo" in "reset" method //throw new \Exception("Can't rollback migrations `$migration`. The migration class doesn't exist"); + $this->note("WARNING: Can't rollback migrations `$migration`. The migration class doesn't exist"); continue; } // Add the migration to the list of rolledback migration $rolledBack[] = $migration; - // Extract some options - $pretend = Arr::get($options, 'pretend', false); - // Run the migration down $this->runDown($migration, $pretend); } @@ -269,10 +302,31 @@ protected function rollbackMigrations(array $migrations, array $options) } /** - * Rolls all of the currently applied migrations back. + * Check if migrations can be rolledback. + * + * @param array $migrations The migrations classes to rollback + * @throws \Exception If rollback can't be performed + */ + protected function checkRollbackDependencies($migrations) + { + // Get ran migrations + $ranMigrations = $this->repository->getMigrationsList(); + + // Setup rollback analyser + $analyser = new RollbackAnalyser($ranMigrations, $migrations); + + // Any rollback that creates an unfulfilled dependency will cause this script to throw an exception + if ($unfulfillable = $analyser->getUnfulfillable()) { + $unfulfillableList = implode(", ", $unfulfillable); + throw new \Exception("Some migrations can't be rolled back since the following migrations depends on it :: $unfulfillableList"); + } + } + + /** + * Rolls all of the currently applied migrations back. * - * @param bool $pretend Should this operation be pretended - * @return array An array of all the rolledback migration classes + * @param bool $pretend Should this operation be pretended + * @return array An array of all the rolledback migration classes */ public function reset($pretend = false) { @@ -294,11 +348,11 @@ public function reset($pretend = false) } /** - * Run "down" a migration instance. + * Run "down" a migration instance. * - * @param string $migrationClass The migration class name - * @param bool $pretend Is the operation should be pretended - * @return void + * @param string $migrationClass The migration class name + * @param bool $pretend Is the operation should be pretended + * @return void */ protected function runDown($migrationClass, $pretend) { @@ -321,12 +375,12 @@ protected function runDown($migrationClass, $pretend) } /** - * Run a migration inside a transaction if the database supports it. - * Note : As of Laravel 5.4, only PostgresGrammar supports it + * Run a migration inside a transaction if the database supports it. + * Note : As of Laravel 5.4, only PostgresGrammar supports it * - * @param object $migration The migration instance - * @param string $method The method used [up, down] - * @return void + * @param object $migration The migration instance + * @param string $method The method used [up, down] + * @return void */ protected function runMigration($migration, $method) { @@ -345,11 +399,11 @@ protected function runMigration($migration, $method) } /** - * Pretend to run the migrations. + * Pretend to run the migrations. * - * @param object $migration The migration instance - * @param string $method The method used [up, down] - * @return void + * @param object $migration The migration instance + * @param string $method The method used [up, down] + * @return void */ protected function pretendToRun($migration, $method) { @@ -362,11 +416,11 @@ protected function pretendToRun($migration, $method) } /** - * Get all of the queries that would be run for a migration. + * Get all of the queries that would be run for a migration. * - * @param object $migration The migration instance - * @param string $method The method used [up, down] - * @return array The queries executed by the processed schema + * @param object $migration The migration instance + * @param string $method The method used [up, down] + * @return array The queries executed by the processed schema */ protected function getQueries($migration, $method) { @@ -381,10 +435,10 @@ protected function getQueries($migration, $method) } /** - * Resolve a migration instance from it's class name. + * Resolve a migration instance from it's class name. * - * @param string $migrationClass The class name - * @return object The migration class instance + * @param string $migrationClass The class name + * @return object The migration class instance */ public function resolve($migrationClass) { @@ -396,9 +450,9 @@ public function resolve($migrationClass) } /** - * Get all of the migration files in a given path. + * Get all of the migration files in a given path. * - * @return array The list of migration classes found in the filesystem + * @return array The list of migration classes found in the filesystem */ public function getAvailableMigrations() { @@ -406,9 +460,9 @@ public function getAvailableMigrations() } /** - * Get the migration repository instance. + * Get the migration repository instance. * - * @return \Illuminate\Database\Migrations\MigrationRepositoryInterface + * @return \Illuminate\Database\Migrations\MigrationRepositoryInterface */ public function getRepository() { @@ -416,9 +470,9 @@ public function getRepository() } /** - * Set the migration repository instance + * Set the migration repository instance * - * @param MigrationRepositoryInterface $repository + * @param MigrationRepositoryInterface $repository */ public function setRepository(MigrationRepositoryInterface $repository) { @@ -426,9 +480,9 @@ public function setRepository(MigrationRepositoryInterface $repository) } /** - * Determine if the migration repository exists. + * Determine if the migration repository exists. * - * @return bool If the repository exist + * @return bool If the repository exist */ public function repositoryExists() { @@ -436,9 +490,9 @@ public function repositoryExists() } /** - * Get the migration locator instance. + * Get the migration locator instance. * - * @return MigrationLocatorInterface + * @return MigrationLocatorInterface */ public function getLocator() { @@ -446,9 +500,9 @@ public function getLocator() } /** - * Set the migration locator instance + * Set the migration locator instance * - * @param MigrationLocatorInterface $locator + * @param MigrationLocatorInterface $locator */ public function setLocator(MigrationLocatorInterface $locator) { @@ -456,9 +510,9 @@ public function setLocator(MigrationLocatorInterface $locator) } /** - * Get the schema builder. + * Get the schema builder. * - * @return \Illuminate\Database\Schema\Builder + * @return \Illuminate\Database\Schema\Builder */ public function getSchemaBuilder() { @@ -466,9 +520,9 @@ public function getSchemaBuilder() } /** - * Return the connection instance + * Return the connection instance * - * @return \Illuminate\Database\Connection + * @return \Illuminate\Database\Connection */ public function getConnection() { @@ -476,9 +530,9 @@ public function getConnection() } /** - * Define which connection to use + * Define which connection to use * - * @param string $name The connection name + * @param string $name The connection name */ public function setConnection($name) { @@ -487,8 +541,8 @@ public function setConnection($name) } /** - * Get instance of Grammar - * @return \Illuminate\Database\Schema\Grammars\Grammar + * Get instance of Grammar + * @return \Illuminate\Database\Schema\Grammars\Grammar */ protected function getSchemaGrammar() { @@ -496,10 +550,10 @@ protected function getSchemaGrammar() } /** - * Raise a note event for the migrator. + * Raise a note event for the migrator. * - * @param string $message The message - * @return void + * @param string $message The message + * @return void */ protected function note($message) { @@ -507,9 +561,9 @@ protected function note($message) } /** - * Get the notes for the last operation. + * Get the notes for the last operation. * - * @return array An array of notes + * @return array An array of notes */ public function getNotes() { diff --git a/app/sprinkles/core/src/Database/Seeder/BaseSeed.php b/app/sprinkles/core/src/Database/Seeder/BaseSeed.php new file mode 100644 index 000000000..2fd5c6f42 --- /dev/null +++ b/app/sprinkles/core/src/Database/Seeder/BaseSeed.php @@ -0,0 +1,42 @@ +ci = $ci; + } + + /** + * Function used to execute the seed + * + * @return void + */ + abstract public function run(); +} diff --git a/app/sprinkles/core/src/Database/Seeder/SeederInterface.php b/app/sprinkles/core/src/Database/Seeder/SeedInterface.php similarity index 93% rename from app/sprinkles/core/src/Database/Seeder/SeederInterface.php rename to app/sprinkles/core/src/Database/Seeder/SeedInterface.php index bbcc13bc7..1f8710b8c 100644 --- a/app/sprinkles/core/src/Database/Seeder/SeederInterface.php +++ b/app/sprinkles/core/src/Database/Seeder/SeedInterface.php @@ -12,7 +12,7 @@ * * @author Louis Charette */ -interface SeederInterface +interface SeedInterface { public function run(); } diff --git a/app/sprinkles/core/src/Database/Seeder/Seeder.php b/app/sprinkles/core/src/Database/Seeder/Seeder.php index 75ad9b24e..f3f335c05 100644 --- a/app/sprinkles/core/src/Database/Seeder/Seeder.php +++ b/app/sprinkles/core/src/Database/Seeder/Seeder.php @@ -8,23 +8,30 @@ namespace UserFrosting\Sprinkle\Core\Database\Seeder; use Interop\Container\ContainerInterface; -use UserFrosting\Sprinkle\Core\Database\Seeder\SeederInterface; +use Illuminate\Support\Str; +use UserFrosting\UniformResourceLocator\Resource; /** * Seeder Class - * Base class for seeds + * + * Finds all seeds class across sprinkles * * @author Louis Charette */ -abstract class Seeder implements SeederInterface +class Seeder { /** - * @var ContainerInterface $ci + * @var ContainerInterface $ci */ protected $ci; /** - * Constructor + * @var string $scheme The resource locator scheme + */ + protected $scheme = 'seeds://'; + + /** + * Class Constructor * * @param ContainerInterface $ci */ @@ -34,9 +41,113 @@ public function __construct(ContainerInterface $ci) } /** - * Function used to execute the seed + * Loop all the available sprinkles and return a list of their seeds + * + * @return array An array of all the seed classes found for every sprinkle + */ + public function getSeeds() + { + return $this->loadSeeders($this->ci->locator->listResources($this->scheme)); + } + + /** + * Get a single seed info + * + * @param string $name The seed name + * @return array The details about a seed file [name, class, sprinkle] + * @throws \Exception If seed not found + */ + public function getSeed($name) + { + // Get seed resource + $seedResource = $this->ci->locator->getResource($this->scheme . $name . ".php"); + + // Make sure we found something + if (!$seedResource) { + throw new \Exception("Seed $name not found"); + } + + // Return the seed info + return $this->getSeedDetails($seedResource); + } + + /** + * Return the class instance of a seed + * + * @param string $name The seed name + * @return SeedInterface The seed class instance + * @throws \Exception If class doesn't exist or is not right interface + */ + public function getSeedClass($name) + { + // Try to get seed info + $seed = $this->getSeed($name); + + // Make sure class exist + $classPath = $seed['class']; + if (!class_exists($classPath)) { + throw new \Exception("Seed class `$classPath` not found. Make sure the class has the correct namespace."); + } + + // Create a new class instance + $seedClass = new $classPath($this->ci); + + // Class must be an instance of `SeederInterface` + if (!$seedClass instanceof SeedInterface) { + throw new \Exception('Seed class must be an instance of `SeederInterface`'); + } + + return $seedClass; + } + + /** + * Execute a seed class + * + * @param SeedInterface $seed The seed to execute + * @return void + */ + public function executeSeed(SeedInterface $seed) + { + $seed->run(); + } + + /** + * Process seeder Resource into info * - * @return void + * @param array $seedFiles List of seeds file + * @return array */ - abstract public function run(); + protected function loadSeeders($seedFiles) + { + $seeds = []; + foreach ($seedFiles as $seedFile) { + $seeds[] = $this->getSeedDetails($seedFile); + } + return $seeds; + } + + /** + * Return an array of seed details inclusing the classname and the sprinkle name + * + * @param Resource $file The seed file + * @return array The details about a seed file [name, class, sprinkle] + */ + protected function getSeedDetails(Resource $file) + { + // Format the sprinkle name for the namespace + $sprinkleName = $file->getLocation()->getName(); + $sprinkleName = Str::studly($sprinkleName); + + // Getting base path, name and classname + $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); + $name = $basePath . $file->getFilename(); + $className = str_replace('/', '\\', $basePath) . $file->getFilename(); + + // Build the class name and namespace + return [ + 'name' => $name, + 'class' => "\\UserFrosting\\Sprinkle\\$sprinkleName\\Database\\Seeds\\$className", + 'sprinkle' => $sprinkleName + ]; + } } diff --git a/app/sprinkles/core/src/Database/Seeder/SeederLocator.php b/app/sprinkles/core/src/Database/Seeder/SeederLocator.php deleted file mode 100644 index 8127e946f..000000000 --- a/app/sprinkles/core/src/Database/Seeder/SeederLocator.php +++ /dev/null @@ -1,134 +0,0 @@ -sprinkleManager = $sprinkleManager; - $this->files = $files; - } - - /** - * Returm a list of all available seeds for a specific sprinkle - * - * @param string $sprinkleName The sprinkle name - * @return array The list of available seed classes - */ - public function getSeedersForSprinkle($sprinkleName) - { - $seeds = new Collection; - - // Get the sprinkle seed path and get all files in that path recursively - $path = $this->seederDirectoryPath($sprinkleName); - - // If directory diesn't exist, stop - if (!$this->files->exists($path)) { - return $seeds; - } - - // Get files - $files = $this->files->allFiles($path); - - // Transform the path into the mgiration full class name - $seeds = collect($files)->transform(function ($file) use ($sprinkleName, $path) { - return $this->getSeedDetails($file, $path, $sprinkleName); - }); - - // Return as array - return $seeds; - } - - /** - * Loop all the available sprinkles and return a list of their seeds - * - * @return Collection A collection of all the seed classes found for every sprinkle - */ - public function getSeeders() - { - $seeds = new Collection; - foreach ($this->sprinkleManager->getSprinkleNames() as $sprinkle) { - $sprinkleSeeds = $this->getSeedersForSprinkle($sprinkle); - $seeds = $seeds->merge($sprinkleSeeds); - } - - return $seeds; - } - - /** - * Returns the path of the seed directory for a sprinkle. - * - * @param string $sprinkleName - * @return string The sprinkle seed dir path - */ - protected function seederDirectoryPath($sprinkleName) - { - return \UserFrosting\SPRINKLES_DIR . - \UserFrosting\DS . - $sprinkleName . - \UserFrosting\DS . - \UserFrosting\SRC_DIR_NAME . - "/Database/Seeds"; - } - - /** - * Get the full classname of a seed based on the absolute file path, - * the initial search path and the SprinkleName - * - * @param string $file The seed file absolute path - * @param string $path The initial search path - * @param string $sprinkleName The sprinkle name - * @return array The details about a seed file [name, class, sprinkle] - */ - protected function getSeedDetails($file, $path, $sprinkleName) - { - // Format the sprinkle name for the namespace - $sprinkleName = Str::studly($sprinkleName); - - // Extract the class name from the path and file - $relativePath = str_replace($path, '', $file); - $className = str_replace('.php', '', $relativePath); - $className = str_replace('/', '', $className); - - // Build the class name and namespace - return [ - 'name' => $className, - 'class' => "\\UserFrosting\\Sprinkle\\".$sprinkleName."\\Database\\Seeds\\" . $className, - 'sprinkle' => $sprinkleName - ]; - } -} diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 54e18ff10..05ad083f3 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -35,7 +35,6 @@ use UserFrosting\Config\ConfigPathBuilder; use UserFrosting\I18n\LocalePathBuilder; use UserFrosting\Assets\Assets; -use UserFrosting\Assets\PathTransformer\PrefixTransformer; use UserFrosting\Assets\AssetBundles\GulpBundleAssetsCompiledBundles as CompiledAssetBundles; use UserFrosting\Sprinkle\Core\Util\RawAssetBundles; use UserFrosting\I18n\MessageTranslator; @@ -104,27 +103,9 @@ public function register(ContainerInterface $container) $config = $c->config; $locator = $c->locator; - // Hacky way to clean up locator paths. - $locatorPaths = []; - foreach ($locator->getPaths('assets') as $pathSet) { - foreach ($pathSet as $path) { - $locatorPaths[] = $path; - } - } - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; - $sprinkles = $c->sprinkleManager->getSprinkleNames(); - - $prefixTransformer = new PrefixTransformer(); - $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); - $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); - - foreach ($sprinkles as $sprinkle) { - $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); - } - - $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); + $assets = new Assets($locator, 'assets', $baseUrl); return new AssetLoader($assets); }; @@ -139,28 +120,11 @@ public function register(ContainerInterface $container) $config = $c->config; $locator = $c->locator; - // Hacky way to clean up locator paths. - $locatorPaths = []; - foreach ($locator->getPaths('assets') as $pathSet) { - foreach ($pathSet as $path) { - $locatorPaths[] = $path; - } - } - // Load asset schema if ($config['assets.use_raw']) { $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; - $sprinkles = $c->sprinkleManager->getSprinkleNames(); - - $prefixTransformer = new PrefixTransformer(); - $prefixTransformer->define(\UserFrosting\BOWER_ASSET_DIR, 'vendor-bower'); - $prefixTransformer->define(\UserFrosting\NPM_ASSET_DIR, 'vendor-npm'); - - foreach ($sprinkles as $sprinkle) { - $prefixTransformer->define(\UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle); - } - $assets = new Assets($locator, 'assets', $baseUrl, $prefixTransformer); + $assets = new Assets($locator, 'assets', $baseUrl); // Load raw asset bundles for each Sprinkle. @@ -281,8 +245,8 @@ public function register(ContainerInterface $container) // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) if (!$config['assets.use_raw']) { - $c->locator->resetScheme('assets'); - $c->locator->addPath('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME); + $c->locator->removeStream('assets'); + $c->locator->registerStream('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); } return $config; @@ -429,7 +393,7 @@ public function register(ContainerInterface $container) $container['factory'] = function ($c) { // Get the path of all of the sprinkle's factories - $factoriesPath = $c->locator->findResources('factories://', true, true); + $factoriesPath = $c->locator->findResources('factories://', true); // Create a new Factory Muffin instance $fm = new FactoryMuffin(); @@ -542,7 +506,7 @@ public function register(ContainerInterface $container) $migrator = new Migrator( $c->db, new DatabaseMigrationRepository($c->db, $c->config['migrations.repository_table']), - new MigrationLocator($c->sprinkleManager, new Filesystem) + new MigrationLocator($c->locator) ); // Make sure repository exist diff --git a/app/sprinkles/core/src/Util/ClassFinder.php b/app/sprinkles/core/src/Util/ClassFinder.php deleted file mode 100644 index c3d81f985..000000000 --- a/app/sprinkles/core/src/Util/ClassFinder.php +++ /dev/null @@ -1,78 +0,0 @@ -sprinkleManager = $sprinkleManager; - } - - /** - * Finds a class across sprinkles. Will return the first instance found - * while respecting the sprinkle load order. Search is done after the `src/` - * dir. So to find `UserFrosting\Sprinkle\Core\Database\Models\Users`, - * search for `\Database\Models\Users` - * - * @param string $className The class name to find, including path inside `src/` - * @return string The fully qualified classname - * @throws \Exception If class not found - */ - public function getClass($className) - { - $sprinkles = $this->getSprinkles(); - foreach ($sprinkles as $sprinkle) { - - // Format the sprinkle name for the namespace - $sprinkle = Str::studly($sprinkle); - - // Build the class name and namespace - $class = "\\UserFrosting\\Sprinkle\\$sprinkle\\$className"; - - // Check if class exist. - if (class_exists($class)) { - return $class; - } - } - - //No class if found. Throw Exception - $sprinklesString = implode(", ", $sprinkles); - throw new \Exception("Class $className not found in sprinkles [$sprinklesString]"); - } - - /** - * Return an array of sprinkles respecting the load order - * - * @return array - */ - protected function getSprinkles() - { - $sprinkles = $this->sprinkleManager->getSprinkleNames(); - return array_reverse($sprinkles); - } -} diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php index d391fef22..56e6b752d 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php @@ -56,7 +56,7 @@ public function setUp() // Get the repository and locator instances $this->repository = new DatabaseMigrationRepository($this->ci->db, $this->migrationTable); - $this->locator = new MigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $this->locator = new MigrationLocatorStub($this->ci->locator); // Get the migrator instance and setup right connection $this->migrator = new Migrator($this->ci->db, $this->repository, $this->locator); @@ -172,7 +172,7 @@ public function testPretendRollback() public function testChangeRepositoryAndDeprecatedClass() { // Change the repository so we can test with the DeprecatedMigrationLocatorStub - $locator = new DeprecatedMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $locator = new DeprecatedMigrationLocatorStub($this->ci->locator); $this->migrator->setLocator($locator); // Run up. Should also run the seeder @@ -191,7 +191,7 @@ public function testChangeRepositoryAndDeprecatedClass() public function testWithInvalidClass() { // Change the repository so we can test with the InvalidMigrationLocatorStub - $locator = new InvalidMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $locator = new InvalidMigrationLocatorStub($this->ci->locator); $this->migrator->setLocator($locator); // Expect a `BadClassNameException` exception @@ -204,7 +204,7 @@ public function testWithInvalidClass() public function testDependableMigrations() { // Change the repository so we can test with the DependableMigrationLocatorStub - $locator = new DependableMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $locator = new DependableMigrationLocatorStub($this->ci->locator); $this->migrator->setLocator($locator); // Run up @@ -228,7 +228,7 @@ public function testDependableMigrationsWithInstalled() $this->assertTrue($this->schema->hasTable('password_resets')); // Change the repository so we can run up the `two` migrations - $locator = new FlightsTableMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $locator = new FlightsTableMigrationLocatorStub($this->ci->locator); $this->migrator->setLocator($locator); // Run up again @@ -244,13 +244,60 @@ public function testDependableMigrationsWithInstalled() public function testUnfulfillableMigrations() { // Change the repository so we can test with the DeprecatedStub - $locator = new UnfulfillableMigrationLocatorStub($this->ci->sprinkleManager, new Filesystem); + $locator = new UnfulfillableMigrationLocatorStub($this->ci->locator); $this->migrator->setLocator($locator); // Should have an exception for unfulfilled migrations $this->expectException(\Exception::class); $migrated = $this->migrator->run(); } + + public function testSpecificMigrationCanBeRollback() + { + // Change the repository so we can test with the DependableMigrationLocatorStub + $locator = new DependableMigrationLocatorStub($this->ci->locator); + $this->migrator->setLocator($locator); + + // Run up + $migrated = $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + $this->assertTrue($this->schema->hasTable('flights')); + + // Rollback only the Flights table. Should work as no other depends on it + $migration = '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable'; + $rolledBack = $this->migrator->rollbackMigration($migration); + $this->assertCount(1, $rolledBack); + $this->assertEquals([$migration], $rolledBack); + + // Look at actual db for tables. Flight should be gone, but other still there + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + $this->assertFalse($this->schema->hasTable('flights')); + } + + public function testSpecificMigrationRollbackWithDependencies() + { + // Change the repository so we can test with the DependableMigrationLocatorStub + $locator = new DependableMigrationLocatorStub($this->ci->locator); + $this->migrator->setLocator($locator); + + // Run up + $migrated = $this->migrator->run(); + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + $this->assertTrue($this->schema->hasTable('flights')); + + // Rollback only the user table. Should fail as the flight table depends on it + $migration = '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable'; + $this->expectException(\Exception::class); + $rolledBack = $this->migrator->rollbackMigration($migration); + + // Look at actual db for tables. Should be no changes + $this->assertTrue($this->schema->hasTable('users')); + $this->assertTrue($this->schema->hasTable('password_resets')); + $this->assertTrue($this->schema->hasTable('flights')); + } } class MigrationLocatorStub extends MigrationLocator { diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php index 5345bb105..919ae0de3 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php @@ -236,6 +236,7 @@ public function testMigratorRollbackAllInstalledMigrations() // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations $this->repository->shouldReceive('getLast')->once()->andReturn($testMigrations); + $this->repository->shouldReceive('getMigrationsList')->once()->andReturn($testMigrations); $this->repository->shouldReceive('delete')->times(3)->andReturn([]); // SchemaBuilder will only create 2 tables @@ -258,19 +259,22 @@ public function testMigratorRollbackAllInstalledMigrations() */ public function testMigratorRollbackAllInstalledMigrationsWithOneMissing() { - // When running up, Locator will return all 3 migration classes + // Locator will only return one of the two installed migrations $this->locator->shouldReceive('getMigrations')->once()->andReturn([ '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' ]); - // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations - $this->repository->shouldReceive('getLast')->once()->andReturn([ + // Repository will be asked to return the ran migrations (two of them) + // and will only be asked to delete one + $installed = [ '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' - ]); + ]; + $this->repository->shouldReceive('getLast')->once()->andReturn($installed); + $this->repository->shouldReceive('getMigrationsList')->once()->andReturn($installed); $this->repository->shouldReceive('delete')->times(1)->andReturn([]); - // SchemaBuilder will only create 2 tables + // SchemaBuilder will only drop one of the 2 tables $this->schema->shouldReceive('dropIfExists')->times(1)->andReturn([]); // Connection will be asked for the SchemaGrammar @@ -278,15 +282,95 @@ public function testMigratorRollbackAllInstalledMigrationsWithOneMissing() $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); - // Run migrations up + // Rollback migrations $migrations = $this->migrator->rollback(); - // The migration already ran shoudn't be in the pending ones + // The migration not available from the locator shouldn't have been run dowm $this->assertEquals([ '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable' ], $migrations); } + /** + * Test a specific migration with no dependencies can be rollbacked + */ + public function testMigratorRollbackSpecific() + { + // The installed / available migrations + $testMigrations = [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ]; + + // Migration object for the one being deleted + $migration = '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable'; + $migrationObject = (object) [ + 'migration' => $migration + ]; + + // Locator will return all 3 migration classes as available + $this->locator->shouldReceive('getMigrations')->once()->andReturn($testMigrations); + + // Repository will be asked to return the ran migrations and delete one + $this->repository->shouldReceive('getMigration')->once()->andReturn($migrationObject); + $this->repository->shouldReceive('getMigrationsList')->once()->andReturn($testMigrations); + $this->repository->shouldReceive('delete')->times(1)->andReturn([]); + + // SchemaBuilder will delete 1 table + $this->schema->shouldReceive('dropIfExists')->times(1)->andReturn([]); + + // Connection will be asked for the SchemaGrammar + $grammar = m::mock(Grammar::class); + $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); + $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); + + // Rollback only the Flights table. Should work as no other depends on it + $rolledback = $this->migrator->rollbackMigration($migration); + + // The migration already ran shoudn't be in the pending ones + $this->assertEquals([$migration], $rolledback); + } + + /** + * Test a specific migration with some dependencies can be rollbacked + */ + public function testMigratorRollbackSpecificWithDependencies() + { + // The installed / available migrations + $testMigrations = [ + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' + ]; + + // Migration object for the one being deleted + $migration = '\\UserFrosting\\Tests\\Integration\\Migrations\\one\\CreateUsersTable'; + $migrationObject = (object) [ + 'migration' => $migration + ]; + + // Locator will return all 3 migration classes as available + $this->locator->shouldReceive('getMigrations')->once()->andReturn($testMigrations); + + // Repository will be asked to return the ran migrations and delete one + $this->repository->shouldReceive('getMigration')->once()->andReturn($migrationObject); + $this->repository->shouldReceive('getMigrationsList')->once()->andReturn($testMigrations); + $this->repository->shouldNotReceive('delete'); + + // SchemaBuilder will delete 1 table + $this->schema->shouldNotReceive('dropIfExists'); + + // Connection will be asked for the SchemaGrammar + $grammar = m::mock(Grammar::class); + $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); + $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); + + // Rollback only the user table. Should fail as the flight table depends on it + $this->expectException(\Exception::class); + $rolledback = $this->migrator->rollbackMigration($migration); + } + /** * Test where one of the installed migration is not in the available migration classes */ @@ -299,14 +383,15 @@ public function testMigratorResetAllInstalledMigrations() '\\UserFrosting\\Tests\\Integration\\Migrations\\two\\CreateFlightsTable' ]; - // When running up, Locator will return all 3 migration classes + // Locator will return all 3 migration classes $this->locator->shouldReceive('getMigrations')->once()->andReturn($testMigrations); - // Repository will be asked to return the ran migrations (one), the next batch number and will log 2 new migrations - $this->repository->shouldReceive('getMigrationsList')->once()->andReturn($testMigrations); + // Repository will be asked to return the ran migrations (all of them), + // then asked to delete all 3 of them + $this->repository->shouldReceive('getMigrationsList')->twice()->andReturn($testMigrations); $this->repository->shouldReceive('delete')->times(3)->andReturn([]); - // SchemaBuilder will only create 2 tables + // SchemaBuilder will drop all 3 tables $this->schema->shouldReceive('dropIfExists')->times(3)->andReturn([]); // Connection will be asked for the SchemaGrammar @@ -314,10 +399,10 @@ public function testMigratorResetAllInstalledMigrations() $this->connection->shouldReceive('getSchemaGrammar')->andReturn($grammar); $grammar->shouldReceive('supportsSchemaTransactions')->andReturn(false); - // Run migrations up + // Reset mgirations $migrations = $this->migrator->reset(); - // The migration already ran shoudn't be in the pending ones + // All the migrations should have been rolledback $this->assertEquals(array_reverse($testMigrations), $migrations); } } diff --git a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php index fc61ee729..21f6d07f8 100644 --- a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php @@ -7,11 +7,13 @@ */ namespace UserFrosting\Tests\Integration; -use \SplFileInfo; use Mockery as m; use UserFrosting\Tests\TestCase; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocator; -use Illuminate\Filesystem\Filesystem; +use UserFrosting\UniformResourceLocator\Resource; +use UserFrosting\UniformResourceLocator\ResourceLocator; +use UserFrosting\UniformResourceLocator\ResourceLocation; +use UserFrosting\UniformResourceLocator\ResourceStream; class MigrationLocatorTest extends TestCase { @@ -21,123 +23,88 @@ public function tearDown() } /** - * Make sure migrations can be returned for all sprinkles + * Make sure no error is thrown if the Migration dir doesn't exist */ - public function testGetMigrations() + public function testGetMigrationsWithNoMigrationDir() { - // Simulate the SprinkleManager - $sprinkleManager = m::mock('UserFrosting\System\Sprinkle\SprinkleManager'); - - // The locator will ask sprinkleManager for `getSprinkleNames`. When it does, we'll return this fake data - $sprinkleManager->shouldReceive('getSprinkleNames')->once()->andReturn([ - 'core', - 'Account' - ]); - - // Simulate the Filesystem. - $filesystem = m::mock('Illuminate\Filesystem\Filesystem'); - - // When `MigrationLocator` will ask the filesystem for `glob` and `core` sprinkle, - // filesystem will return fake test path. - $filesystem->shouldReceive('exists')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->andReturn(true); - $filesystem->shouldReceive('allFiles')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->once()->andReturn([ - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/one/CreateUsersTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/one/CreatePasswordResetsTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/two/CreateFlightsTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/CreateMainTable.php') - ]); - - // When `MigrationLocator` will also ask the filesystem the same thing, but for the `account` sprinkle - $filesystem->shouldReceive('exists')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/Account/src/Database/Migrations")->andReturn(true); - $filesystem->shouldReceive('allFiles')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/Account/src/Database/Migrations")->once()->andReturn([ - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/Account/src/Database/Migrations/one/CreateUsersTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/Account/src/Database/Migrations/one/CreatePasswordResetsTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/Account/src/Database/Migrations/two/CreateFlightsTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/Account/src/Database/Migrations/CreateMainTable.php') - ]); - - // Create a new MigrationLocator instance with our simulated SprinkleManager and filesystem - // and ask to find core sprinkle migration files - $locator = new MigrationLocator($sprinkleManager, $filesystem); + // Setup mock locator + $resourceLocator = m::mock(ResourceLocator::class); + + // Setup mock stream + $resourceStream = m::mock(ResourceStream::class); + $resourceStream->shouldReceive('getPath')->andReturn('src/Database/Migrations'); + + // Setup mock locations + $resourceCoreLocation = m::mock(ResourceLocation::class); + $resourceCoreLocation->shouldReceive('getName')->andReturn('Core'); + $resourceCoreLocation->shouldReceive('getPath')->andReturn('app/sprinkles/Core'); + $resourceAccountLocation = m::mock(ResourceLocation::class); + $resourceAccountLocation->shouldReceive('getName')->andReturn('account'); + $resourceAccountLocation->shouldReceive('getPath')->andReturn('app/sprinkles/Account'); + + // When `MigrationLocator` will ask the resource locator to `listResources`, we simulate returning no Resources + $resourceLocator->shouldReceive('listResources')->once()->andReturn([]); + $locator = new MigrationLocator($resourceLocator); $results = $locator->getMigrations(); - // The `getMigrationForSprinkle` method should return this - $expected = [ - "\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\one\\CreateUsersTable", - "\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\one\\CreatePasswordResetsTable", - "\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\two\\CreateFlightsTable", - "\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\CreateMainTable", - "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreateUsersTable", - "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreatePasswordResetsTable", - "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\two\\CreateFlightsTable", - "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\CreateMainTable" - ]; - // Test results match expectations - $this->assertEquals($expected, $results); + $this->assertCount(0, $results); + $this->assertEquals([], $results); } /** - * Make sure migrations can be returned for a specific sprinkle + * Make sure migrations can be returned for all sprinkles */ - public function testGetMigrationsForSprinkle() + public function testGetMigrations() { - // Simulate the SprinkleManager - $sprinkleManager = m::mock('UserFrosting\System\Sprinkle\SprinkleManager'); - - // Simulate the Filesystem. - $filesystem = m::mock('Illuminate\Filesystem\Filesystem'); - - // When `MigrationLocator` will ask the filesystem for `glob`, which it should do only once, - // filesystem will return fake test path. - $filesystem->shouldReceive('exists')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->andReturn(true); - $filesystem->shouldReceive('allFiles')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->once()->andReturn([ - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/one/CreateUsersTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/one/CreatePasswordResetsTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/two/CreateFlightsTable.php'), - new SplFileInfo(\UserFrosting\ROOT_DIR . '/app/sprinkles/core/src/Database/Migrations/CreateMainTable.php') + // Setup mock locator + $resourceLocator = m::mock(ResourceLocator::class); + + // Setup mock stream + $resourceStream = m::mock(ResourceStream::class); + $resourceStream->shouldReceive('getPath')->andReturn('src/Database/Migrations'); + + // Setup mock locations + $resourceCoreLocation = m::mock(ResourceLocation::class); + $resourceCoreLocation->shouldReceive('getName')->andReturn('Core'); + $resourceCoreLocation->shouldReceive('getPath')->andReturn('app/sprinkles/Core'); + $resourceAccountLocation = m::mock(ResourceLocation::class); + $resourceAccountLocation->shouldReceive('getName')->andReturn('account'); + $resourceAccountLocation->shouldReceive('getPath')->andReturn('app/sprinkles/Account'); + + // When `MigrationLocator` will ask the resource locator to `listResources`, we simulate returning Resources + $resourceLocator->shouldReceive('listResources')->once()->andReturn([ + new Resource($resourceStream, $resourceCoreLocation, '', 'one/CreateUsersTable.php'), + new Resource($resourceStream, $resourceCoreLocation, '', 'one/CreatePasswordResetsTable.php'), + new Resource($resourceStream, $resourceCoreLocation, '', 'two/CreateFlightsTable.php'), + new Resource($resourceStream, $resourceCoreLocation, '', 'CreateMainTable.php'), + new Resource($resourceStream, $resourceAccountLocation, '', 'one/CreateUsersTable.php'), + new Resource($resourceStream, $resourceAccountLocation, '', 'one/CreatePasswordResetsTable.php'), + new Resource($resourceStream, $resourceAccountLocation, '', 'two/CreateFlightsTable.php'), + new Resource($resourceStream, $resourceAccountLocation, '', 'CreateMainTable.php') ]); - // Create a new MigrationLocator instance with our simulated SprinkleManager and filesystem - // and ask to find core sprinkle migration files - $locator = new MigrationLocator($sprinkleManager, $filesystem); - $results = $locator->getMigrationsForSprinkle('core'); + // Create a new MigrationLocator instance with our simulated ResourceLocation + $locator = new MigrationLocator($resourceLocator); + $results = $locator->getMigrations(); - // The `getMigrationForSprinkle` method should return this + // The `getMigration` method should return this $expected = [ - "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreateUsersTable", - "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreatePasswordResetsTable", - "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\two\\CreateFlightsTable", - "\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\CreateMainTable" + '\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\two\\CreateFlightsTable', + '\\UserFrosting\\Sprinkle\\Core\\Database\\Migrations\\CreateMainTable', + '\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\one\\CreateUsersTable', + '\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\one\\CreatePasswordResetsTable', + '\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\two\\CreateFlightsTable', + '\\UserFrosting\\Sprinkle\\Account\\Database\\Migrations\\CreateMainTable' ]; // Test results match expectations + $this->assertCount(8, $results); $this->assertEquals($expected, $results); - } - - /** - * Make sure no error is thrown if the Migration dir doesn't exist - */ - public function testGetMigrationsForSprinkleWithNoMigrationDir() - { - // Simulate the SprinkleManager - $sprinkleManager = m::mock('UserFrosting\System\Sprinkle\SprinkleManager'); - - // Simulate the Filesystem. - $filesystem = m::mock('Illuminate\Filesystem\Filesystem'); - // When `MigrationLocator` will ask the filesystem for `glob`, which it should do only once, - // filesystem will return fake test path. - $filesystem->shouldReceive('exists')->with(\UserFrosting\ROOT_DIR . "/app/sprinkles/core/src/Database/Migrations")->andReturn(false); - $filesystem->shouldNotReceive('allFiles'); - - // Create a new MigrationLocator instance with our simulated SprinkleManager and filesystem - // and ask to find core sprinkle migration files - $locator = new MigrationLocator($sprinkleManager, $filesystem); - $results = $locator->getMigrationsForSprinkle('core'); - - // Test results match expectations - $this->assertEquals([], $results); + return $locator; } /** @@ -146,15 +113,16 @@ public function testGetMigrationsForSprinkleWithNoMigrationDir() function testActualInstance() { // Get sprinkle manager and make sure `core` is returned - $sprinkleManager = $this->ci->sprinkleManager; - $this->assertContains('core', $sprinkleManager->getSprinkleNames()); + $this->assertContains('core', $this->ci->sprinkleManager->getSprinkleNames()); // Create a new MigrationLocator instance with our real SprinkleManager and filesystem // and ask to find core sprinkle migration files - $locator = new MigrationLocator($sprinkleManager, new Filesystem); - $results = $locator->getMigrationsForSprinkle('core'); + $locator = new MigrationLocator($this->ci->locator); + $results = $locator->getMigrations(); - // Test results match expectations + // We'll need to convert the array returned by `getMigrations` to a + // collection to make it easier to search + $this->assertInternalType('array', $results); $this->assertContains('\UserFrosting\Sprinkle\Core\Database\Migrations\v400\SessionsTable', $results); } } diff --git a/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php b/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php new file mode 100644 index 000000000..5ffd86c97 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php @@ -0,0 +1,172 @@ +fakeCi = new Container; + + // Register services stub + $serviceProvider = new ServicesProviderStub(); + $serviceProvider->register($this->fakeCi); + } + + public function tearDown() + { + m::close(); + } + + /** + * @return Seeder + */ + public function testSeeder() + { + $seeder = new Seeder($this->fakeCi); + $this->assertInstanceOf(Seeder::class, $seeder); + return $seeder; + } + + /** + * @param Seeder $seeder + * @depends testSeeder + */ + public function testgetSeeds(Seeder $seeder) + { + $seeds = $seeder->getSeeds(); + $this->assertInternalType('array', $seeds); + $this->assertCount(3, $seeds); + $this->assertEquals([ + [ + 'name' => 'Seed1', + 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed1', + 'sprinkle' => 'Core' + ], + [ + 'name' => 'Seed2', + 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed2', + 'sprinkle' => 'Core' + ], + [ + 'name' => 'Test/Seed', + 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Test\\Seed', + 'sprinkle' => 'Core' + ] + ], $seeds); + } + + /** + * @param Seeder $seeder + * @depends testSeeder + */ + public function testGetSeed(Seeder $seeder) + { + $seed = $seeder->getSeed('Seed1'); + $this->assertInternalType('array', $seed); + $this->assertEquals([ + 'name' => 'Seed1', + 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed1', + 'sprinkle' => 'Core' + ], $seed); + } + + /** + * @param Seeder $seeder + * @depends testSeeder + * @expectedException \Exception + */ + public function testUnfoundGetSeed(Seeder $seeder) + { + $seed = $seeder->getSeed('FakeSeed'); + } + + /** + * @param Seeder $seeder + * @depends testSeeder + */ + public function testGetSeedClass(Seeder $seeder) + { + $seed = $seeder->getSeedClass('Seed1'); + $this->assertInstanceOf(SeedInterface::class, $seed); + } + + /** + * @param Seeder $seeder + * @depends testSeeder + * @expectedException \Exception + */ + public function testGetSeedClassNotSeedInterface(Seeder $seeder) + { + // This class is not an instance of SeedInterface + $seeder->getSeedClass('Seed2'); + } + + /** + * @param Seeder $seeder + * @depends testSeeder + * @expectedException \Exception + */ + public function testGetSeedClassException(Seeder $seeder) + { + // The namespace in this class is wrong + $seeder->getSeedClass('Test/Seed'); + } + + /** + * @param Seeder $seeder + * @depends testSeeder + */ + public function testExecuteSeed(Seeder $seeder) + { + // Get a fake seed + $seed = m::mock('\UserFrosting\Sprinkle\Core\Database\Seeder\BaseSeed'); + $seed->shouldReceive('run'); + + $seeder->executeSeed($seed); + } +} + +/** + * ServicesProviderStub + */ +class ServicesProviderStub +{ + /** + * @param ContainerInterface $container A DI container implementing ArrayAccess and container-interop. + */ + public function register(ContainerInterface $container) + { + /** + * @return \UserFrosting\UniformResourceLocator\ResourceLocator + */ + $container['locator'] = function ($c) { + $locator = new ResourceLocator(\UserFrosting\SPRINKLES_DIR); + $locator->registerStream('seeds', '', 'Seeder/Seeds/'); + $locator->registerLocation('Core', 'core/tests/Integration/'); + return $locator; + }; + } +} diff --git a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php new file mode 100644 index 000000000..f589c9447 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php @@ -0,0 +1,18 @@ +getBakeryCommands(); + /** + * @var ResourceLocator $locator + */ + $locator = $this->ci->locator; - // Get the sprinkles commands - $sprinkles = $this->ci->sprinkleManager->getSprinkleNames(); - foreach ($sprinkles as $sprinkle) { - $commands = $commands->merge($this->getSprinkleCommands($sprinkle)); - } + // Get Bakery command resources + $commandResources = $locator->listResources($this->scheme); // Add commands to the App - $commands->each(function($command) { + foreach ($commandResources as $commandResource) { + + // Translate the resource to a class + $command = $this->getResourceClass($commandResource); + + // Get command instance $instance = new $command(); + + // Class must be an instance of symfony command + if (!$instance instanceof Command) { + throw new \Exception("Bakery command class must be an instance of `" . Command::class . "`"); + } + + // Add command to the Console app $instance->setContainer($this->ci); $this->app->add($instance); - }); + }; } /** - * Return the list of available commands for a specific sprinkle - * Sprinkles commands should be located in `src/Bakery/` + * Transform a Bakery Command Resource into a classpath * - * @param string $sprinkle The sprinkle name - * @return \Illuminate\Support\Collection A collection of commands + * @param Resource $file The command resource + * @return string The command class path */ - protected function getSprinkleCommands($sprinkle) + protected function getResourceClass(Resource $file) { - // Find all the migration files - $path = $this->commandDirectoryPath($sprinkle); - $files = glob($path . "*.php"); - $commands = collect($files); - - // Transform the path into a class names - $commands->transform(function ($file) use ($sprinkle, $path) { - $className = basename($file, '.php'); - $sprinkleName = Str::studly($sprinkle); - $className = "\\UserFrosting\\Sprinkle\\".$sprinkleName."\\Bakery\\".$className; - return $className; - }); - - return $commands; - } + // Process sprinkle and system commands + if (!is_null($location = $file->getLocation())) { + + // Format the sprinkle name for the namespace + $sprinkleName = $file->getLocation()->getName(); + $sprinkleName = Str::studly($sprinkleName); + + // Getting the classpath + $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); + $className = str_replace('/', '\\', $basePath) . $file->getFilename(); + $classPath = "\\UserFrosting\\Sprinkle\\$sprinkleName\\Bakery\\$className"; + + } else { + // Getting the classpath + $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); + $className = str_replace('/', '\\', $basePath) . $file->getFilename(); + $classPath = "\\UserFrosting\\System\\Bakery\\Command\\$className"; + } - /** - * Return the list of available commands in system/Bakery/Command/ - * - * @return \Illuminate\Support\Collection A collection of commands - */ - protected function getBakeryCommands() - { - // Find all the migration files - $files = glob(\UserFrosting\APP_DIR . "/system/Bakery/Command/" . "*.php"); - $commands = collect($files); - - // Transform the path into a class names - $commands->transform(function ($file) { - $className = basename($file, '.php'); - $className = "\\UserFrosting\\System\\Bakery\\Command\\".$className; - return $className; - }); - - return $commands; - } + // Make sure class exist + if (!class_exists($classPath)) { + throw new \Exception("Bakery command found in `{$file->getAbsolutePath()}`, but class `$classPath` doesn't exist. Make sure the class has the correct namespace."); + } - /** - * Returns the path of the Bakery commands directory. - * - * @param string $sprinkleName The sprinkle name - * @return string The sprinkle bakery command directory path - */ - protected function commandDirectoryPath($sprinkleName) - { - return \UserFrosting\SPRINKLES_DIR . - \UserFrosting\DS . - $sprinkleName . - \UserFrosting\DS . - \UserFrosting\SRC_DIR_NAME . - "/Bakery/"; + return $classPath; } /** - * Write the base `sprinkles.json` file if none exist. + * Write the base `sprinkles.json` file if none exist. * - * @return string The sprinkle model file + * @return string The sprinkle model file */ protected function setupBaseSprinkleList() { diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 18ba423a9..2abd242d3 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -9,11 +9,8 @@ use Interop\Container\ContainerInterface; use RocketTheme\Toolbox\Event\EventDispatcher; -use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; -use RocketTheme\Toolbox\StreamWrapper\ReadOnlyStream; -use RocketTheme\Toolbox\StreamWrapper\Stream; -use RocketTheme\Toolbox\StreamWrapper\StreamBuilder; use UserFrosting\System\Sprinkle\SprinkleManager; +use UserFrosting\UniformResourceLocator\ResourceLocator; /** * UserFrosting system services provider. @@ -41,62 +38,36 @@ public function register(ContainerInterface $container) * Path/file locator service. * * Register custom streams for the application, and add paths for app-level streams. + * @return \UserFrosting\UniformResourceLocator\ResourceLocator */ $container['locator'] = function ($c) { - $locator = new UniformResourceLocator(\UserFrosting\ROOT_DIR); + $locator = new ResourceLocator(\UserFrosting\ROOT_DIR); - $locator->addPath('build', '', \UserFrosting\BUILD_DIR_NAME); - $locator->addPath('log', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\LOG_DIR_NAME); - $locator->addPath('cache', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\CACHE_DIR_NAME); - $locator->addPath('session', '', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\SESSION_DIR_NAME); - $locator->addPath('assets', 'vendor', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME . '/' . 'bower_components'); - $locator->addPath('assets', 'vendor', \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME . '/' . 'node_modules'); + // Register shared streams + $locator->registerStream('bakery', '', \UserFrosting\BAKERY_SYSTEM_DIR, true); + $locator->registerStream('build', '', \UserFrosting\BUILD_DIR_NAME, true); + $locator->registerStream('log', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\LOG_DIR_NAME, true); + $locator->registerStream('cache', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\CACHE_DIR_NAME, true); + $locator->registerStream('session', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); + $locator->registerStream('assets', 'vendor', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\BOWER_ASSET_DIR, true); + $locator->registerStream('assets', 'vendor', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\NPM_ASSET_DIR, true); - // Use locator to initialize streams - ReadOnlyStream::setLocator($locator); - Stream::setLocator($locator); - - // Fire up StreamBuilder - $c->streamBuilder; + // Register sprinkles streams + $locator->registerStream('assets', '', \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME); + $locator->registerStream('config', '', \UserFrosting\DS . \UserFrosting\CONFIG_DIR_NAME); + $locator->registerStream('extra', '', \UserFrosting\DS . \UserFrosting\EXTRA_DIR_NAME); + $locator->registerStream('factories', '', \UserFrosting\DS . \UserFrosting\FACTORY_DIR_NAME); + $locator->registerStream('locale', '', \UserFrosting\DS . \UserFrosting\LOCALE_DIR_NAME); + $locator->registerStream('routes', '', \UserFrosting\DS . \UserFrosting\ROUTE_DIR_NAME); + $locator->registerStream('schema', '', \UserFrosting\DS . \UserFrosting\SCHEMA_DIR_NAME); + $locator->registerStream('sprinkles', '', ''); + $locator->registerStream('templates', '', \UserFrosting\DS . \UserFrosting\TEMPLATE_DIR_NAME); + $locator->registerStream('bakery', '', \UserFrosting\BAKERY_DIR); return $locator; }; - /** - * StreamBuilder, to fire up our custom StreamWrapper defined in the locator service. - */ - $container['streamBuilder'] = function ($c) { - - $streams = [ - 'build' => '\\RocketTheme\\Toolbox\\StreamWrapper\\Stream', - 'log' => '\\RocketTheme\\Toolbox\\StreamWrapper\\Stream', - 'cache' => '\\RocketTheme\\Toolbox\\StreamWrapper\\Stream', - 'session' => '\\RocketTheme\\Toolbox\\StreamWrapper\\Stream', - 'sprinkles' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream', - 'assets' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream', - 'schema' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream', - 'templates' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream', - 'extra' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream', - 'locale' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream', - 'config' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream', - 'routes' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream', - 'factories' => '\\RocketTheme\\Toolbox\\StreamWrapper\\ReadOnlyStream' - ]; - - // Before registering them, we need to unregister any that where previously registered. - // This will cause error when two scripts are run in succession from the CLI - foreach ($streams as $scheme => $handler) { - if (in_array($scheme, stream_get_wrappers())) { - stream_wrapper_unregister($scheme); - } - } - - $sb = new StreamBuilder($streams); - - return $sb; - }; - /** * Set up sprinkle manager service. */ diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index c206cea94..41312f6e3 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -9,8 +9,6 @@ use Illuminate\Support\Str; use Interop\Container\ContainerInterface; -use RocketTheme\Toolbox\Event\EventDispatcher; -use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use UserFrosting\Support\Exception\FileNotFoundException; /** @@ -51,40 +49,6 @@ public function __construct(ContainerInterface $ci) { $this->ci = $ci; $this->sprinklesPath = \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS; - - $this->resourcePaths = [ - 'assets' => \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME, - 'config' => \UserFrosting\DS . \UserFrosting\CONFIG_DIR_NAME, - 'extra' => \UserFrosting\DS . \UserFrosting\EXTRA_DIR_NAME, - 'factories' => \UserFrosting\DS . \UserFrosting\FACTORY_DIR_NAME, - 'locale' => \UserFrosting\DS . \UserFrosting\LOCALE_DIR_NAME, - 'routes' => \UserFrosting\DS . \UserFrosting\ROUTE_DIR_NAME, - 'schema' => \UserFrosting\DS . \UserFrosting\SCHEMA_DIR_NAME, - 'sprinkles' => '', - 'templates' => \UserFrosting\DS . \UserFrosting\TEMPLATE_DIR_NAME - ]; - } - - /** - * Adds the relative path for a specified resource type in a Sprinkle to the resource's stream. - * - * @param string $resourceName - * @param string $sprinkleName - * @return string|bool The full path to specified resource for the specified Sprinkle (if found). - */ - public function addResource($resourceName, $sprinkleName) - { - $resourcePath = $this->resourcePaths[$resourceName]; - $fullPath = $this->sprinklesPath . $sprinkleName . $resourcePath; - - $this->ci->locator->addPath($resourceName, '', $fullPath); - - return $this->ci->locator->findResource("$resourceName://", true, false); - - /* This would allow a stream to subnavigate to a specific sprinkle (e.g. "templates://core/") - Not sure if we need this. - $locator->addPath('templates', '$name', $sprinklesDirFragment . '/' . \UserFrosting\TEMPLATE_DIR_NAME); - */ } /** @@ -92,17 +56,14 @@ public function addResource($resourceName, $sprinkleName) */ public function addResources() { + /** + * @var \UserFrosting\UniformResourceLocator\ResourceLocator $locator + */ + $locator = $this->ci->locator; + // For each sprinkle, register its resources and then run its initializer foreach ($this->sprinkles as $sprinkleName => $sprinkle) { - $this->addResource('config', $sprinkleName); - $this->addResource('assets', $sprinkleName); - $this->addResource('extra', $sprinkleName); - $this->addResource('factories', $sprinkleName); - $this->addResource('locale', $sprinkleName); - $this->addResource('routes', $sprinkleName); - $this->addResource('schema', $sprinkleName); - $this->addResource('sprinkles', $sprinkleName); - $this->addResource('templates', $sprinkleName); + $locator->registerLocation($sprinkleName, $this->sprinklesPath . $sprinkleName); } } @@ -111,7 +72,7 @@ public function addResources() * * Creates an object of a subclass of UserFrosting\System\Sprinkle\Sprinkle if defined for the sprinkle (converting to StudlyCase). * Otherwise, returns null. - * @param $name The name of the Sprinkle to initialize. + * @param string $name The name of the Sprinkle to initialize. */ public function bootSprinkle($name) { From 181538a6f758e9c4aa01defef61385b1f95602e2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 15 Aug 2018 22:05:27 -0400 Subject: [PATCH 076/237] Updated Homestead info and typo in Vagrant doc. --- vagrant/doc.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/vagrant/doc.md b/vagrant/doc.md index 1f5b30e6c..fb4f6ec75 100644 --- a/vagrant/doc.md +++ b/vagrant/doc.md @@ -2,7 +2,7 @@ UserFrosting includes support for Vagrant. This allows you to run UserFrosting without the need to set up your own local web server with traditional WAMP/MAMP stacks. It also provides a consistent environment between developers for writing and debugging code changes more productively. -UserFrosting uses the [Laravel/Homestead](https://laravel.com/docs/5.6/homestead) Vagrant box. It runs a Linux server with Ubuntu 14.04, PHP 5.6, Nginx, SQLite3, MySQL, and a whole lot more (complete specs below). +UserFrosting uses the [Laravel/Homestead](https://laravel.com/docs/5.6/homestead) Vagrant box. It runs a Linux server with Ubuntu 16.04, PHP 7.1, Nginx, SQLite3, MySQL, and a whole lot more (complete specs below). ## Get Started @@ -52,7 +52,7 @@ $ vagrant destroy > Note: destroying the vagrant server will remove all traces of the VM from your computer, reclaiming any disk space used by it. However, it also means the next time you vagrant up, you will be creating a brand new VM with a fresh install of UserFrosting and a new database. -## Customising the UserFrosting configuration +## Customizing the UserFrosting configuration By default, UserFrosting is pre-configured to install with a MySQL database. You can, however, switch to PostegreSQL or SQLite3 by editing the `install-config.yml` file in the vagrant directory. The next time you run `vagrant up` (or `vagrant provision`) it will be installed under the new configuration. @@ -98,9 +98,9 @@ $ mysql -uhomestead -psecret UserFrosting < /home/vagrant/userfrosting/userfrost ### Included Software -* Ubuntu 14.04 +* Ubuntu 16.04 * Git -* PHP 5.6 +* PHP 7.1 * HHVM * Nginx * MySQL From cbce07ad71dec3283a2f964c04fc9b3528c3fd2c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 15 Aug 2018 22:05:58 -0400 Subject: [PATCH 077/237] Renamed Vagrant doc to `README.md` --- vagrant/{doc.md => README.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename vagrant/{doc.md => README.md} (100%) diff --git a/vagrant/doc.md b/vagrant/README.md similarity index 100% rename from vagrant/doc.md rename to vagrant/README.md From fa861e40cadfd7f12c3711103665b05ff601a9c7 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 22 Aug 2018 21:03:45 -0400 Subject: [PATCH 078/237] Fix issue with test when no database is defined --- .../Integration/DatabaseMigratorServiceTest.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php index e6d5a5ca7..f457a37f4 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php @@ -7,6 +7,7 @@ */ namespace UserFrosting\Tests\Integration; +use UserFrosting\Sprinkle\Core\Tests\TestDatabase; use UserFrosting\Tests\TestCase; /** @@ -16,6 +17,19 @@ */ class DatabaseMigratorServiceTest extends TestCase { + use TestDatabase; + + /** + * @inheritDoc + */ + public function setUp() + { + parent::setUp(); + + // Setup test database + $this->setupTestDatabase(); + } + public function testMigratorService() { $this->assertInstanceOf('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator', $this->ci->migrator); From add9a1425716954b58b8bb9b6686e44b7ef2e4d6 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 22 Aug 2018 21:27:04 -0400 Subject: [PATCH 079/237] Updated AssetLoader integration --- .../core/src/Controller/CoreController.php | 16 ++-- .../src/ServicesProvider/ServicesProvider.php | 2 +- app/sprinkles/core/src/Util/AssetLoader.php | 92 ------------------- 3 files changed, 8 insertions(+), 102 deletions(-) delete mode 100644 app/sprinkles/core/src/Util/AssetLoader.php diff --git a/app/sprinkles/core/src/Controller/CoreController.php b/app/sprinkles/core/src/Controller/CoreController.php index 4980808ea..0485758be 100644 --- a/app/sprinkles/core/src/Controller/CoreController.php +++ b/app/sprinkles/core/src/Controller/CoreController.php @@ -26,7 +26,7 @@ class CoreController extends SimpleController * By default, this is the page that non-authenticated users will first see when they navigate to your website's root. * Request type: GET */ - public function pageIndex($request, $response, $args) + public function pageIndex(Request $request, Response $response, $args) { return $this->ci->view->render($response, 'pages/index.html.twig'); } @@ -36,7 +36,7 @@ public function pageIndex($request, $response, $args) * * Request type: GET */ - public function pageAbout($request, $response, $args) + public function pageAbout(Request $request, Response $response, $args) { return $this->ci->view->render($response, 'pages/about.html.twig'); } @@ -46,7 +46,7 @@ public function pageAbout($request, $response, $args) * * Request type: GET */ - public function pageLegal($request, $response, $args) + public function pageLegal(Request $request, Response $response, $args) { return $this->ci->view->render($response, 'pages/legal.html.twig'); } @@ -56,7 +56,7 @@ public function pageLegal($request, $response, $args) * * Request type: GET */ - public function pagePrivacy($request, $response, $args) + public function pagePrivacy(Request $request, Response $response, $args) { return $this->ci->view->render($response, 'pages/privacy.html.twig'); } @@ -67,7 +67,7 @@ public function pagePrivacy($request, $response, $args) * The alert stream contains messages which have been generated by calls to `MessageStream::addMessage` and `MessageStream::addMessageTranslated`. * Request type: GET */ - public function jsonAlerts($request, $response, $args) + public function jsonAlerts(Request $request, Response $response, $args) { return $response->withJson($this->ci->alerts->getAndClearMessages()); } @@ -76,11 +76,9 @@ public function jsonAlerts($request, $response, $args) * Handle all requests for raw assets. * Request type: GET */ - public function getAsset($request, $response, $args) + public function getAsset(Request $request, Response $response, $args) { - // By starting this service, we ensure that the timezone gets set. - $config = $this->ci->config; - + /** @var \UserFrosting\Assets\AssetLoader $assetLoader */ $assetLoader = $this->ci->assetLoader; if (!$assetLoader->loadAsset($args['url'])) { diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 05ad083f3..9f9a59a7f 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -28,6 +28,7 @@ use Slim\Views\Twig; use Slim\Views\TwigExtension; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; +use UserFrosting\Assets\AssetLoader; use UserFrosting\Assets\AssetBundleSchema; use UserFrosting\Cache\TaggableFileStore; use UserFrosting\Cache\MemcachedStore; @@ -54,7 +55,6 @@ use UserFrosting\Sprinkle\Core\Twig\CoreExtension; use UserFrosting\Sprinkle\Core\Util\CheckEnvironment; use UserFrosting\Sprinkle\Core\Util\ClassMapper; -use UserFrosting\Sprinkle\Core\Util\AssetLoader; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\NotFoundException; use UserFrosting\Support\Repository\Loader\ArrayFileLoader; diff --git a/app/sprinkles/core/src/Util/AssetLoader.php b/app/sprinkles/core/src/Util/AssetLoader.php deleted file mode 100644 index 407dab2d6..000000000 --- a/app/sprinkles/core/src/Util/AssetLoader.php +++ /dev/null @@ -1,92 +0,0 @@ -assets = $assets; - } - - /** - * Compute the full filesystem path for the specified relative path (usually extracted from a URL). - * - * Also checks to make sure that the file actually exists. - * @param string $relativePath - * @return bool True if the file exists, false otherwise - */ - public function loadAsset($relativePath) - { - $this->fullPath = $this->assets->urlPathToAbsolutePath($relativePath); - - // Return false if file does not exist - if (!file_exists($this->fullPath)) { - return false; - } - - return true; - } - - /** - * Get the raw contents of the currently targeted file. - * - * @return string - */ - public function getContent() - { - return file_get_contents($this->fullPath); - } - - /** - * Get the length in bytes of the currently targeted file. - * - * @return int - */ - public function getLength() - { - return filesize($this->fullPath); - } - - /** - * Get the best-guess MIME type of the currently targeted file, based on the file extension. - * - * @return string - */ - public function getType() - { - return MimeType::detectByFilename($this->fullPath); - } -} From 3118a97f7f9e20f3c23d4a343fd5504be87e4d46 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 22 Aug 2018 22:23:34 -0400 Subject: [PATCH 080/237] Forgot to register the shared assets somehow --- app/system/ServicesProvider.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 2abd242d3..ec4b9989f 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -50,6 +50,7 @@ public function register(ContainerInterface $container) $locator->registerStream('log', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\LOG_DIR_NAME, true); $locator->registerStream('cache', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\CACHE_DIR_NAME, true); $locator->registerStream('session', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); + $locator->registerStream('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); $locator->registerStream('assets', 'vendor', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\BOWER_ASSET_DIR, true); $locator->registerStream('assets', 'vendor', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\NPM_ASSET_DIR, true); From 2cd1588ce72f303e899e8ca6afe7d826c35bc1ad Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 23 Aug 2018 20:55:58 -0400 Subject: [PATCH 081/237] Nope. This should fix the (non production) assets --- app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 1 - app/system/ServicesProvider.php | 5 ++--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 9f9a59a7f..4be9af681 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -145,7 +145,6 @@ public function register(ContainerInterface $container) } else { $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; $assets = new Assets($locator, 'assets', $baseUrl); - $assets->overrideBasePath($locator->getBase() . '/public/assets'); // Load compiled asset bundle. $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index ec4b9989f..adfe6933f 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -50,9 +50,8 @@ public function register(ContainerInterface $container) $locator->registerStream('log', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\LOG_DIR_NAME, true); $locator->registerStream('cache', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\CACHE_DIR_NAME, true); $locator->registerStream('session', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); - $locator->registerStream('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); - $locator->registerStream('assets', 'vendor', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\BOWER_ASSET_DIR, true); - $locator->registerStream('assets', 'vendor', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\NPM_ASSET_DIR, true); + $locator->registerStream('assets', 'vendor', \UserFrosting\BOWER_ASSET_DIR, true); + $locator->registerStream('assets', 'vendor', \UserFrosting\NPM_ASSET_DIR, true); // Register sprinkles streams $locator->registerStream('assets', '', \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME); From 783e4f7e71c034aeaa617d241a0b78e7f5752678 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 24 Aug 2018 21:48:00 -0400 Subject: [PATCH 082/237] userfrosting/uniformresourcelocator is now on Packagist \o/ --- app/sprinkles/core/composer.json | 7 ------- .../core/src/ServicesProvider/ServicesProvider.php | 4 ---- 2 files changed, 11 deletions(-) diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index cc660c4de..1d51b00e2 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -24,13 +24,6 @@ "name": "Srinivas Nukala" } ], - "repositories": [ - { - "type": "vcs", - "url": "https://github.com/userfrosting/UniformResourceLocator", - "no-api": true - } - ], "require": { "doctrine/dbal": "^2.5", "filp/whoops": "^2.1", diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 4be9af681..49764d8a0 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -20,16 +20,12 @@ use League\FactoryMuffin\FactoryMuffin; use League\FactoryMuffin\Faker\Facade as Faker; use Monolog\Formatter\LineFormatter; -use Monolog\Handler\ErrorLogHandler; use Monolog\Handler\StreamHandler; use Monolog\Logger; use Slim\Csrf\Guard; -use Slim\Http\Uri; use Slim\Views\Twig; use Slim\Views\TwigExtension; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use UserFrosting\Assets\AssetLoader; -use UserFrosting\Assets\AssetBundleSchema; use UserFrosting\Cache\TaggableFileStore; use UserFrosting\Cache\MemcachedStore; use UserFrosting\Cache\RedisStore; From 69a991a822cad90694507c8c0e39adc77e030803 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 29 Sep 2018 18:33:42 -0400 Subject: [PATCH 083/237] Cause an error if a sprinkle doesn't have (need) a `template/` folder --- app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 49764d8a0..90b5a9745 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -633,7 +633,7 @@ public function register(ContainerInterface $container) * Also adds the UserFrosting core Twig extension, which provides additional functions, filters, global variables, etc. */ $container['view'] = function ($c) { - $templatePaths = $c->locator->findResources('templates://', true, true); + $templatePaths = $c->locator->findResources('templates://', true, false); $view = new Twig($templatePaths); From 72f451ab37d6f7ea41a5c4c63327168cf1f8dc36 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 29 Sep 2018 23:17:27 -0400 Subject: [PATCH 084/237] Fix small typo in comment --- app/system/Bakery/BaseCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/system/Bakery/BaseCommand.php b/app/system/Bakery/BaseCommand.php index 7add8188a..731dce960 100644 --- a/app/system/Bakery/BaseCommand.php +++ b/app/system/Bakery/BaseCommand.php @@ -24,7 +24,7 @@ abstract class BaseCommand extends Command { /** - * @var @Symfony\Component\Console\Style\SymfonyStyle + * @var \Symfony\Component\Console\Style\SymfonyStyle * See http://symfony.com/doc/current/console/style.html */ protected $io; From f6cc6cf45d1d7a238d49d891e28acd92160e5f79 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 12 Oct 2018 21:26:34 -0400 Subject: [PATCH 085/237] Linting --- app/sprinkles/core/src/Router.php | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/app/sprinkles/core/src/Router.php b/app/sprinkles/core/src/Router.php index 8a10c8565..19a8b0e0e 100644 --- a/app/sprinkles/core/src/Router.php +++ b/app/sprinkles/core/src/Router.php @@ -7,16 +7,8 @@ */ namespace UserFrosting\Sprinkle\Core; -use FastRoute\Dispatcher; use Illuminate\Filesystem\Filesystem; use InvalidArgumentException; -use RuntimeException; -use Psr\Http\Message\ServerRequestInterface; -use FastRoute\RouteCollector; -use FastRoute\RouteParser; -use FastRoute\RouteParser\Std as StdParser; -use FastRoute\DataGenerator; -use Slim\Interfaces\RouteGroupInterface; use Slim\Interfaces\RouterInterface; use Slim\Interfaces\RouteInterface; @@ -29,7 +21,7 @@ class Router extends \Slim\Router implements RouterInterface { - /* + /** * @var string[] a reverse lookup of route identifiers, indexed by route signature */ protected $identifiers; @@ -82,13 +74,12 @@ public function map($methods, $pattern, $handler) /** * Delete the cache file * - * @access public * @return bool true/false if operation is successfull */ public function clearCache() { // Get Filesystem instance - $fs = new FileSystem; + $fs = new Filesystem; // Make sure file exist and delete it if ($fs->exists($this->cacheFile)) { From b14964190d7035972fbfd045be1b65a45eac464c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 14 Oct 2018 10:51:22 -0400 Subject: [PATCH 086/237] Fix for #854 - Routes not available in Tests [and Bakery] --- app/sprinkles/core/config/testing.php | 8 ++ app/sprinkles/core/src/Core.php | 7 +- app/sprinkles/core/src/Router.php | 24 +++++ app/sprinkles/core/tests/Unit/RouterTest.php | 27 +++++ app/system/Bakery/Bakery.php | 5 +- app/system/UserFrosting.php | 100 ++++++++++--------- app/tests/TestCase.php | 56 ++++------- 7 files changed, 138 insertions(+), 89 deletions(-) create mode 100644 app/sprinkles/core/tests/Unit/RouterTest.php diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index 7da03c20e..9649fcb27 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -11,6 +11,14 @@ 'default' => 'array', ] ], + /** + * Disable CSRF in the testing env. + */ + 'csrf' => [ + 'blacklist' => [ + '^/' => ['GET'] + ] + ], 'db' => [ 'test_integration' => [ 'driver' => 'sqlite', diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index 6af67897d..ab5d79cdf 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -104,16 +104,19 @@ public function onSprinklesRegisterServices() /** * Add CSRF middleware. + * + * @param Event $event */ public function onAddGlobalMiddleware(Event $event) { $request = $this->ci->request; $path = $request->getUri()->getPath(); - $method = $request->getMethod(); + $method = ($request->getMethod()) ?: 'GET'; // Normalize path to always have a leading slash $path = '/' . ltrim($path, '/'); - // Normalize method to uppercase + + // Normalize method to uppercase. $method = strtoupper($method); $csrfBlacklist = $this->ci->config['csrf.blacklist']; diff --git a/app/sprinkles/core/src/Router.php b/app/sprinkles/core/src/Router.php index 19a8b0e0e..abcb374f0 100644 --- a/app/sprinkles/core/src/Router.php +++ b/app/sprinkles/core/src/Router.php @@ -9,6 +9,7 @@ use Illuminate\Filesystem\Filesystem; use InvalidArgumentException; +use Slim\App; use Slim\Interfaces\RouterInterface; use Slim\Interfaces\RouteInterface; @@ -89,4 +90,27 @@ public function clearCache() // It's still considered a success if file doesn't exist return true; } + + /** + * Load all avaialbe routes + * + * @param App $slimApp + */ + public function loadRoutes(App $slimApp) + { + // Since routes aren't encapsulated in a class yet, we need this workaround :( + global $app; + $app = $slimApp; + + $ci = $app->getContainer(); + + // TODO :: Use the new locator instead of `findRessources` + $routePaths = array_reverse($ci->locator->findResources('routes://', true, true)); + foreach ($routePaths as $path) { + $routeFiles = glob($path . '/*.php'); + foreach ($routeFiles as $routeFile) { + require $routeFile; + } + } + } } diff --git a/app/sprinkles/core/tests/Unit/RouterTest.php b/app/sprinkles/core/tests/Unit/RouterTest.php new file mode 100644 index 000000000..456305988 --- /dev/null +++ b/app/sprinkles/core/tests/Unit/RouterTest.php @@ -0,0 +1,27 @@ +ci->router; + + // Get all routes. We should have more than 0 in a default install + $routes = $router->getRoutes(); + $this->assertNotCount(0, $routes); + + // Try to get a path + $path = $router->pathFor('index'); + $this->assertEquals('/', $path); + } +} \ No newline at end of file diff --git a/app/system/Bakery/Bakery.php b/app/system/Bakery/Bakery.php index 78a1016a0..1fe4c53b2 100644 --- a/app/system/Bakery/Bakery.php +++ b/app/system/Bakery/Bakery.php @@ -51,10 +51,7 @@ public function __construct() $this->app = new Application("UserFrosting Bakery", \UserFrosting\VERSION); // Setup the sprinkles - $uf = new UserFrosting(); - - // Set argument as false, we are using the CLI - $uf->setupSprinkles(false); + $uf = new UserFrosting(true); // Get the container $this->ci = $uf->getContainer(); diff --git a/app/system/UserFrosting.php b/app/system/UserFrosting.php index 4f569ec4b..511412201 100644 --- a/app/system/UserFrosting.php +++ b/app/system/UserFrosting.php @@ -14,6 +14,9 @@ use UserFrosting\Support\Exception\FileNotFoundException; use UserFrosting\System\Facade; +/** + * UserFrosting Main Class + */ class UserFrosting { /** @@ -26,24 +29,36 @@ class UserFrosting */ protected $app; + /** + * @var bool Is the app in CLI mode + */ + protected $isCli; + /** * Create the UserFrosting application instance. + * + * @param bool $cli Is the app in CLI mode. Set to false if setting up in an HTTP/web environment, true if setting up for CLI scripts. */ - public function __construct() + public function __construct($cli = false) { // First, we create our DI container $this->ci = new Container; + // Assign vars + $this->isCli = $cli; + // Set up facade reference to container. Facade::setFacadeContainer($this->ci); + + // Setup UF App + $this->setupApp(); } /** * Fires an event with optional parameters. * * @param string $eventName - * @param Event $event - * + * @param Event|null $event * @return Event */ public function fireEvent($eventName, Event $event = null) @@ -57,7 +72,7 @@ public function fireEvent($eventName, Event $event = null) /** * Return the underlying Slim App instance, if available. * - * @return Slim\App + * @return App */ public function getApp() { @@ -67,65 +82,25 @@ public function getApp() /** * Return the DI container. * - * @return Slim\Container + * @return Container */ public function getContainer() { return $this->ci; } - /** - * Include all defined routes in route stream. - * - * Include them in reverse order to allow higher priority routes to override lower priority. - */ - public function loadRoutes() - { - // Since routes aren't encapsulated in a class yet, we need this workaround :( - global $app; - $app = $this->app; - - $routePaths = array_reverse($this->ci->locator->findResources('routes://', true, true)); - foreach ($routePaths as $path) { - $routeFiles = glob($path . '/*.php'); - foreach ($routeFiles as $routeFile) { - require_once $routeFile; - } - } - } - /** * Initialize the application. Set up Sprinkles and the Slim app, define routes, register global middleware, and run Slim. */ public function run() { - $this->setupSprinkles(); - - // Set the configuration settings for Slim in the 'settings' service - $this->ci->settings = $this->ci->config['settings']; - - // Next, we'll instantiate the Slim application. Note that the application is required for the SprinkleManager to set up routes. - $this->app = new App($this->ci); - - $slimAppEvent = new SlimAppEvent($this->app); - - $this->fireEvent('onAppInitialize', $slimAppEvent); - - // Set up all routes - $this->loadRoutes(); - - // Add global middleware - $this->fireEvent('onAddGlobalMiddleware', $slimAppEvent); - $this->app->run(); } /** - * Register system services, load all sprinkles, and add their resources and services. - * - * @param bool $isWeb Set to true if setting up in an HTTP/web environment, false if setting up for CLI scripts. + * Register system services, load all sprinkles, and add their resources and services */ - public function setupSprinkles($isWeb = true) + protected function setupSprinkles() { // Register system services $serviceProvider = new ServicesProvider(); @@ -137,7 +112,7 @@ public function setupSprinkles($isWeb = true) try { $sprinkleManager->initFromSchema(\UserFrosting\SPRINKLES_SCHEMA_FILE); } catch (FileNotFoundException $e) { - if ($isWeb) { + if (!$this->isCli) { $this->renderSprinkleErrorPage($e->getMessage()); } else { $this->renderSprinkleErrorCli($e->getMessage()); @@ -155,8 +130,35 @@ public function setupSprinkles($isWeb = true) $this->fireEvent('onSprinklesRegisterServices'); } + /** + * Setup UserFrosting App, load sprinkles, load routes, etc. + */ + protected function setupApp() + { + // Setup sprinkles + $this->setupSprinkles(); + + // Set the configuration settings for Slim in the 'settings' service + $this->ci->settings = $this->ci->config['settings']; + + // Next, we'll instantiate the Slim application. Note that the application is required for the SprinkleManager to set up routes. + $this->app = new App($this->ci); + + $slimAppEvent = new SlimAppEvent($this->app); + + $this->fireEvent('onAppInitialize', $slimAppEvent); + + // Set up all routes + $this->ci->router->loadRoutes($this->app); + + // Add global middleware + $this->fireEvent('onAddGlobalMiddleware', $slimAppEvent); + } + /** * Render a basic error page for problems with loading Sprinkles. + * + * @param string $errorMessage Message to display [Default ""] */ protected function renderSprinkleErrorPage($errorMessage = "") { @@ -179,6 +181,8 @@ protected function renderSprinkleErrorPage($errorMessage = "") /** * Render a CLI error message for problems with loading Sprinkles. + * + * @param string $errorMessage Message to display [Default ""] */ protected function renderSprinkleErrorCli($errorMessage = "") { diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php index bd8b2237f..c5576871b 100644 --- a/app/tests/TestCase.php +++ b/app/tests/TestCase.php @@ -7,7 +7,6 @@ */ namespace UserFrosting\Tests; -use Slim\App; use PHPUnit\Framework\TestCase as BaseTestCase; use UserFrosting\System\UserFrosting; use UserFrosting\Sprinkle\Core\Facades\Debug; @@ -20,13 +19,6 @@ */ class TestCase extends BaseTestCase { - /** - * The Slim application instance. - * - * @var \Slim\App - */ - protected $app; - /** * The global container object, which holds all your services. * @@ -62,7 +54,7 @@ class TestCase extends BaseTestCase */ protected function setUp() { - if (!$this->app) { + if (!$this->ci) { $this->refreshApplication(); } @@ -78,6 +70,7 @@ protected function setUp() /** * Boot the testing helper traits. * + * @deprecated * @return void */ protected function setUpTraits() @@ -103,17 +96,11 @@ protected function refreshApplication() // no way to override environment vars that have already been set. putenv('UF_MODE=testing'); - // Setup the sprinkles - $uf = new UserFrosting(); - - // Set argument as false, we are using the CLI - $uf->setupSprinkles(false); + // Setup the base UF app + $uf = new UserFrosting(true); // Get the container $this->ci = $uf->getContainer(); - - // Next, we'll instantiate the application. Note that the application is required for the SprinkleManager to set up routes. - $this->app = new App($this->ci); } /** @@ -123,12 +110,11 @@ protected function refreshApplication() */ protected function tearDown() { - if ($this->app) { + if ($this->ci) { foreach ($this->beforeApplicationDestroyedCallbacks as $callback) { call_user_func($callback); } - $this->app = null; $this->ci = null; } @@ -154,14 +140,14 @@ public function afterApplicationCreated(callable $callback) } /** - * Asserts that collections are equivalent. + * Asserts that collections are equivalent. * - * @param array $expected - * @param array $actual - * @param string $key [description] - * @param string $message [description] - * @throws \PHPUnit_Framework_AssertionFailedError - * @return void + * @param array $expected + * @param array $actual + * @param string $key [description] + * @param string $message [description] + * @throws \PHPUnit_Framework_AssertionFailedError + * @return void */ public static function assertCollectionsSame($expected, $actual, $key = 'id', $message = '') { @@ -204,10 +190,10 @@ protected function beforeApplicationDestroyed(callable $callback) */ /** - * Cast an item to an array if it has a toArray() method. + * Cast an item to an array if it has a toArray() method. * - * @param object $item - * @return mixed + * @param object $item + * @return mixed */ protected static function castToComparable($item) { @@ -215,10 +201,10 @@ protected static function castToComparable($item) } /** - * Remove all relations on a collection of models. + * Remove all relations on a collection of models. * - * @param array $models - * @return void + * @param array $models + * @return void */ protected static function ignoreRelations($models) { @@ -228,10 +214,10 @@ protected static function ignoreRelations($models) } /** - * cloneObjectArray + * cloneObjectArray * - * @param array $original - * @return array + * @param array $original + * @return array */ protected function cloneObjectArray($original) { From e0e90c12afc58a3190d15ba3ab1c18ed53923a4a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 14 Oct 2018 10:53:09 -0400 Subject: [PATCH 087/237] Added comments to testing config ...to keep track of why those options are set --- app/sprinkles/core/config/testing.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index 9649fcb27..55c21d330 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -6,6 +6,9 @@ */ return [ + /** + * Don't use persistant caching in tests + */ 'cache' => [ 'illuminate' => [ 'default' => 'array', @@ -19,12 +22,18 @@ '^/' => ['GET'] ] ], + /** + * Use in memory db for testing + */ 'db' => [ 'test_integration' => [ 'driver' => 'sqlite', 'database' => ':memory:', ] ], + /** + * Don'T display error detail in test. Return the non formatted errors + */ 'settings' => [ 'displayErrorDetails' => false ] From 978db3768920cc9e835801ede4a0bbd7bd3ecba8 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 14 Oct 2018 16:59:50 -0400 Subject: [PATCH 088/237] Migrated `route:list` Bakery command to Core Sprinkle and 4.2 + Added more info, show in table form and added sorting/filtering --- .../core/src/Bakery/RouteListCommand.php | 129 ++++++++++++++++++ .../Bakery/Command/RouteListCommand.php | 70 ---------- 2 files changed, 129 insertions(+), 70 deletions(-) create mode 100644 app/sprinkles/core/src/Bakery/RouteListCommand.php delete mode 100644 app/system/Bakery/Command/RouteListCommand.php diff --git a/app/sprinkles/core/src/Bakery/RouteListCommand.php b/app/sprinkles/core/src/Bakery/RouteListCommand.php new file mode 100644 index 000000000..5233b68e7 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/RouteListCommand.php @@ -0,0 +1,129 @@ +setName('route:list') + ->setDescription('Generate a list all registered routes') + ->addOption('method', null, InputOption::VALUE_REQUIRED, 'Filter the routes by method.') + ->addOption('name', null, InputOption::VALUE_REQUIRED, 'Filter the routes by name.') + ->addOption('uri', null, InputOption::VALUE_REQUIRED, 'Filter the routes by uri.') + ->addOption('reverse', 'r', InputOption::VALUE_NONE, 'Reverse the ordering of the routes.') + ->addOption('sort', null, InputOption::VALUE_REQUIRED, 'The column (method, uri, name, action) to sort by.', 'uri'); + } + + /** + * {@inheritDoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title("Registered Routes"); + + // Get routes list + $this->routes = $this->ci->router->getRoutes(); + + // If not route, don't go further + if (count($this->routes) === 0) { + return $this->io->error("Your application doesn't have any routes."); + } + + // Compile the routes into a displayable format + $routes = collect($this->routes)->map(function ($route) use ($input) { + return $this->getRouteInformation($route, $input); + })->all(); + + // Apply sort + if ($sort = $input->getOption('sort')) { + $routes = $this->sortRoutes($sort, $routes); + } + + // Apply reverse if required + if ($input->getOption('reverse')) { + $routes = array_reverse($routes); + } + + // Display routes + $this->io->table($this->headers, array_filter($routes)); + } + + /** + * Get the route information for a given route. + * + * @param Route $route + * @param InputInterface $input [description] + * @return array + */ + protected function getRouteInformation(Route $route, InputInterface $input) + { + return $this->filterRoute([ + 'method' => implode('|', $route->getMethods()), + 'uri' => $route->getPattern(), + 'name' => $route->getName(), + 'action' => $route->getCallable(), + ], $input); + } + + /** + * Sort the routes by a given element. + * + * @param string $sort + * @param array $routes + * @return array + */ + protected function sortRoutes($sort, $routes) + { + return Arr::sort($routes, function ($route) use ($sort) { + return $route[$sort]; + }); + } + + /** + * Filter the route by URI and / or name. + * + * @param array $route + * @param InputInterface $input [description] + * @return array|null + */ + protected function filterRoute(array $route, InputInterface $input) + { + if (($input->getOption('name') && ! Str::contains($route['name'], $input->getOption('name'))) || + $input->getOption('uri') && ! Str::contains($route['uri'], $input->getOption('uri')) || + $input->getOption('method') && ! Str::contains($route['method'], strtoupper($input->getOption('method')))) { + return; + } + + return $route; + } +} diff --git a/app/system/Bakery/Command/RouteListCommand.php b/app/system/Bakery/Command/RouteListCommand.php deleted file mode 100644 index cec58516b..000000000 --- a/app/system/Bakery/Command/RouteListCommand.php +++ /dev/null @@ -1,70 +0,0 @@ -setName("route:list") - ->setDescription("Dumps all routes."); - } - - /** - * {@inheritDoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - global $app; - - $this->ci->settings = $this->ci->config['settings']; - $this->app = new App($this->ci); - $app = $this->app; - - $this->io->title("Registered Routes"); - $routePaths = array_reverse($this->ci->locator->findResources('routes://', true, true)); - $routeCount=0; - foreach ($routePaths as $path) { - $routeFiles = glob($path . '/*.php'); - foreach ($routeFiles as $routeFile) { - $routeCount += 1; - //$this->io->writeln("$routeFile"); - require_once $routeFile; - } - } - - $allRoutes = $app->getContainer()->get('router')->getRoutes(); - foreach ($allRoutes as $route) { - $p = $route->getPattern(); - foreach ($route->getMethods() as $m) - $this->io->writeln($m.' '.$p); - } - - $this->io->success("Route list generated from {$routeCount} files!"); - } -} From 56cad27ed08c0899b25b3958acdedac887b4c283 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 15 Oct 2018 18:57:39 -0400 Subject: [PATCH 089/237] Use new locator to load routes instead of glob --- app/sprinkles/core/src/Router.php | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/app/sprinkles/core/src/Router.php b/app/sprinkles/core/src/Router.php index abcb374f0..6bb7b538e 100644 --- a/app/sprinkles/core/src/Router.php +++ b/app/sprinkles/core/src/Router.php @@ -104,13 +104,9 @@ public function loadRoutes(App $slimApp) $ci = $app->getContainer(); - // TODO :: Use the new locator instead of `findRessources` - $routePaths = array_reverse($ci->locator->findResources('routes://', true, true)); - foreach ($routePaths as $path) { - $routeFiles = glob($path . '/*.php'); - foreach ($routeFiles as $routeFile) { - require $routeFile; - } + $routeFiles = array_reverse($ci->locator->listResources('routes://', true)); + foreach ($routeFiles as $routeFile) { + require $routeFile; } } } From fcc2bfc3eea7ac22b07afb63d4dcdde308da34af Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 15 Oct 2018 21:23:52 -0400 Subject: [PATCH 090/237] Added @return for all services for easier documentation, part of #711 --- .../src/ServicesProvider/ServicesProvider.php | 45 +++++++++++++--- .../src/ServicesProvider/ServicesProvider.php | 16 +++--- .../src/ServicesProvider/ServicesProvider.php | 54 ++++++++++++++++++- app/system/ServicesProvider.php | 10 ++-- 4 files changed, 106 insertions(+), 19 deletions(-) diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index 037d98269..e3cf80309 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -7,10 +7,8 @@ */ namespace UserFrosting\Sprinkle\Account\ServicesProvider; -use Birke\Rememberme\Authenticator as RememberMe; use Illuminate\Database\Capsule\Manager as Capsule; -use Monolog\Formatter\LineFormatter; -use Monolog\Handler\ErrorLogHandler; +use Interop\Container\ContainerInterface; use Monolog\Handler\StreamHandler; use Monolog\Logger; use Psr\Http\Message\ResponseInterface as Response; @@ -25,7 +23,6 @@ use UserFrosting\Sprinkle\Account\Repository\PasswordResetRepository; use UserFrosting\Sprinkle\Account\Repository\VerificationRepository; use UserFrosting\Sprinkle\Account\Twig\AccountExtension; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Log\MixedFormatter; /** @@ -38,12 +35,14 @@ class ServicesProvider /** * Register UserFrosting's account services. * - * @param Container $container A DI container implementing ArrayAccess and container-interop. + * @param ContainerInterface $container A DI container implementing ArrayAccess and container-interop. */ - public function register($container) + public function register(ContainerInterface $container) { /** * Extend the asset manager service to see assets for the current user's theme. + * + * @return \UserFrosting\Assets\Assets */ $container->extend('assets', function ($assets, $c) { @@ -68,6 +67,8 @@ public function register($container) * Extend the 'classMapper' service to register model classes. * * Mappings added: User, Group, Role, Permission, Activity, PasswordReset, Verification + * + * @return \UserFrosting\Sprinkle\Core\Util\ClassMapper */ $container->extend('classMapper', function ($classMapper, $c) { $classMapper->setClassMapping('user', 'UserFrosting\Sprinkle\Account\Database\Models\User'); @@ -84,6 +85,8 @@ public function register($container) * Extends the 'errorHandler' service with custom exception handlers. * * Custom handlers added: ForbiddenExceptionHandler + * + * @return \UserFrosting\Sprinkle\Core\Error\ExceptionHandlerManager */ $container->extend('errorHandler', function ($handler, $c) { // Register the ForbiddenExceptionHandler. @@ -98,6 +101,7 @@ public function register($container) /** * Extends the 'localePathBuilder' service, adding any locale files from the user theme. * + * @return \UserFrosting\I18n\LocalePathBuilder */ $container->extend('localePathBuilder', function ($pathBuilder, $c) { // Add paths for user theme, if a user is logged in @@ -125,6 +129,8 @@ public function register($container) * Extends the 'view' service with the AccountExtension for Twig. * * Adds account-specific functions, globals, filters, etc to Twig, and the path to templates for the user theme. + * + * @return \Slim\Views\Twig */ $container->extend('view', function ($view, $c) { $twig = $view->getEnvironment(); @@ -159,6 +165,8 @@ public function register($container) * Authentication service. * * Supports logging in users, remembering their sessions, etc. + * + * @return \UserFrosting\Sprinkle\Account\Authenticate\Authenticator */ $container['authenticator'] = function ($c) { $classMapper = $c->classMapper; @@ -178,6 +186,8 @@ public function register($container) /** * Sets up the AuthGuard middleware, used to limit access to authenticated users for certain routes. + * + * @return \UserFrosting\Sprinkle\Account\Authenticate\AuthGuard */ $container['authGuard'] = function ($c) { $authenticator = $c->authenticator; @@ -188,6 +198,8 @@ public function register($container) * Authorization check logging with Monolog. * * Extend this service to push additional handlers onto the 'auth' log stack. + * + * @return \Monolog\Logger */ $container['authLogger'] = function ($c) { $logger = new Logger('auth'); @@ -208,6 +220,8 @@ public function register($container) * Authorization service. * * Determines permissions for user actions. Extend this service to add additional access condition callbacks. + * + * @return \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $container['authorizer'] = function ($c) { $config = $c->config; @@ -327,6 +341,8 @@ public function register($container) /** * Loads the User object for the currently logged-in user. + * + * @return \UserFrosting\Sprinkle\Account\Database\Models\User */ $container['currentUser'] = function ($c) { $authenticator = $c->authenticator; @@ -334,6 +350,11 @@ public function register($container) return $authenticator->user(); }; + /** + * Password Hasher service + * + * @return \UserFrosting\Sprinkle\Account\Authenticate\Hasher + */ $container['passwordHasher'] = function ($c) { $hasher = new Hasher(); return $hasher; @@ -341,6 +362,8 @@ public function register($container) /** * Returns a callback that forwards to dashboard if user is already logged in. + * + * @return callable */ $container['redirect.onAlreadyLoggedIn'] = function ($c) { /** @@ -361,6 +384,8 @@ public function register($container) /** * Returns a callback that handles setting the `UF-Redirect` header after a successful login. + * + * @return callable */ $container['redirect.onLogin'] = function ($c) { /** @@ -380,7 +405,7 @@ public function register($container) return $determineRedirectOnLogin($response)->withStatus(200); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $c->authorizer; $currentUser = $c->authenticator->user(); @@ -395,6 +420,8 @@ public function register($container) /** * Repository for password reset requests. + * + * @return \UserFrosting\Sprinkle\Account\Repository\PasswordResetRepository */ $container['repoPasswordReset'] = function ($c) { $classMapper = $c->classMapper; @@ -406,6 +433,8 @@ public function register($container) /** * Repository for verification requests. + * + * @return \UserFrosting\Sprinkle\Account\Repository\VerificationRepository */ $container['repoVerification'] = function ($c) { $classMapper = $c->classMapper; @@ -419,6 +448,8 @@ public function register($container) * Logger for logging the current user's activities to the database. * * Extend this service to push additional handlers onto the 'userActivity' log stack. + * + * @return \Monolog\Logger */ $container['userActivityLogger'] = function ($c) { $classMapper = $c->classMapper; diff --git a/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php index c7ded2b12..7f87c28e7 100644 --- a/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php @@ -7,11 +7,9 @@ */ namespace UserFrosting\Sprinkle\Admin\ServicesProvider; +use Interop\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use UserFrosting\Sprinkle\Account\Authenticate\Authenticator; -use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager; -use UserFrosting\Sprinkle\Core\Facades\Debug; /** * Registers services for the admin sprinkle. @@ -23,14 +21,16 @@ class ServicesProvider /** * Register UserFrosting's admin services. * - * @param Container $container A DI container implementing ArrayAccess and container-interop. + * @param ContainerInterface $container A DI container implementing ArrayAccess and container-interop. */ - public function register($container) + public function register(ContainerInterface $container) { /** * Extend the 'classMapper' service to register sprunje classes. * * Mappings added: 'activity_sprunje', 'group_sprunje', 'permission_sprunje', 'role_sprunje', 'user_sprunje' + * + * @return \UserFrosting\Sprinkle\Core\Util\ClassMapper */ $container->extend('classMapper', function ($classMapper, $c) { $classMapper->setClassMapping('activity_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\ActivitySprunje'); @@ -47,6 +47,8 @@ public function register($container) * Returns a callback that handles setting the `UF-Redirect` header after a successful login. * * Overrides the service definition in the account Sprinkle. + * + * @return callable */ $container['redirect.onLogin'] = function ($c) { /** @@ -62,11 +64,11 @@ public function register($container) // Backwards compatibility for the deprecated determineRedirectOnLogin service if ($c->has('determineRedirectOnLogin')) { $determineRedirectOnLogin = $c->determineRedirectOnLogin; - + return $determineRedirectOnLogin($response)->withStatus(200); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $c->authorizer; $currentUser = $c->authenticator->user(); diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 90b5a9745..22ce66408 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -75,6 +75,9 @@ public function register(ContainerInterface $container) * Flash messaging service. * * Persists error/success messages between requests in the session. + * + * @throws \Exception If alert storage handler is not supported + * @return \UserFrosting\Sprinkle\Core\Alert\AlertStream */ $container['alerts'] = function ($c) { $config = $c->config; @@ -94,6 +97,8 @@ public function register(ContainerInterface $container) * Loads assets from a specified relative location. * Assets are Javascript, CSS, image, and other files used by your site. * This implementation is a temporary hack until Assets can be refactored. + * + * @return \UserFrosting\Assets\AssetLoader */ $container['assetLoader'] = function ($c) { $config = $c->config; @@ -111,6 +116,8 @@ public function register(ContainerInterface $container) * * Loads raw or compiled asset information from your bundle.config.json schema file. * Assets are Javascript, CSS, image, and other files used by your site. + * + * @return \UserFrosting\Assets\Assets */ $container['assets'] = function ($c) { $config = $c->config; @@ -152,6 +159,7 @@ public function register(ContainerInterface $container) /** * Cache service. * + * @throws \Exception If cache handler is not supported * @return \Illuminate\Cache\Repository */ $container['cache'] = function ($c) { @@ -180,16 +188,19 @@ public function register(ContainerInterface $container) * Middleware to check environment. * * @todo We should cache the results of this, the first time that it succeeds. + * + * @return \UserFrosting\Sprinkle\Core\Util\CheckEnvironment */ $container['checkEnvironment'] = function ($c) { - $checkEnvironment = new CheckEnvironment($c->view, $c->locator, $c->cache); - return $checkEnvironment; + return new CheckEnvironment($c->view, $c->locator, $c->cache); }; /** * Class mapper. * * Creates an abstraction on top of class names to allow extending them in sprinkles. + * + * @return \UserFrosting\Sprinkle\Core\Util\ClassMapper */ $container['classMapper'] = function ($c) { $classMapper = new ClassMapper(); @@ -203,6 +214,8 @@ public function register(ContainerInterface $container) * Site config service (separate from Slim settings). * * Will attempt to automatically determine which config file(s) to use based on the value of the UF_MODE environment variable. + * + * @return \UserFrosting\Support\Repository\Repository */ $container['config'] = function ($c) { // Grab any relevant dotenv variables from the .env file @@ -251,6 +264,8 @@ public function register(ContainerInterface $container) * Initialize CSRF guard middleware. * * @see https://github.com/slimphp/Slim-Csrf + * @throws BadRequestException + * @return \Slim\Csrf\Guard */ $container['csrf'] = function ($c) { $csrfKey = $c->config['session.keys.csrf']; @@ -280,6 +295,7 @@ public function register(ContainerInterface $container) * Initialize Eloquent Capsule, which provides the database layer for UF. * * @todo construct the individual objects rather than using the facade + * @return \Illuminate\Database\Capsule\Manager */ $container['db'] = function ($c) { $config = $c->config; @@ -324,6 +340,8 @@ public function register(ContainerInterface $container) * Debug logging with Monolog. * * Extend this service to push additional handlers onto the 'debug' log stack. + * + * @return \Monolog\Logger */ $container['debugLogger'] = function ($c) { $logger = new Logger('debug'); @@ -342,6 +360,8 @@ public function register(ContainerInterface $container) /** * Custom error-handler for recoverable errors. + * + * @return \UserFrosting\Sprinkle\Core\Error\ExceptionHandlerManager */ $container['errorHandler'] = function ($c) { $settings = $c->settings; @@ -364,6 +384,8 @@ public function register(ContainerInterface $container) * Error logging with Monolog. * * Extend this service to push additional handlers onto the 'error' log stack. + * + * @return \Monolog\Logger */ $container['errorLogger'] = function ($c) { $log = new Logger('errors'); @@ -384,6 +406,8 @@ public function register(ContainerInterface $container) * Factory service with FactoryMuffin. * * Provide access to factories for the rapid creation of objects for the purpose of testing + * + * @return \League\FactoryMuffin\FactoryMuffin */ $container['factory'] = function ($c) { @@ -404,6 +428,9 @@ public function register(ContainerInterface $container) /** * Builds search paths for locales in all Sprinkles. + * + * @throws \UnexpectedValueException + * @return \UserFrosting\I18n\LocalePathBuilder */ $container['localePathBuilder'] = function ($c) { $config = $c->config; @@ -460,6 +487,8 @@ public function register(ContainerInterface $container) /** * Mail service. + * + * @return \UserFrosting\Sprinkle\Core\Mail\Mailer */ $container['mailer'] = function ($c) { $mailer = new Mailer($c->mailLogger, $c->config['mail']); @@ -477,6 +506,8 @@ public function register(ContainerInterface $container) * * PHPMailer will use this to log SMTP activity. * Extend this service to push additional handlers onto the 'mail' log stack. + * + * @return \Monolog\Logger */ $container['mailLogger'] = function ($c) { $log = new Logger('mail'); @@ -496,6 +527,8 @@ public function register(ContainerInterface $container) * Migrator service. * * This service handles database migration operations + * + * @return \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator */ $container['migrator'] = function ($c) { $migrator = new Migrator( @@ -515,6 +548,8 @@ public function register(ContainerInterface $container) /** * Error-handler for 404 errors. Notice that we manually create a UserFrosting NotFoundException, * and a NotFoundExceptionHandler. This lets us pass through to the UF error handling system. + * + * @return callable */ $container['notFoundHandler'] = function ($c) { return function ($request, $response) use ($c) { @@ -527,6 +562,8 @@ public function register(ContainerInterface $container) /** * Error-handler for PHP runtime errors. Notice that we just pass this through to our general-purpose * error-handling service. + * + * @return \UserFrosting\Sprinkle\Core\Error\ExceptionHandlerManager */ $container['phpErrorHandler'] = function ($c) { return $c->errorHandler; @@ -536,6 +573,8 @@ public function register(ContainerInterface $container) * Laravel query logging with Monolog. * * Extend this service to push additional handlers onto the 'query' log stack. + * + * @return \Monolog\Logger */ $container['queryLogger'] = function ($c) { $logger = new Logger('query'); @@ -554,6 +593,8 @@ public function register(ContainerInterface $container) /** * Override Slim's default router with the UF router. + * + * @return \UserFrosting\Sprinkle\Core\Router */ $container['router'] = function ($c) { $routerCacheFile = false; @@ -566,6 +607,9 @@ public function register(ContainerInterface $container) /** * Start the PHP session, with the name and parameters specified in the configuration file. + * + * @throws \Exception + * @return \UserFrosting\Session\Session */ $container['session'] = function ($c) { $config = $c->config; @@ -593,6 +637,8 @@ public function register(ContainerInterface $container) * Request throttler. * * Throttles (rate-limits) requests of a predefined type, with rules defined in site config. + * + * @return \UserFrosting\Sprinkle\Core\Throttle\Throttler */ $container['throttler'] = function ($c) { $throttler = new Throttler($c->classMapper); @@ -615,6 +661,8 @@ public function register(ContainerInterface $container) /** * Translation service, for translating message tokens. + * + * @return \UserFrosting\I18n\MessageTranslator */ $container['translator'] = function ($c) { // Load the translations @@ -631,6 +679,8 @@ public function register(ContainerInterface $container) * Set up Twig as the view, adding template paths for all sprinkles and the Slim Twig extension. * * Also adds the UserFrosting core Twig extension, which provides additional functions, filters, global variables, etc. + * + * @return \Slim\Views\Twig */ $container['view'] = function ($c) { $templatePaths = $c->locator->findResources('templates://', true, false); diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index adfe6933f..42640b8b4 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -29,6 +29,8 @@ public function register(ContainerInterface $container) { /** * Set up the event dispatcher, required by Sprinkles to hook into the UF lifecycle. + * + * @return \RocketTheme\Toolbox\Event\EventDispatcher */ $container['eventDispatcher'] = function ($c) { return new EventDispatcher(); @@ -36,8 +38,9 @@ public function register(ContainerInterface $container) /** * Path/file locator service. - * + * * Register custom streams for the application, and add paths for app-level streams. + * * @return \UserFrosting\UniformResourceLocator\ResourceLocator */ $container['locator'] = function ($c) { @@ -70,10 +73,11 @@ public function register(ContainerInterface $container) /** * Set up sprinkle manager service. + * + * @return \UserFrosting\System\Sprinkle\SprinkleManager */ $container['sprinkleManager'] = function ($c) { - $sprinkleManager = new SprinkleManager($c); - return $sprinkleManager; + return new SprinkleManager($c); }; } } From 36affb05e596fde37219be07819807a8be55eb8b Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 17 Oct 2018 22:29:39 -0400 Subject: [PATCH 091/237] Code style + doc + type hint + misc class fixes (ref #711) --- .../account/src/Account/Registration.php | 9 +- .../account/src/Authenticate/AuthGuard.php | 20 +- .../src/Authenticate/Authenticator.php | 25 +- .../account/src/Authenticate/Hasher.php | 6 +- .../Authorize/AccessConditionExpression.php | 3 +- .../src/Authorize/AuthorizationManager.php | 9 +- .../Authorize/ParserNodeFunctionEvaluator.php | 13 +- .../account/src/Bakery/CreateAdminUser.php | 82 +++--- .../src/Controller/AccountController.php | 25 +- .../Migrations/v400/ActivitiesTable.php | 6 +- .../Database/Migrations/v400/GroupsTable.php | 6 +- .../Migrations/v400/PasswordResetsTable.php | 6 +- .../Migrations/v400/PermissionRolesTable.php | 6 +- .../Migrations/v400/PermissionsTable.php | 6 +- .../Migrations/v400/PersistencesTable.php | 6 +- .../Migrations/v400/RoleUsersTable.php | 6 +- .../Database/Migrations/v400/RolesTable.php | 6 +- .../Database/Migrations/v400/UsersTable.php | 6 +- .../Migrations/v400/VerificationsTable.php | 6 +- .../account/src/Database/Models/Activity.php | 19 +- .../account/src/Database/Models/Group.php | 3 +- .../src/Database/Models/PasswordReset.php | 8 +- .../src/Database/Models/Permission.php | 18 +- .../account/src/Database/Models/Role.php | 14 +- .../account/src/Database/Models/User.php | 16 +- .../src/Database/Models/Verification.php | 14 +- .../AuthCompromisedExceptionHandler.php | 2 +- .../Handler/AuthExpiredExceptionHandler.php | 7 +- .../src/Log/UserActivityDatabaseHandler.php | 2 +- .../account/src/Log/UserActivityProcessor.php | 6 +- .../Repository/PasswordResetRepository.php | 4 +- .../src/Repository/TokenRepository.php | 2 +- .../src/Repository/VerificationRepository.php | 4 +- .../account/src/Twig/AccountExtension.php | 14 +- app/sprinkles/account/src/Util/Util.php | 9 +- .../account/tests/Unit/FactoriesTest.php | 1 - .../account/tests/Unit/HasherTest.php | 14 +- .../account/tests/Unit/RegistrationTest.php | 2 - .../src/Controller/ActivityController.php | 25 +- .../admin/src/Controller/AdminController.php | 43 +-- .../admin/src/Controller/GroupController.php | 183 +++++++++---- .../src/Controller/PermissionController.php | 77 +++--- .../admin/src/Controller/RoleController.php | 221 ++++++++++----- .../admin/src/Controller/UserController.php | 257 ++++++++++++------ .../admin/src/Sprunje/ActivitySprunje.php | 11 +- .../admin/src/Sprunje/GroupSprunje.php | 4 +- .../admin/src/Sprunje/PermissionSprunje.php | 17 +- .../src/Sprunje/PermissionUserSprunje.php | 4 +- .../admin/src/Sprunje/RoleSprunje.php | 9 +- .../src/Sprunje/UserPermissionSprunje.php | 4 +- .../admin/src/Sprunje/UserSprunje.php | 29 +- .../admin/tests/Integration/SprunjeTests.php | 2 - app/sprinkles/core/config/testing.php | 2 +- app/sprinkles/core/src/Alert/AlertStream.php | 22 +- .../core/src/Alert/CacheAlertStream.php | 39 ++- .../core/src/Alert/SessionAlertStream.php | 31 +-- app/sprinkles/core/src/Bakery/BakeCommand.php | 8 +- .../core/src/Bakery/ClearCacheCommand.php | 8 +- .../core/src/Bakery/DebugCommand.php | 18 +- .../core/src/Bakery/MigrateCommand.php | 11 +- .../core/src/Bakery/MigrateRefreshCommand.php | 5 +- .../core/src/Bakery/MigrateResetCommand.php | 13 +- .../src/Bakery/MigrateRollbackCommand.php | 5 +- .../core/src/Bakery/MigrateStatusCommand.php | 5 +- .../core/src/Bakery/RouteListCommand.php | 4 +- app/sprinkles/core/src/Bakery/SeedCommand.php | 4 +- .../core/src/Bakery/SeedListCommand.php | 4 +- .../core/src/Bakery/SetupCommand.php | 4 +- .../core/src/Bakery/SetupDbCommand.php | 4 +- .../core/src/Bakery/SetupEnvCommand.php | 4 +- .../core/src/Bakery/SetupSmtpCommand.php | 4 +- .../core/src/Controller/CoreController.php | 18 ++ app/sprinkles/core/src/Database/Builder.php | 37 +-- .../core/src/Database/EloquentBuilder.php | 10 +- app/sprinkles/core/src/Database/Migration.php | 9 +- .../Migrations/v400/SessionsTable.php | 6 +- .../Migrations/v400/ThrottlesTable.php | 6 +- .../Migrator/DatabaseMigrationRepository.php | 13 +- .../Migrator/MigrationDependencyAnalyser.php | 56 ++-- .../Migrator/MigrationLocatorInterface.php | 4 +- .../Migrator/MigrationRepositoryInterface.php | 8 +- .../MigrationRollbackDependencyAnalyser.php | 20 +- .../core/src/Database/Migrator/Migrator.php | 6 - .../Models/Concerns/HasRelationships.php | 27 +- .../core/src/Database/Models/Model.php | 13 +- .../Relations/BelongsToManyConstrained.php | 15 +- .../Relations/BelongsToManyThrough.php | 11 +- .../Relations/BelongsToManyUnique.php | 2 +- .../Database/Relations/Concerns/Syncable.php | 9 +- .../Database/Relations/Concerns/Unique.php | 59 ++-- .../Database/Relations/HasManySyncable.php | 2 +- .../Database/Relations/MorphManySyncable.php | 2 +- .../Database/Relations/MorphToManyUnique.php | 2 +- .../core/src/Database/Seeder/BaseSeed.php | 10 +- .../src/Database/Seeder/SeedInterface.php | 3 + .../core/src/Database/Seeder/Seeder.php | 17 +- .../src/Error/ExceptionHandlerManager.php | 10 +- .../src/Error/Handler/ExceptionHandler.php | 19 +- .../Handler/ExceptionHandlerInterface.php | 24 +- .../Error/Handler/HttpExceptionHandler.php | 3 +- .../Handler/NotFoundExceptionHandler.php | 5 +- .../core/src/Error/Renderer/ErrorRenderer.php | 12 +- .../Error/Renderer/ErrorRendererInterface.php | 12 +- .../core/src/Error/Renderer/HtmlRenderer.php | 5 +- .../core/src/Error/Renderer/JsonRenderer.php | 2 +- .../src/Error/Renderer/PlainTextRenderer.php | 4 + .../src/Error/Renderer/WhoopsRenderer.php | 29 +- .../Http/Concerns/DeterminesContentType.php | 1 + .../core/src/Log/DatabaseHandler.php | 11 +- app/sprinkles/core/src/Log/MixedFormatter.php | 2 +- app/sprinkles/core/src/Mail/MailMessage.php | 2 + .../core/src/Mail/StaticMailMessage.php | 4 +- .../core/src/Mail/TwigMailMessage.php | 16 +- app/sprinkles/core/src/Sprunje/Sprunje.php | 27 +- .../core/src/Throttle/ThrottleRule.php | 12 +- app/sprinkles/core/src/Throttle/Throttler.php | 11 +- app/sprinkles/core/src/Twig/CacheHelper.php | 3 +- app/sprinkles/core/src/Twig/CoreExtension.php | 4 +- app/sprinkles/core/src/Util/Captcha.php | 18 +- .../core/src/Util/CheckEnvironment.php | 31 ++- app/sprinkles/core/src/Util/ClassMapper.php | 2 +- .../core/src/Util/EnvironmentInfo.php | 6 +- .../core/src/Util/ShutdownHandler.php | 4 +- .../core/tests/DatabaseTransactions.php | 2 - .../Integration/DatabaseMigratorTest.php | 2 - .../core/tests/Integration/DatabaseTests.php | 82 +++++- .../Migrations/DeprecatedClassTable.php | 6 - .../Migrations/UnfulfillableTable.php | 6 +- .../one/CreatePasswordResetsTable.php | 6 +- .../Migrations/one/CreateUsersTable.php | 5 +- .../Migrations/two/CreateFlightsTable.php | 6 +- .../tests/Integration/Seeder/SeederTests.php | 2 - app/sprinkles/core/tests/RefreshDatabase.php | 8 - app/sprinkles/core/tests/Unit/RouterTest.php | 2 - app/system/Bakery/Bakery.php | 14 +- app/system/Bakery/BaseCommand.php | 2 +- app/system/Bakery/Command/BuildAssets.php | 17 +- app/system/Bakery/Command/Test.php | 6 +- app/system/Bakery/ConfirmableTrait.php | 5 +- app/system/Bakery/DatabaseTest.php | 2 - app/system/Bakery/Migration.php | 6 +- app/system/Facade.php | 29 +- app/system/ServicesProvider.php | 2 +- app/system/SlimAppEvent.php | 6 + app/system/Sprinkle/Sprinkle.php | 1 - app/system/Sprinkle/SprinkleManager.php | 8 +- app/tests/DatabaseTransactions.php | 2 - app/tests/TestCase.php | 13 +- app/tests/Unit/ExampleTest.php | 2 - 149 files changed, 1343 insertions(+), 1035 deletions(-) diff --git a/app/sprinkles/account/src/Account/Registration.php b/app/sprinkles/account/src/Account/Registration.php index 2b4d26427..7d5a36dbe 100644 --- a/app/sprinkles/account/src/Account/Registration.php +++ b/app/sprinkles/account/src/Account/Registration.php @@ -53,7 +53,7 @@ class Registration protected $defaultRoles = []; /** - * @var array $requiredProperties The minimum info required to register a new user + * @var array $requiredProperties The minimum info required to register a new user */ protected $requiredProperties = [ 'user_name', @@ -78,9 +78,9 @@ public function __construct(ContainerInterface $ci, $userdata = []) } /** - * Register a new user + * Register a new user * - * @return \UserFrosting\Sprinkle\Account\Database\Models\User The created user + * @return \UserFrosting\Sprinkle\Account\Database\Models\User The created user */ public function register() { @@ -203,11 +203,9 @@ public function emailIsUnique($email) /** * Hash the user password in the userdata array - * @return void */ protected function hashPassword() { - // Hash password $this->userdata['password'] = Password::hash($this->userdata['password']); } @@ -226,7 +224,6 @@ protected function setDefaults() * Send verification email for specified user * * @param User $user The user to send the email for - * @return void */ protected function sendVerificationEmail(User $user) { diff --git a/app/sprinkles/account/src/Authenticate/AuthGuard.php b/app/sprinkles/account/src/Authenticate/AuthGuard.php index efcfaae15..1db38ddd1 100644 --- a/app/sprinkles/account/src/Authenticate/AuthGuard.php +++ b/app/sprinkles/account/src/Authenticate/AuthGuard.php @@ -7,9 +7,8 @@ */ namespace UserFrosting\Sprinkle\Account\Authenticate; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Slim\Http\Body; +use Psr\Http\Message\ServerRequestInterface as Request; +use Psr\Http\Message\ResponseInterface as Response; use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException; /** @@ -27,9 +26,9 @@ class AuthGuard /** * Constructor. * - * @param $authenticator Authenticator The current authentication object. + * @param Authenticator $authenticator The current authentication object. */ - public function __construct($authenticator) + public function __construct(Authenticator $authenticator) { $this->authenticator = $authenticator; } @@ -37,13 +36,12 @@ public function __construct($authenticator) /** * Invoke the AuthGuard middleware, throwing an exception if there is no authenticated user in the session. * - * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request - * @param \Psr\Http\Message\ResponseInterface $response PSR7 response - * @param callable $next Next middleware - * - * @return \Psr\Http\Message\ResponseInterface + * @param Request $request PSR7 request + * @param Response $response PSR7 response + * @param callable $next Next middleware + * @return Response */ - public function __invoke($request, $response, $next) + public function __invoke(Request $request, Response $response, $next) { if (!$this->authenticator->check()) { throw new AuthExpiredException(); diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index 5fb89201c..7c3b3415f 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -10,6 +10,7 @@ use Birke\Rememberme\Authenticator as RememberMe; use Birke\Rememberme\Storage\PDOStorage as RememberMePDO; use Birke\Rememberme\Triplet as RememberMeTriplet; +use Illuminate\Cache\Repository as Cache; use Illuminate\Database\Capsule\Manager as Capsule; use UserFrosting\Session\Session; use UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountDisabledException; @@ -21,6 +22,7 @@ use UserFrosting\Sprinkle\Account\Database\Models\User; use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Core\Util\ClassMapper; +use UserFrosting\Support\Repository\Repository as Config; /** * Handles authentication tasks. @@ -83,9 +85,9 @@ class Authenticator * @param ClassMapper $classMapper Maps generic class identifiers to specific class names. * @param Session $session The session wrapper object that will store the user's id. * @param Config $config Config object that contains authentication settings. - * @param mixed $cache Cache service instance + * @param Cache $cache Cache service instance */ - public function __construct(ClassMapper $classMapper, Session $session, $config, $cache) + public function __construct(ClassMapper $classMapper, Session $session, Config $config, Cache $cache) { $this->classMapper = $classMapper; $this->session = $session; @@ -123,6 +125,15 @@ public function __construct(ClassMapper $classMapper, Session $session, $config, * Attempts to authenticate a user based on a supplied identity and password. * * If successful, the user's id is stored in session. + * + * @throws InvalidCredentialsException + * @throws AccountDisabledException + * @throws AccountNotVerifiedException + * @param string $identityColumn + * @param string $identityValue + * @param string $password + * @param bool $rememberMe + * @return User */ public function attempt($identityColumn, $identityValue, $password, $rememberMe = false) { @@ -311,8 +322,8 @@ public function viaRemember() /** * Attempt to log in the client from their rememberMe token (in their cookie). * - * @return User|bool If successful, the User object of the remembered user. Otherwise, return false. * @throws AuthCompromisedException The client attempted to log in with an invalid rememberMe token. + * @return User|bool If successful, the User object of the remembered user. Otherwise, return false. */ protected function loginRememberedUser() { @@ -338,8 +349,8 @@ protected function loginRememberedUser() /** * Attempt to log in the client from the session. * - * @return User|null If successful, the User object of the user in session. Otherwise, return null. * @throws AuthExpiredException The client attempted to use an expired rememberMe token. + * @return User|null If successful, the User object of the user in session. Otherwise, return null. */ protected function loginSessionUser() { @@ -407,10 +418,10 @@ protected function validateUserAccount($userId) } /** - * Flush the cache associated with a session id + * Flush the cache associated with a session id * - * @param string $id The session id - * @return bool + * @param string $id The session id + * @return bool */ public function flushSessionCache($id) { diff --git a/app/sprinkles/account/src/Authenticate/Hasher.php b/app/sprinkles/account/src/Authenticate/Hasher.php index e277eef83..ad126c204 100644 --- a/app/sprinkles/account/src/Authenticate/Hasher.php +++ b/app/sprinkles/account/src/Authenticate/Hasher.php @@ -7,6 +7,8 @@ */ namespace UserFrosting\Sprinkle\Account\Authenticate; +use UserFrosting\Sprinkle\Account\Util\HashFailedException; + /** * Password hashing and validation class * @@ -43,10 +45,10 @@ public function getHashType($password) /** * Hashes a plaintext password using bcrypt. * + * @throws HashFailedException * @param string $password the plaintext password. * @param array $options * @return string the hashed password. - * @throws HashFailedException */ public function hash($password, array $options = []) { @@ -67,7 +69,7 @@ public function hash($password, array $options = []) * @param string $password The plaintext password to verify. * @param string $hash The hash to compare against. * @param array $options - * @return boolean True if the password matches, false otherwise. + * @return bool True if the password matches, false otherwise. */ public function verify($password, $hash, array $options = []) { diff --git a/app/sprinkles/account/src/Authorize/AccessConditionExpression.php b/app/sprinkles/account/src/Authorize/AccessConditionExpression.php index dd5647e86..ec9ea2e34 100644 --- a/app/sprinkles/account/src/Authorize/AccessConditionExpression.php +++ b/app/sprinkles/account/src/Authorize/AccessConditionExpression.php @@ -9,12 +9,10 @@ use Monolog\Logger; use PhpParser\Lexer\Emulative as EmulativeLexer; -use PhpParser\Node; use PhpParser\NodeTraverser; use PhpParser\Parser as Parser; use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter; use PhpParser\Error as PhpParserException; -use Psr\Http\Message\ServerRequestInterface as Request; use UserFrosting\Sprinkle\Account\Database\Models\User; /** @@ -65,6 +63,7 @@ class AccessConditionExpression /** * Create a new AccessConditionExpression object. * + * @param ParserNodeFunctionEvaluator $nodeVisitor * @param User $user A user object, which for convenience can be referenced as 'self' in access conditions. * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. * @param bool $debug Set to true if you want debugging information printed to the auth log. diff --git a/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/app/sprinkles/account/src/Authorize/AuthorizationManager.php index def152bfb..2b1ce5acb 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationManager.php @@ -32,6 +32,7 @@ class AuthorizationManager * Create a new AuthorizationManager object. * * @param ContainerInterface $ci The global container object, which holds all your services. + * @param array $callbacks */ public function __construct(ContainerInterface $ci, array $callbacks = []) { @@ -67,11 +68,11 @@ public function getCallbacks() * * Determine if this user has access to the given $slug under the given $params. * - * @param UserFrosting\Sprinkle\Account\Database\Models\User $user + * @param User $user * @param string $slug The permission slug to check for access. - * @param array $params[optional] An array of field names => values, specifying any additional data to provide the authorization module + * @param array $params An array of field names => values, specifying any additional data to provide the authorization module * when determining whether or not this user has access. - * @return boolean True if the user has access, false otherwise. + * @return bool True if the user has access, false otherwise. */ public function checkAccess(User $user, $slug, array $params = []) { @@ -139,7 +140,7 @@ public function checkAccess(User $user, $slug, array $params = []) /** * Remove extraneous information from the permission to reduce verbosity. * - * @param array + * @param array $permissions * @return array */ protected function getPermissionsArrayDebugInfo($permissions) diff --git a/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php b/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php index e8e5cde43..b7244c1ce 100644 --- a/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php +++ b/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php @@ -27,10 +27,12 @@ class ParserNodeFunctionEvaluator extends NodeVisitorAbstract * @var array[callable] An array of callback functions to be used when evaluating a condition expression. */ protected $callbacks; + /** * @var \PhpParser\PrettyPrinter\Standard The PrettyPrinter object to use (initialized in the ctor) */ protected $prettyPrinter; + /** * @var array The parameters to be used when evaluating the methods in the condition expression, as an array. */ @@ -49,11 +51,11 @@ class ParserNodeFunctionEvaluator extends NodeVisitorAbstract /** * Create a new ParserNodeFunctionEvaluator object. * - * @param array $params The parameters to be used when evaluating the methods in the condition expression, as an array. + * @param array $callbacks The parameters to be used when evaluating the methods in the condition expression, as an array. * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. * @param bool $debug Set to true if you want debugging information printed to the auth log. */ - public function __construct($callbacks, $logger, $debug = false) + public function __construct($callbacks, Logger $logger, $debug = false) { $this->callbacks = $callbacks; $this->prettyPrinter = new StandardPrettyPrinter; @@ -140,6 +142,11 @@ public function leaveNode(Node $node) } } + /** + * Set params + * + * @param array $params + */ public function setParams($params) { $this->params = $params; @@ -169,7 +176,7 @@ private function resolveArray($arg) * Resolve a parameter path (e.g. "user.id", "post", etc) into its value. * * @param string $path the name of the parameter to resolve, based on the parameters set in this object. - * @throws Exception the path could not be resolved. Path is malformed or key does not exist. + * @throws \Exception the path could not be resolved. Path is malformed or key does not exist. * @return mixed the value of the specified parameter. */ private function resolveParamPath($path) diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index 913954be1..a88934aff 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -34,7 +34,7 @@ class CreateAdminUser extends BaseCommand ]; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -48,7 +48,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -126,10 +126,10 @@ protected function execute(InputInterface $input, OutputInterface $output) } /** - * Ask for the username and return a valid one + * Ask for the username and return a valid one * - * @param string $username The base/default username - * @return string The validated username + * @param string $username The base/default username + * @return string The validated username */ protected function askUsername($username = '') { @@ -140,10 +140,10 @@ protected function askUsername($username = '') } /** - * Validate the username. + * Validate the username. * - * @param string $username The input - * @return bool Is the username validated ? + * @param string $username The input + * @return bool Is the username validated ? */ protected function validateUsername($username) { @@ -169,10 +169,10 @@ protected function validateUsername($username) } /** - * Ask for the email and return a valid one + * Ask for the email and return a valid one * - * @param string $email The base/default email - * @return string The validated email + * @param string $email The base/default email + * @return string The validated email */ protected function askEmail($email = '') { @@ -183,10 +183,10 @@ protected function askEmail($email = '') } /** - * Validate the email. + * Validate the email. * - * @param string $email The input - * @return bool Is the email validated ? + * @param string $email The input + * @return bool Is the email validated ? */ protected function validateEmail($email) { @@ -206,10 +206,10 @@ protected function validateEmail($email) } /** - * Ask for the first name and return a valid one + * Ask for the first name and return a valid one * - * @param string $firstName The base/default first name - * @return string The validated first name + * @param string $firstName The base/default first name + * @return string The validated first name */ protected function askFirstName($firstName = '') { @@ -220,10 +220,10 @@ protected function askFirstName($firstName = '') } /** - * Validate the first name + * Validate the first name * - * @param string $firstName The input - * @return bool Is the input validated ? + * @param string $firstName The input + * @return bool Is the input validated ? */ protected function validateFirstName($firstName) { @@ -237,10 +237,10 @@ protected function validateFirstName($firstName) } /** - * Ask for the last name and return a valid one + * Ask for the last name and return a valid one * - * @param string $lastName The base/default last name - * @return string The validated last name + * @param string $lastName The base/default last name + * @return string The validated last name */ protected function askLastName($lastName = '') { @@ -251,10 +251,10 @@ protected function askLastName($lastName = '') } /** - * Validate the last name entered is valid + * Validate the last name entered is valid * - * @param string $lastName The lastname - * @return bool Input is valid or not + * @param string $lastName The lastname + * @return bool Input is valid or not */ protected function validateLastName($lastName) { @@ -268,11 +268,11 @@ protected function validateLastName($lastName) } /** - * Ask for the password and return a valid one + * Ask for the password and return a valid one * - * @param string $password The base/default password - * @param bool $requireConfirmation (default true) - * @return string The validated password + * @param string $password The base/default password + * @param bool $requireConfirmation (default true) + * @return string The validated password */ protected function askPassword($password = '', $requireConfirmation = true) { @@ -283,10 +283,10 @@ protected function askPassword($password = '', $requireConfirmation = true) } /** - * Validate password input + * Validate password input * - * @param string $password The input - * @return bool Is the password valid or not + * @param string $password The input + * @return bool Is the password valid or not */ protected function validatePassword($password) { @@ -300,11 +300,11 @@ protected function validatePassword($password) } /** - * Ask for password confirmation + * Ask for password confirmation * - * @param string $passwordToConfirm - * @param bool $requireConfirmation (default true) - * @return bool Is the password confirmed or not + * @param string $passwordToConfirm + * @param bool $requireConfirmation (default true) + * @return bool Is the password confirmed or not */ protected function confirmPassword($passwordToConfirm, $requireConfirmation = true) { @@ -319,11 +319,11 @@ protected function confirmPassword($passwordToConfirm, $requireConfirmation = tr } /** - * Validate the confirmation password + * Validate the confirmation password * - * @param string $password The confirmation - * @param string $passwordToConfirm The password to confirm - * @return bool Is the confirmation password valid or not + * @param string $password The confirmation + * @param string $passwordToConfirm The password to confirm + * @return bool Is the confirmation password valid or not */ protected function validatePasswordConfirmation($password, $passwordToConfirm) { diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index fb15d45c0..3dfd1e191 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -45,10 +45,10 @@ class AccountController extends SimpleController * Route: /account/check-username * Route Name: {none} * Request type: GET + * @throws BadRequestException * @param Request $request * @param Response $response * @param array $args - * @return void */ public function checkUsername(Request $request, Response $response, $args) { @@ -118,7 +118,6 @@ public function checkUsername(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function denyResetPassword(Request $request, Response $response, $args) { @@ -179,7 +178,6 @@ public function denyResetPassword(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function forgotPassword(Request $request, Response $response, $args) { @@ -273,7 +271,6 @@ public function forgotPassword(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function getModalAccountTos(Request $request, Response $response, $args) { @@ -290,7 +287,6 @@ public function getModalAccountTos(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function imageCaptcha(Request $request, Response $response, $args) { @@ -321,7 +317,6 @@ public function imageCaptcha(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function login(Request $request, Response $response, $args) { @@ -416,7 +411,6 @@ public function login(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function logout(Request $request, Response $response, $args) { @@ -441,7 +435,6 @@ public function logout(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function pageForgotPassword(Request $request, Response $response, $args) { @@ -470,10 +463,10 @@ public function pageForgotPassword(Request $request, Response $response, $args) * Route: /account/register * Route Name: register * Request type: GET + * @throws NotFoundException If site registration is disabled * @param Request $request * @param Response $response * @param array $args - * @return void */ public function pageRegister(Request $request, Response $response, $args) { @@ -529,7 +522,6 @@ public function pageRegister(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function pageResendVerification(Request $request, Response $response, $args) { @@ -558,7 +550,6 @@ public function pageResendVerification(Request $request, Response $response, $ar * @param Request $request * @param Response $response * @param array $args - * @return void */ public function pageResetPassword(Request $request, Response $response, $args) { @@ -592,7 +583,6 @@ public function pageResetPassword(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function pageSetPassword(Request $request, Response $response, $args) { @@ -624,10 +614,10 @@ public function pageSetPassword(Request $request, Response $response, $args) * Route: /account/settings * Route Name: {none} * Request type: GET + * @throws ForbiddenException If user is not authozied to access page * @param Request $request * @param Response $response * @param array $args - * @return void */ public function pageSettings(Request $request, Response $response, $args) { @@ -681,7 +671,6 @@ public function pageSettings(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function pageSignIn(Request $request, Response $response, $args) { @@ -726,7 +715,6 @@ public function pageSignIn(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function profile(Request $request, Response $response, $args) { @@ -817,10 +805,10 @@ public function profile(Request $request, Response $response, $args) * Route: /account/register * Route Name: {none} * Request type: POST + * @throws SpammyRequestException * @param Request $request * @param Response $response * @param array $args - * @return void */ public function register(Request $request, Response $response, $args) { @@ -943,7 +931,6 @@ public function register(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function resendVerification(Request $request, Response $response, $args) { @@ -1039,7 +1026,6 @@ public function resendVerification(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function setPassword(Request $request, Response $response, $args) { @@ -1115,7 +1101,6 @@ public function setPassword(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function settings(Request $request, Response $response, $args) { @@ -1216,7 +1201,6 @@ public function settings(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function suggestUsername(Request $request, Response $response, $args) { @@ -1250,7 +1234,6 @@ public function suggestUsername(Request $request, Response $response, $args) * @param Request $request * @param Response $response * @param array $args - * @return void */ public function verify(Request $request, Response $response, $args) { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php index dc075adc5..bf38ca09b 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php @@ -9,20 +9,18 @@ use UserFrosting\Sprinkle\Core\Database\Migration; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; /** * Sessions table migration * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class ActivitiesTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -45,7 +43,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php index 1a6dc6f96..d2c9ce418 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Account\Database\Models\Group; use UserFrosting\Sprinkle\Core\Database\Migration; @@ -18,13 +17,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class GroupsTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -73,7 +71,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php index 7eb9fd7df..68518e196 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration; /** @@ -17,13 +16,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class passwordResetsTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -48,7 +46,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php index ee7f6c821..238c5fc12 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration; /** @@ -17,13 +16,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class PermissionRolesTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -46,7 +44,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php index 2a6406fe4..a4fc7595d 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php @@ -24,7 +24,7 @@ class PermissionsTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ static public $dependencies = [ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable', @@ -32,7 +32,7 @@ class PermissionsTable extends Migration ]; /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -245,7 +245,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php index d3b55af24..07834f3fc 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration; /** @@ -17,13 +16,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class PersistencesTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -48,7 +46,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php index 51ced3dba..f36ecfc1d 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration; /** @@ -17,13 +16,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class RoleUsersTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -46,7 +44,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php index 28c55230c..aecf42654 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Account\Database\Models\Role; use UserFrosting\Sprinkle\Core\Database\Migration; @@ -18,13 +17,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class RolesTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -69,7 +67,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php b/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php index 4b0626bbd..4af640e90 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration; /** @@ -17,13 +16,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class UsersTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -60,7 +58,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php index bbed6e588..54035c85e 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration; /** @@ -17,13 +16,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class VerificationsTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -48,7 +46,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/account/src/Database/Models/Activity.php b/app/sprinkles/account/src/Database/Models/Activity.php index d5be589ec..75d1109e6 100644 --- a/app/sprinkles/account/src/Database/Models/Activity.php +++ b/app/sprinkles/account/src/Database/Models/Activity.php @@ -8,6 +8,7 @@ namespace UserFrosting\Sprinkle\Account\Database\Models; use Illuminate\Database\Capsule\Manager as Capsule; +use Illuminate\Database\Query\Builder; use UserFrosting\Sprinkle\Core\Database\Models\Model; /** @@ -38,8 +39,10 @@ class Activity extends Model /** * Joins the activity's user, so we can do things like sort, search, paginate, etc. + * + * @param Builder $query */ - public function scopeJoinUser($query) + public function scopeJoinUser(Builder $query) { $query = $query->select('activities.*'); @@ -51,9 +54,10 @@ public function scopeJoinUser($query) /** * Add clauses to select the most recent event of each type for each user, to the query. * - * @return \Illuminate\Database\Query\Builder + * @param Builder $query + * @return Builder */ - public function scopeMostRecentEvents($query) + public function scopeMostRecentEvents(Builder $query) { return $query->select('user_id', 'event_type', Capsule::raw('MAX(occurred_at) as occurred_at')) ->groupBy('user_id') @@ -63,10 +67,11 @@ public function scopeMostRecentEvents($query) /** * Add clauses to select the most recent event of a given type for each user, to the query. * + * @param Builder $query * @param string $type The type of event, matching the `event_type` field in the user_event table. - * @return \Illuminate\Database\Query\Builder + * @return Builder */ - public function scopeMostRecentEventsByType($query, $type) + public function scopeMostRecentEventsByType(Builder$query, $type) { return $query->select('user_id', Capsule::raw('MAX(occurred_at) as occurred_at')) ->where('type', $type) @@ -75,10 +80,12 @@ public function scopeMostRecentEventsByType($query, $type) /** * Get the user associated with this activity. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id'); diff --git a/app/sprinkles/account/src/Database/Models/Group.php b/app/sprinkles/account/src/Database/Models/Group.php index f10e066c1..993c15f79 100644 --- a/app/sprinkles/account/src/Database/Models/Group.php +++ b/app/sprinkles/account/src/Database/Models/Group.php @@ -7,7 +7,6 @@ */ namespace UserFrosting\Sprinkle\Account\Database\Models; -use Illuminate\Database\Capsule\Manager as Capsule; use UserFrosting\Sprinkle\Core\Database\Models\Model; /** @@ -61,7 +60,7 @@ public function delete() */ public function users() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->hasMany($classMapper->getClassMapping('user'), 'group_id'); diff --git a/app/sprinkles/account/src/Database/Models/PasswordReset.php b/app/sprinkles/account/src/Database/Models/PasswordReset.php index ac8a930d2..8cf7d00bc 100644 --- a/app/sprinkles/account/src/Database/Models/PasswordReset.php +++ b/app/sprinkles/account/src/Database/Models/PasswordReset.php @@ -7,7 +7,6 @@ */ namespace UserFrosting\Sprinkle\Account\Database\Models; -use Illuminate\Database\Capsule\Manager as Capsule; use UserFrosting\Sprinkle\Core\Database\Models\Model; /** @@ -42,7 +41,7 @@ class PasswordReset extends Model public $timestamps = true; /** - * Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted. + * @var string Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted. */ protected $token; @@ -56,6 +55,7 @@ public function getToken() /** * @param string $value + * @return self */ public function setToken($value) { @@ -65,10 +65,12 @@ public function setToken($value) /** * Get the user associated with this reset request. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id'); diff --git a/app/sprinkles/account/src/Database/Models/Permission.php b/app/sprinkles/account/src/Database/Models/Permission.php index 463af8d5a..37a504527 100644 --- a/app/sprinkles/account/src/Database/Models/Permission.php +++ b/app/sprinkles/account/src/Database/Models/Permission.php @@ -7,7 +7,7 @@ */ namespace UserFrosting\Sprinkle\Account\Database\Models; -use Illuminate\Database\Capsule\Manager as Capsule; +use Illuminate\Database\Eloquent\Builder; use UserFrosting\Sprinkle\Core\Database\Models\Model; /** @@ -61,7 +61,7 @@ public function delete() */ public function roles() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsToMany($classMapper->getClassMapping('role'), 'permission_roles', 'permission_id', 'role_id')->withTimestamps(); @@ -70,11 +70,11 @@ public function roles() /** * Query scope to get all permissions assigned to a specific role. * - * @param \Illuminate\Database\Eloquent\Builder $query + * @param Builder $query * @param int $roleId - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ - public function scopeForRole($query, $roleId) + public function scopeForRole(Builder $query, $roleId) { return $query->join('permission_roles', function ($join) use ($roleId) { $join->on('permission_roles.permission_id', 'permissions.id') @@ -85,11 +85,11 @@ public function scopeForRole($query, $roleId) /** * Query scope to get all permissions NOT associated with a specific role. * - * @param \Illuminate\Database\Eloquent\Builder $query + * @param Builder $query * @param int $roleId - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ - public function scopeNotForRole($query, $roleId) + public function scopeNotForRole(Builder $query, $roleId) { return $query->join('permission_roles', function ($join) use ($roleId) { $join->on('permission_roles.permission_id', 'permissions.id') @@ -104,7 +104,7 @@ public function scopeNotForRole($query, $roleId) */ public function users() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsToManyThrough( diff --git a/app/sprinkles/account/src/Database/Models/Role.php b/app/sprinkles/account/src/Database/Models/Role.php index ce9cb8cad..e8f12199f 100644 --- a/app/sprinkles/account/src/Database/Models/Role.php +++ b/app/sprinkles/account/src/Database/Models/Role.php @@ -7,7 +7,7 @@ */ namespace UserFrosting\Sprinkle\Account\Database\Models; -use Illuminate\Database\Capsule\Manager as Capsule; +use Illuminate\Database\Eloquent\Builder; use UserFrosting\Sprinkle\Core\Database\Models\Model; /** @@ -60,7 +60,7 @@ public function delete() */ public static function getDefaultSlugs() { - /** @var UserFrosting\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = static::$ci->config; return array_map('trim', array_keys($config['site.registration.user_defaults.roles'], true)); @@ -71,7 +71,7 @@ public static function getDefaultSlugs() */ public function permissions() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsToMany($classMapper->getClassMapping('permission'), 'permission_roles', 'role_id', 'permission_id')->withTimestamps(); @@ -80,11 +80,11 @@ public function permissions() /** * Query scope to get all roles assigned to a specific user. * - * @param \Illuminate\Database\Eloquent\Builder $query + * @param Builder $query * @param int $userId - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ - public function scopeForUser($query, $userId) + public function scopeForUser(Builder $query, $userId) { return $query->join('role_users', function ($join) use ($userId) { $join->on('role_users.role_id', 'roles.id') @@ -97,7 +97,7 @@ public function scopeForUser($query, $userId) */ public function users() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsToMany($classMapper->getClassMapping('user'), 'role_users', 'role_id', 'user_id'); diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index a81db1680..8771738d6 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -8,6 +8,7 @@ namespace UserFrosting\Sprinkle\Account\Database\Models; use Carbon\Carbon; +use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletes; use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Core\Database\Models\Model; @@ -109,6 +110,7 @@ class User extends Model * We add relations here so that Twig will be able to find them. * See http://stackoverflow.com/questions/29514081/cannot-access-eloquent-attributes-on-twig/35908957#35908957 * Every property in __get must also be implemented here for Twig to recognize it. + * * @param string $name the name of the property to check. * @return bool true if the property is defined, false otherwise. */ @@ -128,8 +130,8 @@ public function __isset($name) /** * Get a property for this object. * - * @param string $name the name of the property to retrieve. * @throws \Exception the property does not exist for this object. + * @param string $name the name of the property to retrieve. * @return string the associated property. */ public function __get($name) @@ -445,11 +447,11 @@ public function roles() /** * Query scope to get all users who have a specific role. * - * @param \Illuminate\Database\Eloquent\Builder $query + * @param Builder $query * @param int $roleId - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ - public function scopeForRole($query, $roleId) + public function scopeForRole(Builder $query, $roleId) { return $query->join('role_users', function ($join) use ($roleId) { $join->on('role_users.user_id', 'users.id') @@ -460,10 +462,10 @@ public function scopeForRole($query, $roleId) /** * Joins the user's most recent activity directly, so we can do things like sort, search, paginate, etc. * - * @param \Illuminate\Database\Eloquent\Builder $query - * @return \Illuminate\Database\Eloquent\Builder + * @param Builder $query + * @return Builder */ - public function scopeJoinLastActivity($query) + public function scopeJoinLastActivity(Builder $query) { $query = $query->select('users.*'); diff --git a/app/sprinkles/account/src/Database/Models/Verification.php b/app/sprinkles/account/src/Database/Models/Verification.php index cd5166dae..cb897acf9 100644 --- a/app/sprinkles/account/src/Database/Models/Verification.php +++ b/app/sprinkles/account/src/Database/Models/Verification.php @@ -7,7 +7,6 @@ */ namespace UserFrosting\Sprinkle\Account\Database\Models; -use Illuminate\Database\Capsule\Manager as Capsule; use UserFrosting\Sprinkle\Core\Database\Models\Model; /** @@ -42,15 +41,22 @@ class Verification extends Model public $timestamps = true; /** - * Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted. + * @var string Stores the raw (unhashed) token when created, so that it can be emailed out to the user. NOT persisted. */ protected $token; + /** + * @return string + */ public function getToken() { return $this->token; } + /** + * @param string $value + * @return self + */ public function setToken($value) { $this->token = $value; @@ -59,10 +65,12 @@ public function setToken($value) /** * Get the user associated with this verification request. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $this->belongsTo($classMapper->getClassMapping('user'), 'user_id'); diff --git a/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php b/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php index 330ca65a6..ff7bbc0cd 100644 --- a/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php +++ b/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php @@ -20,7 +20,7 @@ class AuthCompromisedExceptionHandler extends HttpExceptionHandler /** * Render a generic, user-friendly response without sensitive debugging information. * - * @return ResponseInterface + * @return \Psr\Http\Message\ResponseInterface */ public function renderGenericResponse() { diff --git a/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php b/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php index c651f77df..9ed1de0e9 100644 --- a/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php +++ b/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php @@ -7,6 +7,7 @@ */ namespace UserFrosting\Sprinkle\Account\Error\Handler; +use Psr\Http\Message\ResponseInterface; use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler; /** @@ -19,6 +20,8 @@ class AuthExpiredExceptionHandler extends HttpExceptionHandler { /** * Custom handling for requests that did not pass authentication. + * + * @return ResponseInterface */ public function handle() { @@ -33,11 +36,11 @@ public function handle() $path = $uri->getPath(); $query = $uri->getQuery(); $fragment = $uri->getFragment(); - + $path = $path . ($query ? '?' . $query : '') . ($fragment ? '#' . $fragment : ''); - + $loginPage = $this->ci->router->pathFor('login', [], [ 'redirect' => $path ]); diff --git a/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php b/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php index d7ceeef74..973d5ccd9 100644 --- a/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php +++ b/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php @@ -17,7 +17,7 @@ class UserActivityDatabaseHandler extends DatabaseHandler { /** - * {@inheritDoc} + * {@inheritdoc} */ protected function write(array $record) { diff --git a/app/sprinkles/account/src/Log/UserActivityProcessor.php b/app/sprinkles/account/src/Log/UserActivityProcessor.php index 257527010..c6cdf3354 100644 --- a/app/sprinkles/account/src/Log/UserActivityProcessor.php +++ b/app/sprinkles/account/src/Log/UserActivityProcessor.php @@ -7,8 +7,6 @@ */ namespace UserFrosting\Sprinkle\Account\Log; -use Monolog\Logger; - /** * Monolog processor for constructing the user activity message. * @@ -29,6 +27,10 @@ public function __construct($userId) $this->userId = $userId; } + /** + * @param array $record + * @return array + */ public function __invoke(array $record) { $additionalFields = [ diff --git a/app/sprinkles/account/src/Repository/PasswordResetRepository.php b/app/sprinkles/account/src/Repository/PasswordResetRepository.php index 2dcffd3c2..a72446f24 100644 --- a/app/sprinkles/account/src/Repository/PasswordResetRepository.php +++ b/app/sprinkles/account/src/Repository/PasswordResetRepository.php @@ -18,12 +18,12 @@ class PasswordResetRepository extends TokenRepository { /** - * {@inheritDoc} + * {@inheritdoc} */ protected $modelIdentifier = 'password_reset'; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function updateUser($user, $args) { diff --git a/app/sprinkles/account/src/Repository/TokenRepository.php b/app/sprinkles/account/src/Repository/TokenRepository.php index a2994396b..25b8b8afb 100644 --- a/app/sprinkles/account/src/Repository/TokenRepository.php +++ b/app/sprinkles/account/src/Repository/TokenRepository.php @@ -21,7 +21,6 @@ */ abstract class TokenRepository { - /** * @var ClassMapper */ @@ -224,6 +223,7 @@ protected function generateRandomToken($gen = null) * * This method is called during complete(), and is a way for concrete implementations to modify the user. * @param User $user the user object to modify. + * @param mixed[] $args * @return mixed[] $args the list of parameters that were supplied to the call to `complete()` */ abstract protected function updateUser($user, $args); diff --git a/app/sprinkles/account/src/Repository/VerificationRepository.php b/app/sprinkles/account/src/Repository/VerificationRepository.php index b0cf0486f..e461c1a55 100644 --- a/app/sprinkles/account/src/Repository/VerificationRepository.php +++ b/app/sprinkles/account/src/Repository/VerificationRepository.php @@ -16,12 +16,12 @@ class VerificationRepository extends TokenRepository { /** - * {@inheritDoc} + * {@inheritdoc} */ protected $modelIdentifier = 'verification'; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function updateUser($user, $args) { diff --git a/app/sprinkles/account/src/Twig/AccountExtension.php b/app/sprinkles/account/src/Twig/AccountExtension.php index 12bacba5a..e74f7991a 100644 --- a/app/sprinkles/account/src/Twig/AccountExtension.php +++ b/app/sprinkles/account/src/Twig/AccountExtension.php @@ -8,8 +8,7 @@ namespace UserFrosting\Sprinkle\Account\Twig; use Interop\Container\ContainerInterface; -use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; -use Slim\Http\Uri; +use UserFrosting\Support\Repository\Repository as Config; /** * Extends Twig functionality for the Account sprinkle. @@ -18,10 +17,19 @@ */ class AccountExtension extends \Twig_Extension implements \Twig_Extension_GlobalsInterface { - + /** + * @var ContainerInterface + */ protected $services; + + /** + * @var Config + */ protected $config; + /** + * @param ContainerInterface $services + */ public function __construct(ContainerInterface $services) { $this->services = $services; diff --git a/app/sprinkles/account/src/Util/Util.php b/app/sprinkles/account/src/Util/Util.php index 6452990c6..5b9c42301 100644 --- a/app/sprinkles/account/src/Util/Util.php +++ b/app/sprinkles/account/src/Util/Util.php @@ -7,6 +7,7 @@ */ namespace UserFrosting\Sprinkle\Account\Util; +use UserFrosting\Sprinkle\Core\Util\ClassMapper; use UserFrosting\Sprinkle\Core\Util\Util as CoreUtil; /** @@ -20,8 +21,13 @@ class Util { /** * Generate a random, unique username from a list of adjectives and nouns. + * + * @param ClassMapper $classMapper + * @param int $maxLength + * @param int $maxTries + * @return string */ - static public function randomUniqueUsername($classMapper, $maxLength, $maxTries = 10) + public static function randomUniqueUsername(ClassMapper $classMapper, $maxLength, $maxTries = 10) { for ($n = 1; $n <= 3; $n++) { for ($m = 0; $m < 10; $m++) { @@ -35,5 +41,4 @@ static public function randomUniqueUsername($classMapper, $maxLength, $maxTries return ''; } - } diff --git a/app/sprinkles/account/tests/Unit/FactoriesTest.php b/app/sprinkles/account/tests/Unit/FactoriesTest.php index 10dfc6de9..766d408a9 100644 --- a/app/sprinkles/account/tests/Unit/FactoriesTest.php +++ b/app/sprinkles/account/tests/Unit/FactoriesTest.php @@ -35,7 +35,6 @@ public function setUp() /** * Test the user factory - * @return void */ function testUserFactory() { diff --git a/app/sprinkles/account/tests/Unit/HasherTest.php b/app/sprinkles/account/tests/Unit/HasherTest.php index 711e3cb05..3f60ec67f 100644 --- a/app/sprinkles/account/tests/Unit/HasherTest.php +++ b/app/sprinkles/account/tests/Unit/HasherTest.php @@ -12,11 +12,12 @@ /** * Tests the password Hasher class. - * - * @extends TestCase */ class HasherTest extends TestCase { + /** + * @var string + */ protected $plainText = 'hodleth'; /** @@ -34,6 +35,9 @@ class HasherTest extends TestCase */ protected $modernHash = '$2y$10$ucxLwloFso6wJoct1baBQefdrttws/taEYvavi6qoPsw/vd1u4Mha'; + /** + * testGetHashType + */ public function testGetHashType() { $hasher = new Hasher; @@ -51,6 +55,9 @@ public function testGetHashType() $this->assertEquals('sha1', $type); } + /** + * testVerify + */ public function testVerify() { $hasher = new Hasher; @@ -60,6 +67,9 @@ public function testVerify() $this->assertTrue($hasher->verify($this->plainText, $this->userCakeHash)); } + /** + * testVerifyReject + */ public function testVerifyReject() { $hasher = new Hasher; diff --git a/app/sprinkles/account/tests/Unit/RegistrationTest.php b/app/sprinkles/account/tests/Unit/RegistrationTest.php index 75ce994a6..ed92c98da 100644 --- a/app/sprinkles/account/tests/Unit/RegistrationTest.php +++ b/app/sprinkles/account/tests/Unit/RegistrationTest.php @@ -31,8 +31,6 @@ public function tearDown() /** * Setup the database schema. - * - * @return void */ public function setUp() { diff --git a/app/sprinkles/admin/src/Controller/ActivityController.php b/app/sprinkles/admin/src/Controller/ActivityController.php index 2fbe0d97f..822b1f7fc 100644 --- a/app/sprinkles/admin/src/Controller/ActivityController.php +++ b/app/sprinkles/admin/src/Controller/ActivityController.php @@ -7,15 +7,10 @@ */ namespace UserFrosting\Sprinkle\Admin\Controller; -use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Slim\Exception\NotFoundException; use UserFrosting\Sprinkle\Core\Controller\SimpleController; -use UserFrosting\Sprinkle\Core\Facades\Debug; -use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; -use UserFrosting\Support\Exception\HttpException; /** * Controller class for activity-related requests. @@ -30,16 +25,19 @@ class ActivityController extends SimpleController * Generates a list of activities, optionally paginated, sorted and/or filtered. * This page requires authentication. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ - public function getList($request, $response, $args) + public function getList(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -47,7 +45,7 @@ public function getList($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $sprunje = $classMapper->createInstance('activity_sprunje', $classMapper, $params); @@ -66,13 +64,16 @@ public function getList($request, $response, $args) * This page renders a table of user activities. * This page requires authentication. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageList($request, $response, $args) + public function pageList(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page diff --git a/app/sprinkles/admin/src/Controller/AdminController.php b/app/sprinkles/admin/src/Controller/AdminController.php index da4da8aec..53ea83f3e 100644 --- a/app/sprinkles/admin/src/Controller/AdminController.php +++ b/app/sprinkles/admin/src/Controller/AdminController.php @@ -8,11 +8,9 @@ namespace UserFrosting\Sprinkle\Admin\Controller; use Carbon\Carbon; +use Psr\Http\Message\ResponseInterface as Response; +use Psr\Http\Message\ServerRequestInterface as Request; use UserFrosting\Sprinkle\Core\Controller\SimpleController; -use UserFrosting\Sprinkle\Account\Database\Models\Group; -use UserFrosting\Sprinkle\Account\Database\Models\User; -use UserFrosting\Sprinkle\Account\Database\Models\Role; -use UserFrosting\Sprinkle\Core\Database\Models\Version; use UserFrosting\Sprinkle\Core\Util\EnvironmentInfo; use UserFrosting\Support\Exception\ForbiddenException; @@ -25,17 +23,18 @@ */ class AdminController extends SimpleController { - /** * Renders the admin panel dashboard - * + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageDashboard($request, $response, $args) + public function pageDashboard(Request $request, Response $response, $args) { - //** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + //** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -43,7 +42,7 @@ public function pageDashboard($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Probably a better way to do this @@ -57,10 +56,10 @@ public function pageDashboard($request, $response, $args) return $item; }); - /** @var Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; - /** @var Config $config */ + /** @var \Illuminate\Cache\Repository $cache */ $cache = $this->ci->cache; // Get each sprinkle db version @@ -96,13 +95,16 @@ public function pageDashboard($request, $response, $args) * * This route requires authentication. * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args */ - public function clearCache($request, $response, $args) + public function clearCache(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -113,7 +115,7 @@ public function clearCache($request, $response, $args) // Flush cache $this->ci->cache->flush(); - /** @var MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; $ms->addMessageTranslated('success', 'CACHE.CLEARED'); @@ -127,13 +129,16 @@ public function clearCache($request, $response, $args) * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalConfirmClearCache($request, $response, $args) + public function getModalConfirmClearCache(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index 7ca94b1b1..23f113d43 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -7,8 +7,6 @@ */ namespace UserFrosting\Sprinkle\Admin\Controller; -use Carbon\Carbon; -use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; @@ -18,12 +16,9 @@ use UserFrosting\Fortress\ServerSideValidator; use UserFrosting\Fortress\Adapter\JqueryValidationAdapter; use UserFrosting\Sprinkle\Account\Database\Models\Group; -use UserFrosting\Sprinkle\Account\Database\Models\User; use UserFrosting\Sprinkle\Core\Controller\SimpleController; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; -use UserFrosting\Support\Exception\HttpException; /** * Controller class for group-related requests, including listing groups, CRUD for groups, etc. @@ -40,18 +35,23 @@ class GroupController extends SimpleController * 2. The user has permission to create a new group; * 3. The submitted data is valid. * This route requires authentication (and should generally be limited to admins or the root user). + * * Request type: POST * @see getModalCreateGroup + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function create($request, $response, $args) + public function create(Request $request, Response $response, $args) { // Get POST parameters: name, slug, icon, description $params = $request->getParsedBody(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -59,7 +59,7 @@ public function create($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // Load the request schema @@ -78,7 +78,7 @@ public function create($request, $response, $args) $error = true; } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check if name or slug already exists @@ -96,7 +96,7 @@ public function create($request, $response, $args) return $response->withStatus(400); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // All checks passed! log events/activities and create group @@ -130,9 +130,16 @@ public function create($request, $response, $args) * 3. The group is empty (does not have any users); * 4. The submitted data is valid. * This route requires authentication (and should generally be limited to admins or the root user). + * * Request type: DELETE + * @throws NotFoundException If group is not found + * @throws ForbiddenException If user is not authozied to access page + * @throws BadRequestException + * @param Request $request + * @param Response $response + * @param array $args */ - public function delete($request, $response, $args) + public function delete(Request $request, Response $response, $args) { $group = $this->getGroupFromParams($args); @@ -141,10 +148,10 @@ public function delete($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -154,7 +161,7 @@ public function delete($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Check that we are not deleting the default group @@ -165,7 +172,7 @@ public function delete($request, $response, $args) throw $e; } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check if there are any users in this group @@ -190,7 +197,7 @@ public function delete($request, $response, $args) ]); }); - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; $ms->addMessageTranslated('success', 'GROUP.DELETION_SUCCESSFUL', [ @@ -204,14 +211,20 @@ public function delete($request, $response, $args) * Returns info for a single group. * * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @throws NotFoundException If group is not found + * @param Request $request + * @param Response $response + * @param array $args */ - public function getInfo($request, $response, $args) + public function getInfo(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -221,7 +234,7 @@ public function getInfo($request, $response, $args) $slug = $args['slug']; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $group = $classMapper->staticMethod('group', 'where', 'slug', $slug)->first(); @@ -244,17 +257,22 @@ public function getInfo($request, $response, $args) * * Generates a list of groups, optionally paginated, sorted and/or filtered. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getList($request, $response, $args) + public function getList(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -262,7 +280,7 @@ public function getList($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $sprunje = $classMapper->createInstance('group_sprunje', $classMapper, $params); @@ -272,7 +290,17 @@ public function getList($request, $response, $args) return $sprunje->toResponse($response); } - public function getModalConfirmDelete($request, $response, $args) + /** + * Get deletetion confirmation modal + * + * @throws NotFoundException If group is not found + * @throws ForbiddenException If user is not authozied to access page + * @throws BadRequestException + * @param Request $request + * @param Response $response + * @param array $args + */ + public function getModalConfirmDelete(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -284,10 +312,10 @@ public function getModalConfirmDelete($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -297,7 +325,7 @@ public function getModalConfirmDelete($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check if there are any users in this group @@ -321,20 +349,25 @@ public function getModalConfirmDelete($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalCreate($request, $response, $args) + public function getModalCreate(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; - /** @var UserFrosting\I18n\MessageTranslator $translator */ + /** @var \UserFrosting\I18n\MessageTranslator $translator */ $translator = $this->ci->translator; // Access-controlled page @@ -342,7 +375,7 @@ public function getModalCreate($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Create a dummy group to prepopulate fields @@ -379,9 +412,15 @@ public function getModalCreate($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. + * * Request type: GET + * @throws NotFoundException If group is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalEdit($request, $response, $args) + public function getModalEdit(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -393,16 +432,16 @@ public function getModalEdit($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; - /** @var UserFrosting\I18n\MessageTranslator $translator */ + /** @var \UserFrosting\I18n\MessageTranslator $translator */ $translator = $this->ci->translator; // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "slug", "icon", "description" for this group @@ -438,7 +477,16 @@ public function getModalEdit($request, $response, $args) ]); } - public function getUsers($request, $response, $args) + /** + * Users List API + * + * @throws NotFoundException If group is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + */ + public function getUsers(Request $request, Response $response, $args) { $group = $this->getGroupFromParams($args); @@ -450,10 +498,10 @@ public function getUsers($request, $response, $args) // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -464,7 +512,7 @@ public function getUsers($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params); @@ -484,9 +532,14 @@ public function getUsers($request, $response, $args) * It checks each field individually, showing only those that you have permission to view. * This will also try to show buttons for deleting, and editing the group. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageInfo($request, $response, $args) + public function pageInfo(Request $request, Response $response, $args) { $group = $this->getGroupFromParams($args); @@ -496,10 +549,10 @@ public function pageInfo($request, $response, $args) return $response->withRedirect($redirectPage, 404); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -557,14 +610,19 @@ public function pageInfo($request, $response, $args) * This page renders a table of groups, with dropdown menus for admin actions for each group. * Actions typically include: edit group, delete group. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageList($request, $response, $args) + public function pageList(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -583,10 +641,16 @@ public function pageList($request, $response, $args) * 2. The user has the necessary permissions to update the posted field(s); * 3. The submitted data is valid. * This route requires authentication (and should generally be limited to admins or the root user). + * * Request type: PUT * @see getModalGroupEdit + * @throws NotFoundException If group is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function updateInfo($request, $response, $args) + public function updateInfo(Request $request, Response $response, $args) { // Get the group based on slug in URL $group = $this->getGroupFromParams($args); @@ -595,13 +659,13 @@ public function updateInfo($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get PUT parameters: (name, slug, icon, description) $params = $request->getParsedBody(); - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // Load the request schema @@ -626,10 +690,10 @@ public function updateInfo($request, $response, $args) $fieldNames[] = $name; } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit submitted fields for this group @@ -640,7 +704,7 @@ public function updateInfo($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check if name or slug already exists @@ -691,6 +755,13 @@ public function updateInfo($request, $response, $args) return $response->withStatus(200); } + /** + * Get group from params + * + * @throws BadRequestException + * @param array $params + * @return Group + */ protected function getGroupFromParams($params) { // Load the request schema @@ -713,7 +784,7 @@ protected function getGroupFromParams($params) throw $e; } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Get the group diff --git a/app/sprinkles/admin/src/Controller/PermissionController.php b/app/sprinkles/admin/src/Controller/PermissionController.php index 660e296c9..cfeb5f02a 100644 --- a/app/sprinkles/admin/src/Controller/PermissionController.php +++ b/app/sprinkles/admin/src/Controller/PermissionController.php @@ -7,23 +7,11 @@ */ namespace UserFrosting\Sprinkle\Admin\Controller; -use Carbon\Carbon; -use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Slim\Exception\NotFoundException; -use UserFrosting\Fortress\RequestDataTransformer; -use UserFrosting\Fortress\RequestSchema; -use UserFrosting\Fortress\ServerSideValidator; -use UserFrosting\Fortress\Adapter\JqueryValidationAdapter; -use UserFrosting\Sprinkle\Account\Database\Models\Permission; -use UserFrosting\Sprinkle\Account\Database\Models\Role; use UserFrosting\Sprinkle\Core\Controller\SimpleController; -use UserFrosting\Sprinkle\Core\Facades\Debug; -use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; -use UserFrosting\Support\Exception\HttpException; /** * Controller class for permission-related requests, including listing permissions, CRUD for permissions, etc. @@ -36,14 +24,20 @@ class PermissionController extends SimpleController * Returns info for a single permission. * * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @throws NotFoundException If permission is not found + * @param Request $request + * @param Response $response + * @param array $args */ - public function getInfo($request, $response, $args) + public function getInfo(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -53,7 +47,7 @@ public function getInfo($request, $response, $args) $permissionId = $args['id']; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $permission = $classMapper->staticMethod('permission', 'find', $permissionId); @@ -76,17 +70,22 @@ public function getInfo($request, $response, $args) * * Generates a list of permissions, optionally paginated, sorted and/or filtered. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getList($request, $response, $args) + public function getList(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -94,7 +93,7 @@ public function getList($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $sprunje = $classMapper->createInstance('permission_sprunje', $classMapper, $params); @@ -109,17 +108,22 @@ public function getList($request, $response, $args) * * Generates a list of users, optionally paginated, sorted and/or filtered. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getUsers($request, $response, $args) + public function getUsers(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -127,7 +131,7 @@ public function getUsers($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $params['permission_id'] = $args['id']; @@ -148,14 +152,20 @@ public function getUsers($request, $response, $args) * Note that permissions cannot be modified through the interface. This is because * permissions are tighly coupled to the code and should only be modified by developers. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @throws NotFoundException If permission is not found + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageInfo($request, $response, $args) + public function pageInfo(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -165,7 +175,7 @@ public function pageInfo($request, $response, $args) $permissionId = $args['id']; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $permission = $classMapper->staticMethod('permission', 'find', $permissionId); @@ -186,14 +196,19 @@ public function pageInfo($request, $response, $args) * This page renders a table of permissions, with dropdown menus for admin actions for each permission. * Actions typically include: edit permission, delete permission. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageList($request, $response, $args) + public function pageList(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index ab86c88be..02d17a2e9 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -7,8 +7,6 @@ */ namespace UserFrosting\Sprinkle\Admin\Controller; -use Carbon\Carbon; -use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; @@ -18,12 +16,9 @@ use UserFrosting\Fortress\ServerSideValidator; use UserFrosting\Fortress\Adapter\JqueryValidationAdapter; use UserFrosting\Sprinkle\Account\Database\Models\Role; -use UserFrosting\Sprinkle\Account\Database\Models\User; use UserFrosting\Sprinkle\Core\Controller\SimpleController; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; -use UserFrosting\Support\Exception\HttpException; /** * Controller class for role-related requests, including listing roles, CRUD for roles, etc. @@ -40,18 +35,23 @@ class RoleController extends SimpleController * 2. The user has permission to create a new role; * 3. The submitted data is valid. * This route requires authentication (and should generally be limited to admins or the root user). + * * Request type: POST * @see getModalCreateRole + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function create($request, $response, $args) + public function create(Request $request, Response $response, $args) { // Get POST parameters: name, slug, description $params = $request->getParsedBody(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -59,7 +59,7 @@ public function create($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // Load the request schema @@ -78,7 +78,7 @@ public function create($request, $response, $args) $error = true; } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check if name or slug already exists @@ -96,7 +96,7 @@ public function create($request, $response, $args) return $response->withStatus(400); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // All checks passed! log events/activities and create role @@ -130,9 +130,16 @@ public function create($request, $response, $args) * 3. The role does not have any associated users; * 4. The submitted data is valid. * This route requires authentication (and should generally be limited to admins or the root user). + * * Request type: DELETE + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page + * @throws BadRequestException + * @param Request $request + * @param Response $response + * @param array $args */ - public function delete($request, $response, $args) + public function delete(Request $request, Response $response, $args) { $role = $this->getRoleFromParams($args); @@ -141,10 +148,10 @@ public function delete($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -154,7 +161,7 @@ public function delete($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check that we are not deleting a default role @@ -189,7 +196,7 @@ public function delete($request, $response, $args) ]); }); - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; $ms->addMessageTranslated('success', 'ROLE.DELETION_SUCCESSFUL', [ @@ -203,14 +210,20 @@ public function delete($request, $response, $args) * Returns info for a single role, along with associated permissions. * * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @throws NotFoundException If role is not found + * @param Request $request + * @param Response $response + * @param array $args */ - public function getInfo($request, $response, $args) + public function getInfo(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -220,7 +233,7 @@ public function getInfo($request, $response, $args) $slug = $args['slug']; - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $role = $classMapper->staticMethod('role', 'where', 'slug', $slug)->first(); @@ -243,17 +256,22 @@ public function getInfo($request, $response, $args) * * Generates a list of roles, optionally paginated, sorted and/or filtered. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getList($request, $response, $args) + public function getList(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -261,7 +279,7 @@ public function getList($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $sprunje = $classMapper->createInstance('role_sprunje', $classMapper, $params); @@ -271,7 +289,17 @@ public function getList($request, $response, $args) return $sprunje->toResponse($response); } - public function getModalConfirmDelete($request, $response, $args) + /** + * Display deletion confirmation modal + * + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page + * @throws BadRequestException + * @param Request $request + * @param Response $response + * @param array $args + */ + public function getModalConfirmDelete(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -283,10 +311,10 @@ public function getModalConfirmDelete($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -296,7 +324,7 @@ public function getModalConfirmDelete($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check that we are not deleting a default role @@ -330,20 +358,25 @@ public function getModalConfirmDelete($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalCreate($request, $response, $args) + public function getModalCreate(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; - /** @var UserFrosting\I18n\MessageTranslator $translator */ + /** @var \UserFrosting\I18n\MessageTranslator $translator */ $translator = $this->ci->translator; // Access-controlled page @@ -351,7 +384,7 @@ public function getModalCreate($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Create a dummy role to prepopulate fields @@ -386,9 +419,15 @@ public function getModalCreate($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. + * * Request type: GET + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalEdit($request, $response, $args) + public function getModalEdit(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -400,16 +439,16 @@ public function getModalEdit($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; - /** @var UserFrosting\I18n\MessageTranslator $translator */ + /** @var \UserFrosting\I18n\MessageTranslator $translator */ $translator = $this->ci->translator; // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "slug", "description" for this role @@ -450,9 +489,15 @@ public function getModalEdit($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages. * This page requires authentication. + * * Request type: GET + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalEditPermissions($request, $response, $args) + public function getModalEditPermissions(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -464,10 +509,10 @@ public function getModalEditPermissions($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit "permissions" field for this role @@ -488,9 +533,15 @@ public function getModalEditPermissions($request, $response, $args) * * Generates a list of permissions, optionally paginated, sorted and/or filtered. * This page requires authentication. + * * Request type: GET + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getPermissions($request, $response, $args) + public function getPermissions(Request $request, Response $response, $args) { $role = $this->getRoleFromParams($args); @@ -502,10 +553,10 @@ public function getPermissions($request, $response, $args) // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -516,7 +567,7 @@ public function getPermissions($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $sprunje = $classMapper->createInstance('permission_sprunje', $classMapper, $params); @@ -533,9 +584,15 @@ public function getPermissions($request, $response, $args) * Returns users associated with a single role. * * This page requires authentication. + * * Request type: GET + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getUsers($request, $response, $args) + public function getUsers(Request $request, Response $response, $args) { $role = $this->getRoleFromParams($args); @@ -544,16 +601,16 @@ public function getUsers($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -581,9 +638,14 @@ public function getUsers($request, $response, $args) * It checks each field individually, showing only those that you have permission to view. * This will also try to show buttons for deleting and editing the role. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageInfo($request, $response, $args) + public function pageInfo(Request $request, Response $response, $args) { $role = $this->getRoleFromParams($args); @@ -593,10 +655,10 @@ public function pageInfo($request, $response, $args) return $response->withRedirect($redirectPage, 404); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -654,14 +716,19 @@ public function pageInfo($request, $response, $args) * This page renders a table of roles, with dropdown menus for admin actions for each role. * Actions typically include: edit role, delete role. * This page requires authentication. + * * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageList($request, $response, $args) + public function pageList(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -680,10 +747,16 @@ public function pageList($request, $response, $args) * 2. The user has the necessary permissions to update the posted field(s); * 3. The submitted data is valid. * This route requires authentication (and should generally be limited to admins or the root user). + * * Request type: PUT * @see getModalRoleEdit + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function updateInfo($request, $response, $args) + public function updateInfo(Request $request, Response $response, $args) { // Get the role based on slug in the URL $role = $this->getRoleFromParams($args); @@ -692,13 +765,13 @@ public function updateInfo($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get PUT parameters: (name, slug, description) $params = $request->getParsedBody(); - /** @var UserFrosting\I18n\MessageTranslator $translator */ + /** @var \UserFrosting\I18n\MessageTranslator $translator */ $ms = $this->ci->alerts; // Load the request schema @@ -723,10 +796,10 @@ public function updateInfo($request, $response, $args) $fieldNames[] = $name; } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit submitted fields for this role @@ -737,7 +810,7 @@ public function updateInfo($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check if name or slug already exists @@ -795,9 +868,16 @@ public function updateInfo($request, $response, $args) * 1. The logged-in user has the necessary permissions to update the putted field(s); * 2. The submitted data is valid. * This route requires authentication. + * * Request type: PUT + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page + * @throws BadRequestException + * @param Request $request + * @param Response $response + * @param array $args */ - public function updateField($request, $response, $args) + public function updateField(Request $request, Response $response, $args) { // Get the username from the URL $role = $this->getRoleFromParams($args); @@ -809,10 +889,10 @@ public function updateField($request, $response, $args) // Get key->value pair from URL and request body $fieldName = $args['field']; - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit the specified field for this user @@ -823,7 +903,7 @@ public function updateField($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get PUT parameters: value @@ -862,7 +942,7 @@ public function updateField($request, $response, $args) // Get validated and transformed value $fieldValue = $data[$fieldName]; - /** @var UserFrosting\I18n\MessageTranslator $translator */ + /** @var \UserFrosting\I18n\MessageTranslator $translator */ $ms = $this->ci->alerts; // Begin transaction - DB will be rolled back if an exception occurs @@ -896,6 +976,13 @@ public function updateField($request, $response, $args) return $response->withStatus(200); } + /** + * Get role instance from params + * + * @throws BadRequestException + * @param array $params + * @return Role + */ protected function getRoleFromParams($params) { // Load the request schema @@ -918,7 +1005,7 @@ protected function getRoleFromParams($params) throw $e; } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Get the role diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index ff41009cd..be0b8f946 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Admin\Controller; use Carbon\Carbon; -use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; @@ -17,16 +16,13 @@ use UserFrosting\Fortress\RequestSchema; use UserFrosting\Fortress\ServerSideValidator; use UserFrosting\Fortress\Adapter\JqueryValidationAdapter; -use UserFrosting\Sprinkle\Account\Database\Models\Group; use UserFrosting\Sprinkle\Account\Database\Models\User; use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Core\Controller\SimpleController; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Mail\EmailRecipient; use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; -use UserFrosting\Support\Exception\HttpException; /** * Controller class for user-related requests, including listing users, CRUD for users, etc. @@ -43,18 +39,23 @@ class UserController extends SimpleController * 2. The logged-in user has the necessary permissions to update the posted field(s); * 3. The submitted data is valid. * This route requires authentication. + * * Request type: POST * @see getModalCreate + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function create($request, $response, $args) + public function create(Request $request, Response $response, $args) { // Get POST parameters: user_name, first_name, last_name, email, locale, (group) $params = $request->getParsedBody(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -62,7 +63,7 @@ public function create($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // Load the request schema @@ -81,7 +82,7 @@ public function create($request, $response, $args) $error = true; } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check if username or email already exists @@ -99,7 +100,7 @@ public function create($request, $response, $args) return $response->withStatus(400); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // If currentUser does not have permission to set the group, but they try to set it to something other than their own group, @@ -175,9 +176,15 @@ public function create($request, $response, $args) * 3. We're not trying to disable the master account; * 4. The submitted data is valid. * This route requires authentication. + * * Request type: POST + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function createPasswordReset($request, $response, $args) + public function createPasswordReset(Request $request, Response $response, $args) { // Get the username from the URL $user = $this->getUserFromParams($args); @@ -186,10 +193,10 @@ public function createPasswordReset($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit "password" for this user @@ -200,10 +207,10 @@ public function createPasswordReset($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // Begin transaction - DB will be rolled back if an exception occurs @@ -240,9 +247,16 @@ public function createPasswordReset($request, $response, $args) * 1. You are not trying to delete the master account; * 2. You have permission to delete the target user's account. * This route requires authentication (and should generally be limited to admins or the root user). + * * Request type: DELETE + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @throws BadRequestException + * @param Request $request + * @param Response $response + * @param array $args */ - public function delete($request, $response, $args) + public function delete(Request $request, Response $response, $args) { $user = $this->getUserFromParams($args); @@ -251,10 +265,10 @@ public function delete($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -264,7 +278,7 @@ public function delete($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Check that we are not deleting the master account @@ -289,7 +303,7 @@ public function delete($request, $response, $args) ]); }); - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; $ms->addMessageTranslated('success', 'DELETION_SUCCESSFUL', [ @@ -304,8 +318,13 @@ public function delete($request, $response, $args) * * This page requires authentication. * Request type: GET + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getActivities($request, $response, $args) + public function getActivities(Request $request, Response $response, $args) { $user = $this->getUserFromParams($args); @@ -314,16 +333,16 @@ public function getActivities($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -350,8 +369,13 @@ public function getActivities($request, $response, $args) * * This page requires authentication. * Request type: GET + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getInfo($request, $response, $args) + public function getInfo(Request $request, Response $response, $args) { $user = $this->getUserFromParams($args); @@ -360,7 +384,7 @@ public function getInfo($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Join user's most recent activity @@ -370,10 +394,10 @@ public function getInfo($request, $response, $args) ->with('lastActivity', 'group') ->first(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -396,16 +420,20 @@ public function getInfo($request, $response, $args) * Generates a list of users, optionally paginated, sorted and/or filtered. * This page requires authentication. * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getList($request, $response, $args) + public function getList(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -413,7 +441,7 @@ public function getList($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $sprunje = $classMapper->createInstance('user_sprunje', $classMapper, $params); @@ -429,8 +457,14 @@ public function getList($request, $response, $args) * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. * Request type: GET + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @throws BadRequestException + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalConfirmDelete($request, $response, $args) + public function getModalConfirmDelete(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -442,10 +476,10 @@ public function getModalConfirmDelete($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -455,7 +489,7 @@ public function getModalConfirmDelete($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Check that we are not deleting the master account @@ -480,21 +514,26 @@ public function getModalConfirmDelete($request, $response, $args) * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * If the currently logged-in user has permission to modify user group membership, then the group toggle will be displayed. * Otherwise, the user will be added to the default group and receive the default roles automatically. + * * This page requires authentication. * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalCreate($request, $response, $args) + public function getModalCreate(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; - /** @var UserFrosting\I18n\MessageTranslator $translator */ + /** @var \UserFrosting\I18n\MessageTranslator $translator */ $translator = $this->ci->translator; // Access-controlled page @@ -502,10 +541,10 @@ public function getModalCreate($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Determine form fields to hide/disable @@ -565,9 +604,15 @@ public function getModalCreate($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. + * * Request type: GET + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalEdit($request, $response, $args) + public function getModalEdit(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -579,7 +624,7 @@ public function getModalEdit($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Get the user to edit @@ -587,10 +632,10 @@ public function getModalEdit($request, $response, $args) ->with('group') ->first(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "email", "locale" for this user @@ -605,7 +650,7 @@ public function getModalEdit($request, $response, $args) // Get a list of all groups $groups = $classMapper->staticMethod('group', 'all'); - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get a list of all locales @@ -652,9 +697,15 @@ public function getModalEdit($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages. * This page requires authentication. + * * Request type: GET + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalEditPassword($request, $response, $args) + public function getModalEditPassword(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -666,10 +717,10 @@ public function getModalEditPassword($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit "password" field for this user @@ -697,9 +748,15 @@ public function getModalEditPassword($request, $response, $args) * * This does NOT render a complete page. Instead, it renders the HTML for the form, which can be embedded in other pages. * This page requires authentication. + * * Request type: GET + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getModalEditRoles($request, $response, $args) + public function getModalEditRoles(Request $request, Response $response, $args) { // GET parameters $params = $request->getQueryParams(); @@ -711,10 +768,10 @@ public function getModalEditRoles($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit "roles" field for this user @@ -736,8 +793,13 @@ public function getModalEditRoles($request, $response, $args) * Generates a list of permissions, optionally paginated, sorted and/or filtered. * This page requires authentication. * Request type: GET + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getPermissions($request, $response, $args) + public function getPermissions(Request $request, Response $response, $args) { $user = $this->getUserFromParams($args); @@ -749,10 +811,10 @@ public function getPermissions($request, $response, $args) // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -763,7 +825,7 @@ public function getPermissions($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; $params['user_id'] = $user->id; @@ -781,8 +843,13 @@ public function getPermissions($request, $response, $args) * * This page requires authentication. * Request type: GET + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function getRoles($request, $response, $args) + public function getRoles(Request $request, Response $response, $args) { $user = $this->getUserFromParams($args); @@ -791,16 +858,16 @@ public function getRoles($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // GET parameters $params = $request->getQueryParams(); - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -827,10 +894,15 @@ public function getRoles($request, $response, $args) * This checks that the currently logged-in user has permission to view the requested user's info. * It checks each field individually, showing only those that you have permission to view. * This will also try to show buttons for activating, disabling/enabling, deleting, and editing the user. + * * This page requires authentication. * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageInfo($request, $response, $args) + public function pageInfo(Request $request, Response $response, $args) { $user = $this->getUserFromParams($args); @@ -840,10 +912,10 @@ public function pageInfo($request, $response, $args) return $response->withRedirect($usersPage, 404); } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -853,7 +925,7 @@ public function pageInfo($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get a list of all locales @@ -957,15 +1029,20 @@ public function pageInfo($request, $response, $args) * * This page renders a table of users, with dropdown menus for admin actions for each user. * Actions typically include: edit user details, activate user, enable/disable user, delete user. + * * This page requires authentication. * Request type: GET + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function pageList($request, $response, $args) + public function pageList(Request $request, Response $response, $args) { - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -983,10 +1060,16 @@ public function pageList($request, $response, $args) * 1. The target user's new email address, if specified, is not already in use; * 2. The logged-in user has the necessary permissions to update the putted field(s); * 3. The submitted data is valid. + * * This route requires authentication. * Request type: PUT + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args */ - public function updateInfo($request, $response, $args) + public function updateInfo(Request $request, Response $response, $args) { // Get the username from the URL $user = $this->getUserFromParams($args); @@ -995,13 +1078,13 @@ public function updateInfo($request, $response, $args) throw new NotFoundException($request, $response); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Get PUT parameters $params = $request->getParsedBody(); - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // Load the request schema @@ -1032,10 +1115,10 @@ public function updateInfo($request, $response, $args) } } - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit submitted fields for this user @@ -1054,7 +1137,7 @@ public function updateInfo($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Check if email already exists @@ -1103,10 +1186,17 @@ public function updateInfo($request, $response, $args) * 1. The logged-in user has the necessary permissions to update the putted field(s); * 2. We're not trying to disable the master account; * 3. The submitted data is valid. + * * This route requires authentication. * Request type: PUT + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page + * @throws BadRequestException + * @param Request $request + * @param Response $response + * @param array $args */ - public function updateField($request, $response, $args) + public function updateField(Request $request, Response $response, $args) { // Get the username from the URL $user = $this->getUserFromParams($args); @@ -1118,10 +1208,10 @@ public function updateField($request, $response, $args) // Get key->value pair from URL and request body $fieldName = $args['field']; - /** @var UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ + /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit the specified field for this user @@ -1132,7 +1222,7 @@ public function updateField($request, $response, $args) throw new ForbiddenException(); } - /** @var UserFrosting\Config\Config $config */ + /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; // Only the master account can edit the master account! @@ -1178,7 +1268,7 @@ public function updateField($request, $response, $args) // Get validated and transformed value $fieldValue = $data[$fieldName]; - /** @var UserFrosting\Sprinkle\Core\MessageStream $ms */ + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; // Special checks and transformations for certain fields @@ -1244,6 +1334,13 @@ public function updateField($request, $response, $args) return $response->withStatus(200); } + /** + * Get User instance from params + * + * @throws BadRequestException + * @param array $params + * @return User + */ protected function getUserFromParams($params) { // Load the request schema @@ -1266,7 +1363,7 @@ protected function getUserFromParams($params) throw $e; } - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = $this->ci->classMapper; // Get the user to delete diff --git a/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php b/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php index da4f0e3f5..adde7bb4a 100644 --- a/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php +++ b/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php @@ -7,8 +7,7 @@ */ namespace UserFrosting\Sprinkle\Admin\Sprunje; -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Facades\Debug; +use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Sprunje\Sprunje; /** @@ -49,9 +48,9 @@ protected function baseQuery() * * @param Builder $query * @param mixed $value - * @return $this + * @return self */ - protected function filterUser($query, $value) + protected function filterUser(Builder $query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -70,9 +69,9 @@ protected function filterUser($query, $value) * * @param Builder $query * @param string $direction - * @return $this + * @return self */ - protected function sortUser($query, $direction) + protected function sortUser(Builder $query, $direction) { $query->orderBy('users.last_name', $direction); return $this; diff --git a/app/sprinkles/admin/src/Sprunje/GroupSprunje.php b/app/sprinkles/admin/src/Sprunje/GroupSprunje.php index 7c7569124..ebe2aabd2 100644 --- a/app/sprinkles/admin/src/Sprunje/GroupSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/GroupSprunje.php @@ -7,8 +7,6 @@ */ namespace UserFrosting\Sprinkle\Admin\Sprunje; -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Sprunje\Sprunje; /** @@ -33,7 +31,7 @@ class GroupSprunje extends Sprunje ]; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function baseQuery() { diff --git a/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php b/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php index c1803f11b..4e7dddbb9 100644 --- a/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php @@ -7,8 +7,7 @@ */ namespace UserFrosting\Sprinkle\Admin\Sprunje; -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Facades\Debug; +use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Sprunje\Sprunje; /** @@ -38,7 +37,7 @@ class PermissionSprunje extends Sprunje ]; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function baseQuery() { @@ -50,9 +49,9 @@ protected function baseQuery() * * @param Builder $query * @param mixed $value - * @return $this + * @return self */ - protected function filterInfo($query, $value) + protected function filterInfo(Builder $query, $value) { return $this->filterProperties($query, $value); } @@ -62,9 +61,9 @@ protected function filterInfo($query, $value) * * @param Builder $query * @param mixed $value - * @return $this + * @return self */ - protected function filterProperties($query, $value) + protected function filterProperties(Builder $query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -83,9 +82,9 @@ protected function filterProperties($query, $value) * * @param Builder $query * @param string $direction - * @return $this + * @return self */ - protected function sortProperties($query, $direction) + protected function sortProperties(Builder $query, $direction) { $query->orderBy('slug', $direction); return $this; diff --git a/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php b/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php index 242681d03..9dc278691 100644 --- a/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php @@ -7,8 +7,6 @@ */ namespace UserFrosting\Sprinkle\Admin\Sprunje; -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\NotFoundException; @@ -24,7 +22,7 @@ class PermissionUserSprunje extends UserSprunje protected $name = 'permission_users'; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function baseQuery() { diff --git a/app/sprinkles/admin/src/Sprunje/RoleSprunje.php b/app/sprinkles/admin/src/Sprunje/RoleSprunje.php index c5e0f8b34..cefcf7cb5 100644 --- a/app/sprinkles/admin/src/Sprunje/RoleSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/RoleSprunje.php @@ -7,8 +7,7 @@ */ namespace UserFrosting\Sprinkle\Admin\Sprunje; -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Facades\Debug; +use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Sprunje\Sprunje; /** @@ -38,7 +37,7 @@ class RoleSprunje extends Sprunje ]; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function baseQuery() { @@ -50,9 +49,9 @@ protected function baseQuery() * * @param Builder $query * @param mixed $value - * @return $this + * @return self */ - protected function filterInfo($query, $value) + protected function filterInfo(Builder $query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); diff --git a/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php b/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php index 6142e7413..1f0c8fe33 100644 --- a/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php @@ -7,8 +7,6 @@ */ namespace UserFrosting\Sprinkle\Admin\Sprunje; -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\NotFoundException; @@ -24,7 +22,7 @@ class UserPermissionSprunje extends PermissionSprunje protected $name = 'user_permissions'; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function baseQuery() { diff --git a/app/sprinkles/admin/src/Sprunje/UserSprunje.php b/app/sprinkles/admin/src/Sprunje/UserSprunje.php index 12378f9ac..d0f033031 100644 --- a/app/sprinkles/admin/src/Sprunje/UserSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/UserSprunje.php @@ -7,8 +7,7 @@ */ namespace UserFrosting\Sprinkle\Admin\Sprunje; -use Illuminate\Database\Capsule\Manager as Capsule; -use UserFrosting\Sprinkle\Core\Facades\Debug; +use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Facades\Translator; use UserFrosting\Sprinkle\Core\Sprunje\Sprunje; @@ -44,7 +43,7 @@ class UserSprunje extends Sprunje ]; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function baseQuery() { @@ -59,9 +58,9 @@ protected function baseQuery() * * @param Builder $query * @param mixed $value - * @return $this + * @return self */ - protected function filterLastActivity($query, $value) + protected function filterLastActivity(Builder $query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -78,9 +77,9 @@ protected function filterLastActivity($query, $value) * * @param Builder $query * @param mixed $value - * @return $this + * @return self */ - protected function filterName($query, $value) + protected function filterName(Builder $query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -99,9 +98,9 @@ protected function filterName($query, $value) * * @param Builder $query * @param mixed $value - * @return $this + * @return self */ - protected function filterStatus($query, $value) + protected function filterStatus(Builder $query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -149,9 +148,9 @@ protected function listStatus() * * @param Builder $query * @param string $direction - * @return $this + * @return self */ - protected function sortLastActivity($query, $direction) + protected function sortLastActivity(Builder $query, $direction) { $query->orderBy('activities.occurred_at', $direction); return $this; @@ -162,9 +161,9 @@ protected function sortLastActivity($query, $direction) * * @param Builder $query * @param string $direction - * @return $this + * @return self */ - protected function sortName($query, $direction) + protected function sortName(Builder $query, $direction) { $query->orderBy('last_name', $direction); return $this; @@ -175,9 +174,9 @@ protected function sortName($query, $direction) * * @param Builder $query * @param string $direction - * @return $this + * @return self */ - protected function sortStatus($query, $direction) + protected function sortStatus(Builder $query, $direction) { $query->orderBy('flag_enabled', $direction)->orderBy('flag_verified', $direction); return $this; diff --git a/app/sprinkles/admin/tests/Integration/SprunjeTests.php b/app/sprinkles/admin/tests/Integration/SprunjeTests.php index bbdf9cf15..6cef7e2b6 100644 --- a/app/sprinkles/admin/tests/Integration/SprunjeTests.php +++ b/app/sprinkles/admin/tests/Integration/SprunjeTests.php @@ -23,8 +23,6 @@ class SprunjeTests extends TestCase /** * Setup the database schema. - * - * @return void */ public function setUp() { diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index 55c21d330..d048b508b 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -32,7 +32,7 @@ ] ], /** - * Don'T display error detail in test. Return the non formatted errors + * Don't display error detail in test. Return the non formatted errors */ 'settings' => [ 'displayErrorDetails' => false diff --git a/app/sprinkles/core/src/Alert/AlertStream.php b/app/sprinkles/core/src/Alert/AlertStream.php index 3946cbf54..d65dc1fb6 100644 --- a/app/sprinkles/core/src/Alert/AlertStream.php +++ b/app/sprinkles/core/src/Alert/AlertStream.php @@ -8,6 +8,7 @@ namespace UserFrosting\Sprinkle\Core\Alert; use UserFrosting\Fortress\ServerSideValidator; +use UserFrosting\I18n\MessageTranslator; /** * AlertStream Class @@ -19,33 +20,35 @@ */ abstract class AlertStream { - /** * @var string */ protected $messagesKey; /** - * @var UserFrosting\I18n\MessageTranslator|null + * @var \UserFrosting\I18n\MessageTranslator|null */ protected $messageTranslator = null; /** * Create a new message stream. + * + * @param string $messagesKey + * @param \UserFrosting\I18n\MessageTranslator|null $translator */ - public function __construct($messagesKey, $translator = null) + public function __construct($messagesKey, MessageTranslator $translator = null) { $this->messagesKey = $messagesKey; - $this->setTranslator($translator); } /** * Set the translator to be used for all message streams. Must be done before `addMessageTranslated` can be used. * - * @param UserFrosting\I18n\MessageTranslator $translator A MessageTranslator to be used to translate messages when added via `addMessageTranslated`. + * @param \UserFrosting\I18n\MessageTranslator $translator A MessageTranslator to be used to translate messages when added via `addMessageTranslated`. + * @return self */ - public function setTranslator($translator) + public function setTranslator(MessageTranslator $translator) { $this->messageTranslator = $translator; return $this; @@ -56,7 +59,7 @@ public function setTranslator($translator) * * @param string $type The type of message, indicating how it will be styled when outputted. Should be set to "success", "danger", "warning", or "info". * @param string $message The message to be added to the message stream. - * @return MessageStream this MessageStream object. + * @return self this MessageStream object. */ public function addMessage($type, $message) { @@ -75,7 +78,8 @@ public function addMessage($type, $message) * @param string $type The type of message, indicating how it will be styled when outputted. Should be set to "success", "danger", "warning", or "info". * @param string $messageId The message id for the message to be added to the message stream. * @param array[string] $placeholders An optional hash of placeholder names => placeholder values to substitute into the translated message. - * @return MessageStream this MessageStream object. + * @throws \RuntimeException + * @return self this MessageStream object. */ public function addMessageTranslated($type, $messageId, $placeholders = array()) { @@ -139,6 +143,8 @@ abstract public function resetMessageStream(); /** * Save messages to the stream + * + * @param string $message */ abstract protected function saveMessages($message); } diff --git a/app/sprinkles/core/src/Alert/CacheAlertStream.php b/app/sprinkles/core/src/Alert/CacheAlertStream.php index 1fd51316a..433d719f0 100644 --- a/app/sprinkles/core/src/Alert/CacheAlertStream.php +++ b/app/sprinkles/core/src/Alert/CacheAlertStream.php @@ -12,33 +12,33 @@ use UserFrosting\Support\Repository\Repository; /** - * CacheAlertStream Class - * Implements a message stream for use between HTTP requests, with i18n - * support via the MessageTranslator class using the cache system to store - * the alerts. Note that the tags are added each time instead of the - * constructor since the session_id can change when the user logs in or out + * CacheAlertStream Class + * Implements a message stream for use between HTTP requests, with i18n + * support via the MessageTranslator class using the cache system to store + * the alerts. Note that the tags are added each time instead of the + * constructor since the session_id can change when the user logs in or out * - * @author Louis Charette + * @author Louis Charette */ class CacheAlertStream extends AlertStream { /** - * @var Cache Object We use the cache object so that added messages will automatically appear in the cache. + * @var Cache Object We use the cache object so that added messages will automatically appear in the cache. */ protected $cache; /** - * @var Repository Object We use the cache object so that added messages will automatically appear in the cache. + * @var Repository Object We use the cache object so that added messages will automatically appear in the cache. */ protected $config; /** - * Create a new message stream. + * Create a new message stream. * - * @param string $messagesKey Store the messages under this key - * @param MessageTranslator|null $translator - * @param Cache $cache - * @param Repository $config + * @param string $messagesKey Store the messages under this key + * @param MessageTranslator|null $translator + * @param Cache $cache + * @param Repository $config */ public function __construct($messagesKey, MessageTranslator $translator = null, Cache $cache, Repository $config) { @@ -48,9 +48,9 @@ public function __construct($messagesKey, MessageTranslator $translator = null, } /** - * Get the messages from this message stream. + * Get the messages from this message stream. * - * @return array An array of messages, each of which is itself an array containing 'type' and 'message' fields. + * @return array An array of messages, each of which is itself an array containing 'type' and 'message' fields. */ public function messages() { @@ -62,9 +62,7 @@ public function messages() } /** - * Clear all messages from this message stream. - * - * @return void + * Clear all messages from this message stream. */ public function resetMessageStream() { @@ -72,10 +70,9 @@ public function resetMessageStream() } /** - * Save messages to the stream + * Save messages to the stream * - * @param string $messages The message - * @return void + * @param string $messages The message */ protected function saveMessages($messages) { diff --git a/app/sprinkles/core/src/Alert/SessionAlertStream.php b/app/sprinkles/core/src/Alert/SessionAlertStream.php index 8b4604b40..01bcbb6d0 100644 --- a/app/sprinkles/core/src/Alert/SessionAlertStream.php +++ b/app/sprinkles/core/src/Alert/SessionAlertStream.php @@ -11,25 +11,25 @@ use UserFrosting\Session\Session; /** - * SessionAlertStream Class - * Implements a message stream for use between HTTP requests, with i18n support via the MessageTranslator class - * Using the session storage to store the alerts + * SessionAlertStream Class + * Implements a message stream for use between HTTP requests, with i18n support via the MessageTranslator class + * Using the session storage to store the alerts * - * @author Alex Weissman (https://alexanderweissman.com) + * @author Alex Weissman (https://alexanderweissman.com) */ class SessionAlertStream extends AlertStream { /** - * @var Session We use the session object so that added messages will automatically appear in the session. + * @var Session We use the session object so that added messages will automatically appear in the session. */ protected $session; /** - * Create a new message stream. + * Create a new message stream. * - * @param string $messagesKey Store the messages under this key - * @param MessageTranslator|null $translator - * @param Session $session + * @param string $messagesKey Store the messages under this key + * @param MessageTranslator|null $translator + * @param Session $session */ public function __construct($messagesKey, MessageTranslator $translator = null, Session $session) { @@ -38,9 +38,9 @@ public function __construct($messagesKey, MessageTranslator $translator = null, } /** - * Get the messages from this message stream. + * Get the messages from this message stream. * - * @return array An array of messages, each of which is itself an array containing "type" and "message" fields. + * @return array An array of messages, each of which is itself an array containing "type" and "message" fields. */ public function messages() { @@ -48,9 +48,7 @@ public function messages() } /** - * Clear all messages from this message stream. - * - * @return void + * Clear all messages from this message stream. */ public function resetMessageStream() { @@ -58,10 +56,9 @@ public function resetMessageStream() } /** - * Save messages to the stream + * Save messages to the stream * - * @param string $messages The message - * @return void + * @param string $messages The message */ protected function saveMessages($messages) { diff --git a/app/sprinkles/core/src/Bakery/BakeCommand.php b/app/sprinkles/core/src/Bakery/BakeCommand.php index 06c093536..19358beec 100644 --- a/app/sprinkles/core/src/Bakery/BakeCommand.php +++ b/app/sprinkles/core/src/Bakery/BakeCommand.php @@ -9,8 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; /** @@ -27,7 +25,7 @@ class BakeCommand extends BaseCommand protected $buildPath; /** - * @var string $ufArt The UserFrosting ASCII art. + * @var string The UserFrosting ASCII art. */ public $title = " _ _ ______ _ _ @@ -40,7 +38,7 @@ class BakeCommand extends BaseCommand |___/"; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -50,7 +48,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php index c40ea8502..eb68b5815 100644 --- a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php +++ b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php @@ -9,8 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; use UserFrosting\Sprinkle\Core\Twig\CacheHelper; @@ -22,7 +20,7 @@ class ClearCacheCommand extends BaseCommand { /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -31,7 +29,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -61,8 +59,6 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Flush the cached data from the cache service - * - * @return void */ protected function clearIlluminateCache() { diff --git a/app/sprinkles/core/src/Bakery/DebugCommand.php b/app/sprinkles/core/src/Bakery/DebugCommand.php index 5fddcd701..a8ac3c8a4 100644 --- a/app/sprinkles/core/src/Bakery/DebugCommand.php +++ b/app/sprinkles/core/src/Bakery/DebugCommand.php @@ -9,8 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; use UserFrosting\System\Bakery\DatabaseTest; @@ -24,7 +22,7 @@ class DebugCommand extends BaseCommand use DatabaseTest; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -34,7 +32,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -63,8 +61,6 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Check the minimum version of php. * This is done by composer itself, but we do it again for good mesure - * - * @return void */ protected function checkPhpVersion() { @@ -77,8 +73,6 @@ protected function checkPhpVersion() /** * Check the minimum version requirement of Node installed - * - * @return void */ protected function checkNodeVersion() { @@ -93,8 +87,6 @@ protected function checkNodeVersion() /** * Check the minimum version requirement for Npm - * - * @return void */ protected function checkNpmVersion() { @@ -110,8 +102,6 @@ protected function checkNpmVersion() /** * List all sprinkles defined in the Sprinkles schema file, * making sure this file exist at the same time - * - * @return void */ protected function listSprinkles() { @@ -137,8 +127,6 @@ protected function listSprinkles() /** * Check the database connexion and setup the `.env` file if we can't * connect and there's no one found. - * - * @return void */ protected function checkDatabase() { @@ -157,8 +145,6 @@ protected function checkDatabase() /** * Display database config as for debug purposes - * - * @return void */ protected function showConfig() { diff --git a/app/sprinkles/core/src/Bakery/MigrateCommand.php b/app/sprinkles/core/src/Bakery/MigrateCommand.php index ffafbac3a..bfbe547a4 100644 --- a/app/sprinkles/core/src/Bakery/MigrateCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateCommand.php @@ -9,7 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; use UserFrosting\System\Bakery\ConfirmableTrait; @@ -25,7 +24,7 @@ class MigrateCommand extends BaseCommand use ConfirmableTrait; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -39,7 +38,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -74,10 +73,10 @@ protected function execute(InputInterface $input, OutputInterface $output) } /** - * Setup migrator and the shared options between other command + * Setup migrator and the shared options between other command * - * @param InputInterface $input - * @return \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator The migrator instance + * @param InputInterface $input + * @return \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator The migrator instance */ protected function setupMigrator(InputInterface $input) { diff --git a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php index b82f99ba5..7d95f8d6c 100644 --- a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php @@ -9,7 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use UserFrosting\Sprinkle\Core\Bakery\MigrateCommand; @@ -22,7 +21,7 @@ class MigrateRefreshCommand extends MigrateCommand { /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -34,7 +33,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php index bfff71ae9..cb059d34d 100644 --- a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php @@ -9,7 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use UserFrosting\Sprinkle\Core\Bakery\MigrateCommand; @@ -22,7 +21,7 @@ class MigrateResetCommand extends MigrateCommand { /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -35,7 +34,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -50,9 +49,9 @@ protected function execute(InputInterface $input, OutputInterface $output) } /** - * Reset the whole database to an empty state by rolling back all migrations + * Reset the whole database to an empty state by rolling back all migrations * - * @param InputInterface $input + * @param InputInterface $input */ protected function performReset(InputInterface $input) { @@ -90,9 +89,9 @@ protected function performReset(InputInterface $input) } /** - * Hard reset the whole database to an empty state by dropping all tables + * Hard reset the whole database to an empty state by dropping all tables * - * @param InputInterface $input + * @param InputInterface $input */ protected function performHardReset(InputInterface $input) { diff --git a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php index 5a47dff93..44bbf618c 100644 --- a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php @@ -9,7 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use UserFrosting\Sprinkle\Core\Bakery\MigrateCommand; @@ -22,7 +21,7 @@ class MigrateRollbackCommand extends MigrateCommand { /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -36,7 +35,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php index 6169f1898..d4b1c60e6 100644 --- a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php @@ -10,7 +10,6 @@ use Illuminate\Support\Collection; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; @@ -23,7 +22,7 @@ class MigrateStatusCommand extends BaseCommand { /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -34,7 +33,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/RouteListCommand.php b/app/sprinkles/core/src/Bakery/RouteListCommand.php index 5233b68e7..95ccddf22 100644 --- a/app/sprinkles/core/src/Bakery/RouteListCommand.php +++ b/app/sprinkles/core/src/Bakery/RouteListCommand.php @@ -31,7 +31,7 @@ class RouteListCommand extends BaseCommand protected $headers = ['Method', 'URI', 'Name', 'Action']; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -45,7 +45,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index 4d8988112..117c2163c 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -31,7 +31,7 @@ class SeedCommand extends BaseCommand protected $seeder; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -43,7 +43,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/SeedListCommand.php b/app/sprinkles/core/src/Bakery/SeedListCommand.php index 8a951bb34..8dc8978d9 100644 --- a/app/sprinkles/core/src/Bakery/SeedListCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedListCommand.php @@ -21,7 +21,7 @@ class SeedListCommand extends BaseCommand { /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -31,7 +31,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/SetupCommand.php b/app/sprinkles/core/src/Bakery/SetupCommand.php index 7cbe41230..dbb3700ae 100644 --- a/app/sprinkles/core/src/Bakery/SetupCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupCommand.php @@ -20,7 +20,7 @@ class SetupCommand extends BaseCommand { /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -30,7 +30,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/SetupDbCommand.php b/app/sprinkles/core/src/Bakery/SetupDbCommand.php index 39fadaad8..08c946cca 100644 --- a/app/sprinkles/core/src/Bakery/SetupDbCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupDbCommand.php @@ -29,7 +29,7 @@ class SetupDbCommand extends BaseCommand protected $envPath = \UserFrosting\APP_DIR. '/.env'; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -46,7 +46,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php index 9db4c2aa2..d07cbad16 100644 --- a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php @@ -32,7 +32,7 @@ class SetupEnvCommand extends BaseCommand protected $modeKey = 'UF_MODE'; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -43,7 +43,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php index 0288ff8b8..ffb201596 100644 --- a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php @@ -43,7 +43,7 @@ class SetupSmtpCommand extends BaseCommand const Setup_None = 'No email support'; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -57,7 +57,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/sprinkles/core/src/Controller/CoreController.php b/app/sprinkles/core/src/Controller/CoreController.php index 0485758be..36c9ee37a 100644 --- a/app/sprinkles/core/src/Controller/CoreController.php +++ b/app/sprinkles/core/src/Controller/CoreController.php @@ -25,6 +25,9 @@ class CoreController extends SimpleController * * By default, this is the page that non-authenticated users will first see when they navigate to your website's root. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ public function pageIndex(Request $request, Response $response, $args) { @@ -35,6 +38,9 @@ public function pageIndex(Request $request, Response $response, $args) * Renders a sample "about" page for UserFrosting. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ public function pageAbout(Request $request, Response $response, $args) { @@ -45,6 +51,9 @@ public function pageAbout(Request $request, Response $response, $args) * Renders terms of service page. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ public function pageLegal(Request $request, Response $response, $args) { @@ -55,6 +64,9 @@ public function pageLegal(Request $request, Response $response, $args) * Renders privacy page. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ public function pagePrivacy(Request $request, Response $response, $args) { @@ -66,6 +78,9 @@ public function pagePrivacy(Request $request, Response $response, $args) * * The alert stream contains messages which have been generated by calls to `MessageStream::addMessage` and `MessageStream::addMessageTranslated`. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ public function jsonAlerts(Request $request, Response $response, $args) { @@ -75,6 +90,9 @@ public function jsonAlerts(Request $request, Response $response, $args) /** * Handle all requests for raw assets. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args */ public function getAsset(Request $request, Response $response, $args) { diff --git a/app/sprinkles/core/src/Database/Builder.php b/app/sprinkles/core/src/Database/Builder.php index eba79df6e..7f75d3abe 100644 --- a/app/sprinkles/core/src/Database/Builder.php +++ b/app/sprinkles/core/src/Database/Builder.php @@ -7,7 +7,6 @@ */ namespace UserFrosting\Sprinkle\Core\Database; -use Illuminate\Database\Capsule\Manager as DB; use Illuminate\Database\Query\Builder as LaravelBuilder; /** @@ -17,14 +16,17 @@ */ class Builder extends LaravelBuilder { + /** + * @var array List of excluded columns + */ protected $excludedColumns = null; /** * Perform a "begins with" pattern match on a specified column in a query. * - * @param $query - * @param $field string The column to match - * @param $value string The value to match + * @param string $field The column to match + * @param string $value The value to match + * @return self */ public function beginsWith($field, $value) { @@ -34,9 +36,9 @@ public function beginsWith($field, $value) /** * Perform an "ends with" pattern match on a specified column in a query. * - * @param $query - * @param $field string The column to match - * @param $value string The value to match + * @param string $field The column to match + * @param string $value The value to match + * @return self */ public function endsWith($field, $value) { @@ -46,8 +48,8 @@ public function endsWith($field, $value) /** * Add columns to be excluded from the query. * - * @param $value array|string The column(s) to exclude - * @return $this + * @param array|string $column The column(s) to exclude + * @return self */ public function exclude($column) { @@ -60,9 +62,10 @@ public function exclude($column) /** * Perform a pattern match on a specified column in a query. - * @param $query - * @param $field string The column to match - * @param $value string The value to match + * + * @param string $field The column to match + * @param string $value The value to match + * @return self */ public function like($field, $value) { @@ -71,9 +74,10 @@ public function like($field, $value) /** * Perform a pattern match on a specified column in a query. - * @param $query - * @param $field string The column to match - * @param $value string The value to match + * + * @param string $field The column to match + * @param string $value The value to match + * @return self */ public function orLike($field, $value) { @@ -83,7 +87,7 @@ public function orLike($field, $value) /** * Execute the query as a "select" statement. * - * @param array $columns + * @param array $columns * @return \Illuminate\Support\Collection */ public function get($columns = ['*']) @@ -190,6 +194,7 @@ protected function getQualifiedColumnNames($table = null) * Fully qualify any unqualified columns in a list with this builder's table name. * * @param array $columns + * @param string $table * @return array */ protected function convertColumnsToFullyQualified($columns, $table = null) diff --git a/app/sprinkles/core/src/Database/EloquentBuilder.php b/app/sprinkles/core/src/Database/EloquentBuilder.php index 00ceab8c7..4066825ac 100644 --- a/app/sprinkles/core/src/Database/EloquentBuilder.php +++ b/app/sprinkles/core/src/Database/EloquentBuilder.php @@ -22,7 +22,7 @@ class EloquentBuilder extends LaravelEloquentBuilder * Add subselect queries to sum the relations. * * @param mixed $relations - * @return $this + * @return self */ public function withSum($relations) { @@ -35,7 +35,7 @@ public function withSum($relations) * Add subselect queries to max the relations. * * @param mixed $relations - * @return $this + * @return self */ public function withMax($relations) { @@ -48,7 +48,7 @@ public function withMax($relations) * Add subselect queries to min the relations. * * @param mixed $relations - * @return $this + * @return self */ public function withMin($relations) { @@ -61,7 +61,7 @@ public function withMin($relations) * Add subselect queries to min the relations. * * @param mixed $relations - * @return $this + * @return self */ public function withAvg($relations) { @@ -75,7 +75,7 @@ public function withAvg($relations) * * @param array $relations * @param string $function - * @return $this + * @return self */ public function withAggregate($relations, $function = 'COUNT') { diff --git a/app/sprinkles/core/src/Database/Migration.php b/app/sprinkles/core/src/Database/Migration.php index c990284f6..ce6071e4e 100644 --- a/app/sprinkles/core/src/Database/Migration.php +++ b/app/sprinkles/core/src/Database/Migration.php @@ -12,13 +12,12 @@ /** * Abstract Migration class. * - * @abstract * @author Louis Charette */ abstract class Migration { /** - * @var Illuminate\Database\Schema\Builder $schema + * @var \Illuminate\Database\Schema\Builder $schema */ protected $schema; @@ -31,11 +30,9 @@ abstract class Migration //public static $dependencies = []; /** - * __construct function. + * Create a new migration instance * - * @access public - * @param Illuminate\Database\Schema\Builder $schema - * @return void + * @param \Illuminate\Database\Schema\Builder|null $schema */ public function __construct(Builder $schema = null) { diff --git a/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php b/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php index dae95ce53..6bdac0fc8 100644 --- a/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php +++ b/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php @@ -8,7 +8,6 @@ namespace UserFrosting\Sprinkle\Core\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration; /** @@ -16,13 +15,12 @@ * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class SessionsTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -39,7 +37,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php b/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php index e5af704fb..f13a8c80d 100644 --- a/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php +++ b/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php @@ -8,20 +8,18 @@ namespace UserFrosting\Sprinkle\Core\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration; /** * Throttles table migration * Version 4.0.0 * - * @extends Migration * @author Alex Weissman (https://alexanderweissman.com) */ class ThrottlesTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public function up() { @@ -43,7 +41,7 @@ public function up() } /** - * {@inheritDoc} + * {@inheritdoc} */ public function down() { diff --git a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php index d80144c70..ef7736add 100644 --- a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php +++ b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php @@ -40,7 +40,6 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface * * @param Capsule $db * @param string $table - * @return void */ public function __construct(Capsule $db, $table = "migrations") { @@ -108,7 +107,6 @@ public function getLast() * @param string $file * @param int $batch * @param string $sprinkle - * @return void */ public function log($file, $batch, $sprinkle = "") { @@ -121,7 +119,6 @@ public function log($file, $batch, $sprinkle = "") * Remove a migration from the log. * * @param string $migration - * @return void */ public function delete($migration) { @@ -150,8 +147,6 @@ public function getLastBatchNumber() /** * Create the migration repository data store. - * - * @return void */ public function createRepository() { @@ -167,9 +162,7 @@ public function createRepository() } /** - * Delete the migration repository data store - * - * @return void + * Delete the migration repository data store */ public function deleteRepository() { @@ -217,9 +210,9 @@ public function getConnection() } /** - * Set the information source to gather data. + * Set the information source to gather data. * - * @param string $name The source name + * @param string $name The source name */ public function setSource($name) { diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php index af337ab4b..49647ef1d 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php @@ -48,10 +48,10 @@ class MigrationDependencyAnalyser protected $analysed = false; /** - * Constructor + * Constructor * - * @param array $pending The pending migrations - * @param array $installed The installed migrations + * @param array $pending The pending migrations + * @param array $installed The installed migrations */ public function __construct(array $pending = [], array $installed = []) { @@ -60,9 +60,7 @@ public function __construct(array $pending = [], array $installed = []) } /** - * Analyse the dependencies - * - * @return void + * Analyse the dependencies */ public function analyse() { @@ -80,16 +78,16 @@ public function analyse() } /** - * Validate if a migration is fulfillable. - * N.B.: The key element here is the recursion while validating the - * dependencies. This is very important as the order the migrations needs - * to be run is defined by this recursion. By waiting for the dependency - * to be marked as fulfillable to mark the parent as fulfillable, the - * parent class will be automatocally placed after it's dependencies - * in the `fullfillable` property. + * Validate if a migration is fulfillable. + * N.B.: The key element here is the recursion while validating the + * dependencies. This is very important as the order the migrations needs + * to be run is defined by this recursion. By waiting for the dependency + * to be marked as fulfillable to mark the parent as fulfillable, the + * parent class will be automatocally placed after it's dependencies + * in the `fullfillable` property. * - * @param string $migrationName The migration classname - * @return bool True/False if the migration is fulfillable + * @param string $migrationName The migration classname + * @return bool True/False if the migration is fulfillable */ protected function validateClassDependencies($migrationName) { @@ -134,9 +132,9 @@ protected function validateClassDependencies($migrationName) } /** - * Return the fulfillable list. Analyse the stack if not done already + * Return the fulfillable list. Analyse the stack if not done already * - * @return array + * @return array */ public function getFulfillable() { @@ -148,9 +146,9 @@ public function getFulfillable() } /** - * Return the fulfillable list. Analyse the stack if not done already + * Return the fulfillable list. Analyse the stack if not done already * - * @return array + * @return array */ public function getUnfulfillable() { @@ -162,10 +160,10 @@ public function getUnfulfillable() } /** - * Mark a dependency as fulfillable. Removes it from the pending list and add it to the fulfillable list + * Mark a dependency as fulfillable. Removes it from the pending list and add it to the fulfillable list * - * @param string $migration The migration classname - * @return bool True, it's fulfillable + * @param string $migration The migration classname + * @return bool True, it's fulfillable */ protected function markAsFulfillable($migration) { @@ -174,10 +172,10 @@ protected function markAsFulfillable($migration) } /** - * Mark a dependency as unfulfillable. Removes it from the pending list and add it to the unfulfillable list + * Mark a dependency as unfulfillable. Removes it from the pending list and add it to the unfulfillable list * - * @param string $migration The migration classname - * @return bool False, it's not fullfillable + * @param string $migration The migration classname + * @return bool False, it's not fullfillable */ protected function markAsUnfulfillable($migration) { @@ -186,11 +184,11 @@ protected function markAsUnfulfillable($migration) } /** - * Returns the migration dependency list - * Also handles the old deprecated behaviour where dependencies where not in a static property + * Returns the migration dependency list + * Also handles the old deprecated behaviour where dependencies where not in a static property * - * @param string $migration The migration class - * @return array The dependency list + * @param string $migration The migration class + * @return array The dependency list */ protected function getMigrationDependencies($migration) { diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php index 9907412dc..d55310508 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php @@ -17,9 +17,9 @@ interface MigrationLocatorInterface { /** - * Loop all the available sprinkles and return a list of their migrations + * Loop all the available sprinkles and return a list of their migrations * - * @return array A list of all the migration files found for every sprinkle + * @return array A list of all the migration files found for every sprinkle */ public function getMigrations(); } diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php index e2dac954c..627e0e6e3 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php @@ -44,7 +44,6 @@ public function getLast(); * * @param string $file * @param int $batch - * @return void */ public function log($file, $batch); @@ -52,7 +51,6 @@ public function log($file, $batch); * Remove a migration from the log. * * @param string $migration - * @return void */ public function delete($migration); @@ -72,15 +70,11 @@ public function getLastBatchNumber(); /** * Create the migration repository data store. - * - * @return void */ public function createRepository(); /** - * Delete the migration repository data store - * - * @return void + * Delete the migration repository data store */ public function deleteRepository(); diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php index 231ed7b73..d263ae4ed 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php @@ -20,10 +20,10 @@ class MigrationRollbackDependencyAnalyser extends MigrationDependencyAnalyser { /** - * Constructor + * Constructor * - * @param array $installed The installed migrations - * @param array $rollback The migrations to rollback + * @param array $installed The installed migrations + * @param array $rollback The migrations to rollback */ public function __construct(array $installed = [], array $rollback = []) { @@ -32,14 +32,14 @@ public function __construct(array $installed = [], array $rollback = []) } /** - * Received each installed migrations and determine if it depends on the - * migrations we want to delete (rollback). It can if no other installed - * migrations depends on it. In this context, fulfillable/unfulfillable - * represent the same thing as "up" dependencies. fulfillable can be - * rolledback, unfulfillable cannot. + * Received each installed migrations and determine if it depends on the + * migrations we want to delete (rollback). It can if no other installed + * migrations depends on it. In this context, fulfillable/unfulfillable + * represent the same thing as "up" dependencies. fulfillable can be + * rolledback, unfulfillable cannot. * - * @param string $migrationName The migration classname - * @return bool True/False if the migration is fulfillable + * @param string $migrationName The migration classname + * @return bool True/False if the migration is fulfillable */ protected function validateClassDependencies($migrationName) { diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index c74f24522..dc32acd20 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -125,7 +125,6 @@ public function pendingMigrations($available, $ran) * * @param array $migrations An array of migrations classes names to be run (unsorted, unvalidated) * @param array $options The options for the current operation [step, pretend] - * @return void */ protected function runPending(array $migrations, array $options = []) { @@ -158,7 +157,6 @@ protected function runPending(array $migrations, array $options = []) * @param string $migrationClass The migration class name * @param int $batch The current bacth number * @param bool $pretend If this operation should be pretended / faked - * @return void */ protected function runUp($migrationClass, $batch, $pretend) { @@ -352,7 +350,6 @@ public function reset($pretend = false) * * @param string $migrationClass The migration class name * @param bool $pretend Is the operation should be pretended - * @return void */ protected function runDown($migrationClass, $pretend) { @@ -380,7 +377,6 @@ protected function runDown($migrationClass, $pretend) * * @param object $migration The migration instance * @param string $method The method used [up, down] - * @return void */ protected function runMigration($migration, $method) { @@ -403,7 +399,6 @@ protected function runMigration($migration, $method) * * @param object $migration The migration instance * @param string $method The method used [up, down] - * @return void */ protected function pretendToRun($migration, $method) { @@ -553,7 +548,6 @@ protected function getSchemaGrammar() * Raise a note event for the migrator. * * @param string $message The message - * @return void */ protected function note($message) { diff --git a/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php b/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php index 4fe9a309c..1c022bd1f 100644 --- a/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php +++ b/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php @@ -9,10 +9,6 @@ use Illuminate\Support\Arr; use Illuminate\Support\Str; - -use Illuminate\Database\Eloquent\Relations\MorphMany; -use Illuminate\Database\Eloquent\Relations\MorphToMany; - use UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyConstrained; use UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough; use UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyUnique; @@ -38,7 +34,9 @@ trait HasRelationships /** * Overrides the default Eloquent hasMany relationship to return a HasManySyncable. * - * {@inheritDoc} + * @param string $related + * @param string $foreignKey + * @param string $localKey * @return \UserFrosting\Sprinkle\Core\Database\Relations\HasManySyncable */ public function hasMany($related, $foreignKey = null, $localKey = null) @@ -57,7 +55,11 @@ public function hasMany($related, $foreignKey = null, $localKey = null) /** * Overrides the default Eloquent morphMany relationship to return a MorphManySyncable. * - * {@inheritDoc} + * @param string $related + * @param string $name + * @param string $type + * @param string $id + * @param string $localKey * @return \UserFrosting\Sprinkle\Core\Database\Relations\MorphManySyncable */ public function morphMany($related, $name, $type = null, $id = null, $localKey = null) @@ -150,7 +152,11 @@ public function belongsToManyThrough( * Define a unique many-to-many relationship. Similar to a regular many-to-many relationship, but removes duplicate child objects. * Can also be used to implement ternary relationships. * - * {@inheritDoc} + * @param string $related + * @param string $table + * @param string $foreignKey + * @param string $relatedKey + * @param string $relation * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyUnique */ public function belongsToManyUnique($related, $table = null, $foreignKey = null, $relatedKey = null, $relation = null) @@ -186,7 +192,12 @@ public function belongsToManyUnique($related, $table = null, $foreignKey = null, /** * Define a unique morphs-to-many relationship. Similar to a regular morphs-to-many relationship, but removes duplicate child objects. * - * {@inheritDoc} + * @param string $related + * @param string $name + * @param string $table + * @param string $foreignKey + * @param string $otherKey + * @param bool $inverse * @return \UserFrosting\Sprinkle\Core\Database\Relations\MorphToManyUnique */ public function morphToManyUnique($related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false) diff --git a/app/sprinkles/core/src/Database/Models/Model.php b/app/sprinkles/core/src/Database/Models/Model.php index 0d020144c..0c88ac487 100644 --- a/app/sprinkles/core/src/Database/Models/Model.php +++ b/app/sprinkles/core/src/Database/Models/Model.php @@ -7,8 +7,10 @@ */ namespace UserFrosting\Sprinkle\Core\Database\Models; +use Interop\Container\ContainerInterface; use Illuminate\Database\Capsule\Manager as DB; use Illuminate\Database\Eloquent\Model as LaravelModel; +use UserFrosting\Sprinkle\Core\Database\Builder ; use UserFrosting\Sprinkle\Core\Database\Models\Concerns\HasRelationships; /** @@ -97,12 +99,12 @@ public function store() /** * Overrides Laravel's base Model to return our custom Eloquent builder object. * - * @param \UserFrosting\Sprinkles\Core\Database\Builder $query - * @return \UserFrosting\Sprinkles\Core\Database\EloquentBuilder + * @param Builder $query + * @return \UserFrosting\Sprinkle\Core\Database\EloquentBuilder */ public function newEloquentBuilder($query) { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; return $classMapper->createInstance( @@ -114,11 +116,11 @@ public function newEloquentBuilder($query) /** * Overrides Laravel's base Model to return our custom query builder object. * - * @return \UserFrosting\Sprinkles\Core\Database\Builder + * @return Builder */ protected function newBaseQueryBuilder() { - /** @var UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ + /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ $classMapper = static::$ci->classMapper; $connection = $this->getConnection(); @@ -147,6 +149,7 @@ public function export() * * @deprecated since 4.1.8 setFetchMode is no longer available as of Laravel 5.4. * @link https://github.com/laravel/framework/issues/17728 + * @return Builder */ public static function queryBuilder() { diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php index d652b562a..2a6329699 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php @@ -18,12 +18,12 @@ * * @deprecated since 4.1.6 * @author Alex Weissman (https://alexanderweissman.com) - * @link https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php + * @see https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php */ class BelongsToManyConstrained extends BelongsToMany { /** - * @var The pivot foreign key on which to constrain the result sets for this relation. + * @var string The pivot foreign key on which to constrain the result sets for this relation. */ protected $constraintKey; @@ -37,7 +37,6 @@ class BelongsToManyConstrained extends BelongsToMany * @param string $foreignKey * @param string $relatedKey * @param string $relationName - * @return void */ public function __construct(Builder $query, Model $parent, $constraintKey, $table, $foreignKey, $relatedKey, $relationName = null) { @@ -49,12 +48,11 @@ public function __construct(Builder $query, Model $parent, $constraintKey, $tabl * Set the constraints for an eager load of the relation. * * @param array $models - * @return void */ public function addEagerConstraints(array $models) { // To make the query more efficient, we only bother querying related models if their pivot key value - // matches the pivot key value of one of the parent models. + // matches the pivot key value of one of the parent models. $pivotKeys = $this->getPivotKeys($models, $this->constraintKey); $this->query->whereIn($this->getQualifiedForeignKeyName(), $this->getKeys($models)) ->whereIn($this->constraintKey, $pivotKeys); @@ -62,6 +60,10 @@ public function addEagerConstraints(array $models) /** * Gets a list of unique pivot key values from an array of models. + * + * @param array $models + * @param string $pivotKey + * @return array */ protected function getPivotKeys(array $models, $pivotKey) { @@ -76,7 +78,7 @@ protected function getPivotKeys(array $models, $pivotKey) * Match the eagerly loaded results to their parents, constraining the results by matching the values of $constraintKey * in the parent object to the child objects. * - * @link Called in https://github.com/laravel/framework/blob/2f4135d8db5ded851d1f4f611124c53b768a3c08/src/Illuminate/Database/Eloquent/Builder.php + * @see Called in https://github.com/laravel/framework/blob/2f4135d8db5ded851d1f4f611124c53b768a3c08/src/Illuminate/Database/Eloquent/Builder.php * @param array $models * @param \Illuminate\Database\Eloquent\Collection $results * @param string $relation @@ -106,6 +108,7 @@ public function match(array $models, Collection $results, $relation) /** * Filter an array of models, only taking models whose $constraintKey value matches $pivotValue. * + * @param array $items * @param mixed $pivotValue * @return array */ diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php index 33be507d4..f27e5dea0 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php @@ -18,7 +18,7 @@ * A BelongsToMany relationship that queries through an additional intermediate model. * * @author Alex Weissman (https://alexanderweissman.com) - * @link https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php + * @see https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php */ class BelongsToManyThrough extends BelongsToMany { @@ -41,7 +41,6 @@ class BelongsToManyThrough extends BelongsToMany * @param string $foreignKey * @param string $relatedKey * @param string $relationName - * @return void */ public function __construct(Builder $query, Model $parent, Relation $intermediateRelation, $table, $foreignKey, $relatedKey, $relationName = null) { @@ -78,7 +77,7 @@ public function getExistenceCompareKey() * * @param string $viaRelationName * @param callable $viaCallback - * @return $this + * @return self */ public function withVia($viaRelationName = null, $viaCallback = null) { @@ -102,7 +101,6 @@ public function withVia($viaRelationName = null, $viaCallback = null) * Set the constraints for an eager load of the relation. * * @param array $models - * @return void */ public function addEagerConstraints(array $models) { @@ -115,7 +113,7 @@ public function addEagerConstraints(array $models) /** * Set the where clause for the relation query. * - * @return $this + * @return self */ protected function addWhereConstraints() { @@ -175,7 +173,6 @@ public function match(array $models, Collection $results, $relation) * Unset tertiary pivots on a collection or array of models. * * @param \Illuminate\Database\Eloquent\Collection $models - * @return void */ protected function unsetTertiaryPivots(Collection $models) { @@ -188,7 +185,7 @@ protected function unsetTertiaryPivots(Collection $models) * Set the join clause for the relation query. * * @param \Illuminate\Database\Eloquent\Builder|null $query - * @return $this + * @return self */ protected function performJoin($query = null) { diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php index f256f1782..6423ba713 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php @@ -14,7 +14,7 @@ * A BelongsToMany relationship that reduces the related members to a unique (by primary key) set. * * @author Alex Weissman (https://alexanderweissman.com) - * @link https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php + * @see https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/BelongsToMany.php */ class BelongsToManyUnique extends BelongsToMany { diff --git a/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php b/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php index 278b76276..8855df2ac 100644 --- a/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php +++ b/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php @@ -7,10 +7,6 @@ */ namespace UserFrosting\Sprinkle\Core\Database\Relations\Concerns; -use Illuminate\Database\Eloquent\Model; -use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Eloquent\Collection; - /** * Implements the `sync` method for HasMany relationships. * @@ -86,7 +82,7 @@ public function sync($data, $deleting = true, $forceCreate = false, $relatedKeyN ->where($relatedKeyName, $id) ->update($row); } - + $changes['updated'] = $this->castKeys($updateIds); // Insert the new rows @@ -105,7 +101,6 @@ public function sync($data, $deleting = true, $forceCreate = false, $relatedKeyN return $changes; } - /** * Cast the given keys to integers if they are numeric and string otherwise. * @@ -118,7 +113,7 @@ protected function castKeys(array $keys) return $this->castKey($v); }, $keys); } - + /** * Cast the given key to an integer if it is numeric. * diff --git a/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php b/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php index b8ce20344..4b75278af 100644 --- a/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php +++ b/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Query\Expression; /** @@ -21,7 +22,7 @@ trait Unique /** * The related tertiary model instance. * - * @var \Illuminate\Database\Eloquent\Model + * @var Model */ protected $tertiaryRelated = null; @@ -64,7 +65,7 @@ trait Unique * Alias to set the "offset" value of the query. * * @param int $value - * @return $this + * @return self */ public function skip($value) { @@ -77,7 +78,7 @@ public function skip($value) * @todo Implement for 'unionOffset' as well? (By checking the value of $this->query->getQuery()->unions) * @see \Illuminate\Database\Query\Builder * @param int $value - * @return $this + * @return self */ public function offset($value) { @@ -90,7 +91,7 @@ public function offset($value) * Alias to set the "limit" value of the query. * * @param int $value - * @return $this + * @return self */ public function take($value) { @@ -103,7 +104,7 @@ public function take($value) * @todo Implement for 'unionLimit' as well? (By checking the value of $this->query->getQuery()->unions) * @see \Illuminate\Database\Query\Builder * @param int $value - * @return $this + * @return self */ public function limit($value) { @@ -141,11 +142,11 @@ public function withOffset($value) /** * Add a query to load the nested tertiary models for this relationship. * - * @param \Illuminate\Database\Eloquent\Model $tertiaryRelated - * @param string $tertiaryRelationName - * @param string $tertiaryKey - * @param callable $tertiaryCallback - * @return $this + * @param string $tertiaryRelated + * @param string $tertiaryRelationName + * @param string $tertiaryKey + * @param callable $tertiaryCallback + * @return self */ public function withTertiary($tertiaryRelated, $tertiaryRelationName = null, $tertiaryKey = null, $tertiaryCallback = null) { @@ -187,9 +188,9 @@ public function count() * Add the constraints for a relationship count query. * * @see \Illuminate\Database\Eloquent\Relations\Relation - * @param \Illuminate\Database\Eloquent\Builder $query - * @param \Illuminate\Database\Eloquent\Builder $parentQuery - * @return \Illuminate\Database\Eloquent\Builder + * @param Builder $query + * @param Builder $parentQuery + * @return Builder */ public function getRelationExistenceCountQuery(Builder $query, Builder $parentQuery) { @@ -202,7 +203,7 @@ public function getRelationExistenceCountQuery(Builder $query, Builder $parentQu * Match the eagerly loaded results to their parents * * @param array $models - * @param \Illuminate\Database\Eloquent\Collection $results + * @param Collection $results * @param string $relation * @return array */ @@ -241,7 +242,7 @@ public function match(array $models, Collection $results, $relation) * and matching up any tertiary models. * * @param array $columns - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection */ public function get($columns = ['*']) { @@ -258,10 +259,10 @@ public function get($columns = ['*']) * If we are applying either a limit or offset, we'll first determine a limited/offset list of model ids * to select from in the final query. * - * @param \Illuminate\Database\Eloquent\Builder $query + * @param Builder $query * @param int $limit * @param int $offset - * @return \Illuminate\Database\Eloquent\Builder + * @return Builder */ public function getPaginatedQuery(Builder $query, $limit = null, $offset = null) { @@ -306,7 +307,7 @@ public function getPaginatedQuery(Builder $query, $limit = null, $offset = null) * This is not what we want here though, because our get() method removes records before * `match` has a chance to build out the substructures. * - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection */ public function getEager() { @@ -319,7 +320,7 @@ public function getEager() * * @param array $columns * @param bool $condenseModels - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection */ public function getModels($columns = ['*'], $condenseModels = true) { @@ -392,7 +393,7 @@ protected function condenseModels(array $models) * that maps parent ids to arrays of related ids, which in turn map to arrays * of tertiary models corresponding to each relationship. * - * @param \Illuminate\Database\Eloquent\Collection $results + * @param Collection $results * @param string $parentKey * @return array */ @@ -439,11 +440,11 @@ protected function buildDictionary(Collection $results, $parentKey = null) if (!is_null($tertiaryKeyValue)) { $tertiaryModel = clone $tertiaryModels[$tertiaryKeyValue]; - + // We also transfer the pivot relation at this point, since we have already coalesced // any tertiary models into the nested dictionary. $this->transferPivotsToTertiary($result, $tertiaryModel); - + $nestedTertiaryDictionary[$parentKeyValue][$result->getKey()][] = $tertiaryModel; } } @@ -479,6 +480,12 @@ protected function buildTertiaryDictionary(array $models) return $dictionary; } + /** + * Transfer the pivot to the tertiary model + * + * @param Model $model + * @param Model $tertiaryModel + */ protected function transferPivotsToTertiary($model, $tertiaryModel) { $pivotAttributes = []; @@ -500,7 +507,7 @@ protected function transferPivotsToTertiary($model, $tertiaryModel) * Get the tertiary models for the relationship. * * @param array $models - * @return \Illuminate\Database\Eloquent\Collection + * @return Collection */ protected function getTertiaryModels(array $models) { @@ -529,8 +536,7 @@ protected function getTertiaryModels(array $models) * Match a collection of child models into a collection of parent models using a dictionary. * * @param array $dictionary - * @param \Illuminate\Database\Eloquent\Collection $results - * @return void + * @param Collection $results */ protected function matchTertiaryModels(array $dictionary, Collection $results) { @@ -549,8 +555,7 @@ protected function matchTertiaryModels(array $dictionary, Collection $results) /** * Unset tertiary pivots on a collection or array of models. * - * @param \Illuminate\Database\Eloquent\Collection $models - * @return void + * @param Collection $models */ protected function unsetTertiaryPivots(Collection $models) { diff --git a/app/sprinkles/core/src/Database/Relations/HasManySyncable.php b/app/sprinkles/core/src/Database/Relations/HasManySyncable.php index bcf2a9d4e..cd7e756b1 100644 --- a/app/sprinkles/core/src/Database/Relations/HasManySyncable.php +++ b/app/sprinkles/core/src/Database/Relations/HasManySyncable.php @@ -14,7 +14,7 @@ * A HasMany relationship that supports a `sync` method. * * @author Alex Weissman (https://alexanderweissman.com) - * @link https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/HasMany.php + * @see https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/HasMany.php */ class HasManySyncable extends HasMany { diff --git a/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php b/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php index 27861932a..2644b8fa9 100644 --- a/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php +++ b/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php @@ -14,7 +14,7 @@ * A MorphMany relationship that constrains on the value of an additional foreign key in the pivot table. * * @author Alex Weissman (https://alexanderweissman.com) - * @link https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/MorphMany.php + * @see https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/MorphMany.php */ class MorphManySyncable extends MorphMany { diff --git a/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php b/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php index cc9a03f93..7e488632f 100644 --- a/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php +++ b/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php @@ -14,7 +14,7 @@ * A MorphToMany relationship that reduces the related members to a unique (by primary key) set. * * @author Alex Weissman (https://alexanderweissman.com) - * @link https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/MorphToMany.php + * @see https://github.com/laravel/framework/blob/5.4/src/Illuminate/Database/Eloquent/Relations/MorphToMany.php */ class MorphToManyUnique extends MorphToMany { diff --git a/app/sprinkles/core/src/Database/Seeder/BaseSeed.php b/app/sprinkles/core/src/Database/Seeder/BaseSeed.php index 2fd5c6f42..ce308e69a 100644 --- a/app/sprinkles/core/src/Database/Seeder/BaseSeed.php +++ b/app/sprinkles/core/src/Database/Seeder/BaseSeed.php @@ -19,14 +19,14 @@ abstract class BaseSeed implements SeedInterface { /** - * @var ContainerInterface $ci + * @var ContainerInterface $ci */ protected $ci; /** - * Constructor + * Constructor * - * @param ContainerInterface $ci + * @param ContainerInterface $ci */ public function __construct(ContainerInterface $ci) { @@ -34,9 +34,7 @@ public function __construct(ContainerInterface $ci) } /** - * Function used to execute the seed - * - * @return void + * Function used to execute the seed */ abstract public function run(); } diff --git a/app/sprinkles/core/src/Database/Seeder/SeedInterface.php b/app/sprinkles/core/src/Database/Seeder/SeedInterface.php index 1f8710b8c..31b5e3043 100644 --- a/app/sprinkles/core/src/Database/Seeder/SeedInterface.php +++ b/app/sprinkles/core/src/Database/Seeder/SeedInterface.php @@ -14,5 +14,8 @@ */ interface SeedInterface { + /** + * Run the seed + */ public function run(); } diff --git a/app/sprinkles/core/src/Database/Seeder/Seeder.php b/app/sprinkles/core/src/Database/Seeder/Seeder.php index f3f335c05..12eeaf099 100644 --- a/app/sprinkles/core/src/Database/Seeder/Seeder.php +++ b/app/sprinkles/core/src/Database/Seeder/Seeder.php @@ -31,9 +31,9 @@ class Seeder protected $scheme = 'seeds://'; /** - * Class Constructor + * Class Constructor * - * @param ContainerInterface $ci + * @param ContainerInterface $ci */ public function __construct(ContainerInterface $ci) { @@ -41,9 +41,9 @@ public function __construct(ContainerInterface $ci) } /** - * Loop all the available sprinkles and return a list of their seeds + * Loop all the available sprinkles and return a list of their seeds * - * @return array An array of all the seed classes found for every sprinkle + * @return array An array of all the seed classes found for every sprinkle */ public function getSeeds() { @@ -104,7 +104,6 @@ public function getSeedClass($name) * Execute a seed class * * @param SeedInterface $seed The seed to execute - * @return void */ public function executeSeed(SeedInterface $seed) { @@ -117,7 +116,7 @@ public function executeSeed(SeedInterface $seed) * @param array $seedFiles List of seeds file * @return array */ - protected function loadSeeders($seedFiles) + protected function loadSeeders(array $seedFiles) { $seeds = []; foreach ($seedFiles as $seedFile) { @@ -127,10 +126,10 @@ protected function loadSeeders($seedFiles) } /** - * Return an array of seed details inclusing the classname and the sprinkle name + * Return an array of seed details inclusing the classname and the sprinkle name * - * @param Resource $file The seed file - * @return array The details about a seed file [name, class, sprinkle] + * @param Resource $file The seed file + * @return array The details about a seed file [name, class, sprinkle] */ protected function getSeedDetails(Resource $file) { diff --git a/app/sprinkles/core/src/Error/ExceptionHandlerManager.php b/app/sprinkles/core/src/Error/ExceptionHandlerManager.php index 4680da5f3..886ee3208 100755 --- a/app/sprinkles/core/src/Error/ExceptionHandlerManager.php +++ b/app/sprinkles/core/src/Error/ExceptionHandlerManager.php @@ -10,7 +10,6 @@ use Interop\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use UserFrosting\Sprinkle\Core\Handler\ExceptionHandlerInterface; /** * Default UserFrosting application error handler @@ -39,7 +38,7 @@ class ExceptionHandlerManager * Constructor * * @param ContainerInterface $ci The global container object, which holds all your services. - * @param boolean $displayErrorDetails Set to true to display full details + * @param bool $displayErrorDetails Set to true to display full details */ public function __construct(ContainerInterface $ci, $displayErrorDetails = false) { @@ -52,11 +51,10 @@ public function __construct(ContainerInterface $ci, $displayErrorDetails = false * * @param ServerRequestInterface $request The most recent Request object * @param ResponseInterface $response The most recent Response object - * @param Throwable $exception The caught Exception object - * + * @param \Throwable $exception The caught Exception object * @return ResponseInterface */ - public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $exception) + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, \Throwable $exception) { // Default exception handler class $handlerClass = '\UserFrosting\Sprinkle\Core\Error\Handler\ExceptionHandler'; @@ -80,7 +78,7 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res * * @param string $exceptionClass The fully qualified class name of the exception to handle. * @param string $handlerClass The fully qualified class name of the assigned handler. - * @throws InvalidArgumentException If the registered handler fails to implement ExceptionHandlerInterface + * @throws \InvalidArgumentException If the registered handler fails to implement ExceptionHandlerInterface */ public function registerHandler($exceptionClass, $handlerClass) { diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php index 4fdc51da0..757880428 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php @@ -10,7 +10,6 @@ use Interop\Container\ContainerInterface; use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; -use UserFrosting\Sprinkle\Core\Error\Renderer\HtmlRenderer; use UserFrosting\Sprinkle\Core\Error\Renderer\JsonRenderer; use UserFrosting\Sprinkle\Core\Error\Renderer\PlainTextRenderer; use UserFrosting\Sprinkle\Core\Error\Renderer\WhoopsRenderer; @@ -43,12 +42,12 @@ class ExceptionHandler implements ExceptionHandlerInterface protected $response; /** - * @var Throwable + * @var \Throwable */ protected $exception; /** - * @var ErrorRendererInterface + * @var \UserFrosting\Sprinkle\Core\Error\Renderer\ErrorRendererInterface */ protected $renderer = null; @@ -76,14 +75,14 @@ class ExceptionHandler implements ExceptionHandlerInterface * @param ContainerInterface $ci * @param ServerRequestInterface $request The most recent Request object * @param ResponseInterface $response The most recent Response object - * @param Throwable $exception The caught Exception object + * @param \Throwable $exception The caught Exception object * @param bool $displayErrorDetails */ public function __construct( ContainerInterface $ci, ServerRequestInterface $request, ResponseInterface $response, - $exception, + \Throwable $exception, $displayErrorDetails = false ) { $this->ci = $ci; @@ -165,8 +164,6 @@ public function renderGenericResponse() /** * Write to the error log - * - * @return void */ public function writeToErrorLog() { @@ -178,8 +175,6 @@ public function writeToErrorLog() /** * Write user-friendly error messages to the alert message stream. - * - * @return void */ public function writeAlerts() { @@ -194,9 +189,8 @@ public function writeAlerts() * Determine which renderer to use based on content type * Overloaded $renderer from calling class takes precedence over all * - * @return ErrorRendererInterface - * * @throws \RuntimeException + * @return \UserFrosting\Sprinkle\Core\Error\Renderer\ErrorRendererInterface */ protected function determineRenderer() { @@ -265,8 +259,7 @@ protected function determineUserMessages() /** * Monolog logging for errors * - * @param $message - * @return void + * @param string $message */ protected function logError($message) { diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php index a928b6910..3118a653e 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php @@ -18,15 +18,37 @@ */ interface ExceptionHandlerInterface { - public function __construct(ContainerInterface $ci, ServerRequestInterface $request, ResponseInterface $response, $exception, $displayErrorDetails = false); + /** + * @param ContainerInterface $ci + * @param ServerRequestInterface $request + * @param ResponseInterface $response + * @param \Exception $exception + * @param bool $displayErrorDetails + */ + public function __construct(ContainerInterface $ci, ServerRequestInterface $request, ResponseInterface $response, \Exception $exception, $displayErrorDetails = false); + /** + * @return ResponseInterface + */ public function handle(); + /** + * @return ResponseInterface + */ public function renderDebugResponse(); + /** + * @return ResponseInterface + */ public function renderGenericResponse(); + /** + * Write to the error log + */ public function writeToErrorLog(); + /** + * Write user-friendly error messages to the alert message stream. + */ public function writeAlerts(); } diff --git a/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php index 946bda7d7..b31180c7e 100644 --- a/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php @@ -8,6 +8,7 @@ namespace UserFrosting\Sprinkle\Core\Error\Handler; use UserFrosting\Support\Exception\HttpException; +use UserFrosting\Support\Message\UserMessage; /** * Handler for HttpExceptions. @@ -18,8 +19,6 @@ class HttpExceptionHandler extends ExceptionHandler { /** * For HttpExceptions, only write to the error log if the status code is 500 - * - * @return void */ public function writeToErrorLog() { diff --git a/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php index 306feedf3..b99afd6bf 100644 --- a/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php @@ -7,9 +7,8 @@ */ namespace UserFrosting\Sprinkle\Core\Error\Handler; +use Psr\Http\Message\ResponseInterface; use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler; -use UserFrosting\Support\Exception\HttpException; -use UserFrosting\Support\Message\UserMessage; /** * Handler for NotFoundExceptions. @@ -21,7 +20,7 @@ class NotFoundExceptionHandler extends HttpExceptionHandler /** * Custom handling for NotFoundExceptions. Always render a generic response! * - * @return Response + * @return ResponseInterface */ public function handle() { diff --git a/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php b/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php index f065af0af..295e4573a 100644 --- a/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php @@ -7,8 +7,14 @@ */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; use Slim\Http\Body; +/** + * [abstract description] + * @var [type] + */ abstract class ErrorRenderer implements ErrorRendererInterface { /** @@ -22,7 +28,7 @@ abstract class ErrorRenderer implements ErrorRendererInterface protected $response; /** - * @var Exception + * @var \Exception */ protected $exception; @@ -39,10 +45,10 @@ abstract class ErrorRenderer implements ErrorRendererInterface * * @param ServerRequestInterface $request The most recent Request object * @param ResponseInterface $response The most recent Response object - * @param Exception $exception The caught Exception object + * @param \Exception $exception The caught Exception object * @param bool $displayErrorDetails */ - public function __construct($request, $response, $exception, $displayErrorDetails = false) + public function __construct(ServerRequestInterface $request, ResponseInterface $response, \Exception $exception, $displayErrorDetails = false) { $this->request = $request; $this->response = $response; diff --git a/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php b/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php index 7af269ab5..3153e4661 100755 --- a/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php +++ b/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php @@ -7,16 +7,22 @@ */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; + +/** + * ErrorRendererInterface + */ interface ErrorRendererInterface { /** * @param ServerRequestInterface $request The most recent Request object * @param ResponseInterface $response The most recent Response object - * @param Exception $exception The caught Exception object + * @param \Exception $exception The caught Exception object * @param bool $displayErrorDetails */ - public function __construct($request, $response, $exception, $displayErrorDetails = false); - + public function __construct(ServerRequestInterface $request, ResponseInterface $response, \Exception $exception, $displayErrorDetails = false); + /** * @return string */ diff --git a/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php b/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php index 1f3267545..a5b24ceef 100644 --- a/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php @@ -57,10 +57,10 @@ public function render() /** * Render a summary of the exception. * - * @param Exception $exception + * @param \Exception $exception * @return string */ - public function renderException($exception) + public function renderException(\Exception $exception) { $html = sprintf('
Type: %s
', get_class($exception)); @@ -134,7 +134,6 @@ public function renderResponseHeaders() * Render HTML representation of a table of data. * * @param mixed[] $data the array of data to render. - * * @return string */ protected function renderTable($data) diff --git a/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php b/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php index 3adfd459f..223de29cb 100755 --- a/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php @@ -22,7 +22,7 @@ public function render() } /** - * @param $message + * @param string $message * @return string */ public function formatExceptionPayload($message) diff --git a/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php b/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php index a4984fc55..9467fac43 100755 --- a/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php @@ -21,6 +21,10 @@ public function render() return $this->exception->getMessage(); } + /** + * Format Exception Body + * @return string + */ public function formatExceptionBody() { $e = $this->exception; diff --git a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php index 614f3077e..e316af424 100644 --- a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php @@ -8,6 +8,8 @@ namespace UserFrosting\Sprinkle\Core\Error\Renderer; use InvalidArgumentException; +use Psr\Http\Message\ResponseInterface; +use Psr\Http\Message\ServerRequestInterface; use RuntimeException; use Symfony\Component\VarDumper\Cloner\AbstractCloner; use Symfony\Component\VarDumper\Cloner\VarCloner; @@ -112,9 +114,9 @@ class WhoopsRenderer extends ErrorRenderer private $templateHelper; /** - * {@inheritDoc} + * {@inheritdoc} */ - public function __construct($request, $response, $exception, $displayErrorDetails = false) + public function __construct(ServerRequestInterface $request, ResponseInterface $response, \Exception $exception, $displayErrorDetails = false) { $this->request = $request; $this->response = $response; @@ -160,7 +162,7 @@ public function __construct($request, $response, $exception, $displayErrorDetail } /** - * {@inheritDoc} + * {@inheritdoc} */ public function render() { @@ -295,6 +297,7 @@ public function render() * Adds an entry to the list of tables displayed in the template. * The expected data is a simple associative array. Any nested arrays * will be flattened with print_r + * * @param string $label * @param array $data */ @@ -335,8 +338,8 @@ public function addDataTableCallback($label, /* callable */ $callback) /** * blacklist a sensitive value within one of the superglobal arrays. * - * @param $superGlobalName string the name of the superglobal array, e.g. '_GET' - * @param $key string the key within the superglobal + * @param string $superGlobalName The name of the superglobal array, e.g. '_GET' + * @param string $key The key within the superglobal */ public function blacklist($superGlobalName, $key) { @@ -347,6 +350,7 @@ public function blacklist($superGlobalName, $key) * Returns all the extra data tables registered with this handler. * Optionally accepts a 'label' parameter, to only return the data * table under that label. + * * @param string|null $label * @return array[]|callable */ @@ -364,6 +368,7 @@ public function getDataTables($label = null) * Allows to disable all attempts to dynamically decide whether to * handle or return prematurely. * Set this to ensure that the handler will perform no matter what. + * * @param bool|null $value * @return bool|null */ @@ -480,8 +485,7 @@ public function getEditorAjax($filePath, $line) } /** - * @param string $title - * @return void + * @param string $title */ public function setPageTitle($title) { @@ -501,9 +505,7 @@ public function getPageTitle() * resources. * * @throws InvalidArgumentException If $path is not a valid directory - * * @param string $path - * @return void */ public function addResourcePath($path) { @@ -519,8 +521,7 @@ public function addResourcePath($path) /** * Adds a custom css file to be loaded. * - * @param string $name - * @return void + * @param string $name */ public function addCustomCss($name) { @@ -537,7 +538,6 @@ public function getResourcePaths() /** * @deprecated - * * @return string */ public function getResourcesPath() @@ -550,9 +550,7 @@ public function getResourcesPath() /** * @deprecated - * - * @param string $resourcesPath - * @return void + * @param string $resourcesPath */ public function setResourcesPath($resourcesPath) { @@ -657,7 +655,6 @@ protected function getInspector() * for all resources. * * @throws RuntimeException If resource cannot be found in any of the available paths - * * @param string $resource * @return string */ diff --git a/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php b/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php index e963afa13..ec567adc6 100644 --- a/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php +++ b/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php @@ -37,6 +37,7 @@ trait DeterminesContentType * as willdurand/negotiation for any other situation. * * @param ServerRequestInterface $request + * @param bool $ajaxDebug * @return string */ protected function determineContentType(ServerRequestInterface $request, $ajaxDebug = false) diff --git a/app/sprinkles/core/src/Log/DatabaseHandler.php b/app/sprinkles/core/src/Log/DatabaseHandler.php index c78308c36..4aa2dd2d8 100644 --- a/app/sprinkles/core/src/Log/DatabaseHandler.php +++ b/app/sprinkles/core/src/Log/DatabaseHandler.php @@ -9,6 +9,7 @@ use Monolog\Logger; use Monolog\Handler\AbstractProcessingHandler; +use UserFrosting\Sprinkle\Core\Util\ClassMapper; /** * Monolog handler for storing the record to a database. @@ -18,7 +19,7 @@ class DatabaseHandler extends AbstractProcessingHandler { /** - * @var UserFrosting\Sprinkle\Core\Util\ClassMapper + * @var ClassMapper */ protected $classMapper; @@ -32,10 +33,10 @@ class DatabaseHandler extends AbstractProcessingHandler * * @param ClassMapper $classMapper Maps the modelIdentifier to the specific Eloquent model. * @param string $modelIdentifier - * @param int $level The minimum logging level at which this handler will be triggered - * @param Boolean $bubble Whether the messages that are handled can bubble up the stack or not + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ - public function __construct($classMapper, $modelIdentifier, $level = Logger::DEBUG, $bubble = true) + public function __construct(ClassMapper $classMapper, $modelIdentifier, $level = Logger::DEBUG, $bubble = true) { $this->classMapper = $classMapper; $this->modelName = $modelIdentifier; @@ -43,7 +44,7 @@ public function __construct($classMapper, $modelIdentifier, $level = Logger::DEB } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function write(array $record) { diff --git a/app/sprinkles/core/src/Log/MixedFormatter.php b/app/sprinkles/core/src/Log/MixedFormatter.php index beae7889f..0eaaf40e8 100644 --- a/app/sprinkles/core/src/Log/MixedFormatter.php +++ b/app/sprinkles/core/src/Log/MixedFormatter.php @@ -23,9 +23,9 @@ class MixedFormatter extends LineFormatter /** * Return the JSON representation of a value * + * @throws \RuntimeException if encoding fails and errors are not ignored * @param mixed $data * @param bool $ignoreErrors - * @throws \RuntimeException if encoding fails and errors are not ignored * @return string */ protected function toJson($data, $ignoreErrors = false) diff --git a/app/sprinkles/core/src/Mail/MailMessage.php b/app/sprinkles/core/src/Mail/MailMessage.php index 29bcf153d..cd4909693 100644 --- a/app/sprinkles/core/src/Mail/MailMessage.php +++ b/app/sprinkles/core/src/Mail/MailMessage.php @@ -44,6 +44,7 @@ abstract class MailMessage /** * Gets the fully rendered text of the message body. * + * @param array $params * @return string */ abstract public function renderBody($params = []); @@ -51,6 +52,7 @@ abstract public function renderBody($params = []); /** * Gets the fully rendered text of the message subject. * + * @param array $params * @return string */ abstract public function renderSubject($params = []); diff --git a/app/sprinkles/core/src/Mail/StaticMailMessage.php b/app/sprinkles/core/src/Mail/StaticMailMessage.php index 098bbfc86..ebbaa16dd 100644 --- a/app/sprinkles/core/src/Mail/StaticMailMessage.php +++ b/app/sprinkles/core/src/Mail/StaticMailMessage.php @@ -39,7 +39,7 @@ public function __construct($subject = "", $body = "") } /** - * {@inheritDoc} + * {@inheritdoc} */ public function renderBody($params = []) { @@ -47,7 +47,7 @@ public function renderBody($params = []) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function renderSubject($params = []) { diff --git a/app/sprinkles/core/src/Mail/TwigMailMessage.php b/app/sprinkles/core/src/Mail/TwigMailMessage.php index aa652403a..f28cb72ad 100644 --- a/app/sprinkles/core/src/Mail/TwigMailMessage.php +++ b/app/sprinkles/core/src/Mail/TwigMailMessage.php @@ -7,6 +7,8 @@ */ namespace UserFrosting\Sprinkle\Core\Mail; +use Slim\Views\Twig; + /** * MailMessage Class * @@ -22,7 +24,7 @@ class TwigMailMessage extends MailMessage protected $params; /** - * @var Twig_Template The Twig template object, to source the content for this message. + * @var \Twig_Template The Twig template object, to source the content for this message. */ protected $template; @@ -34,10 +36,10 @@ class TwigMailMessage extends MailMessage /** * Create a new TwigMailMessage instance. * - * @param Slim\Views\Twig $view The Twig view object used to render mail templates. + * @param Twig $view The Twig view object used to render mail templates. * @param string $filename optional Set the Twig template to use for this message. */ - public function __construct($view, $filename = null) + public function __construct(Twig $view, $filename = null) { $this->view = $view; @@ -63,7 +65,7 @@ public function addParams($params = []) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function renderSubject($params = []) { @@ -72,7 +74,7 @@ public function renderSubject($params = []) } /** - * {@inheritDoc} + * {@inheritdoc} */ public function renderBody($params = []) { @@ -83,9 +85,9 @@ public function renderBody($params = []) /** * Sets the Twig template object for this message. * - * @param Twig_Template $template The Twig template object, to source the content for this message. + * @param \Twig_Template $template The Twig template object, to source the content for this message. */ - public function setTemplate($template) + public function setTemplate(\Twig_Template $template) { $this->template = $template; return $this; diff --git a/app/sprinkles/core/src/Sprunje/Sprunje.php b/app/sprinkles/core/src/Sprunje/Sprunje.php index 5525dc439..113221f65 100644 --- a/app/sprinkles/core/src/Sprunje/Sprunje.php +++ b/app/sprinkles/core/src/Sprunje/Sprunje.php @@ -11,7 +11,6 @@ use Illuminate\Database\Eloquent\Builder; use League\Csv\Writer; use Psr\Http\Message\ResponseInterface as Response; -use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Util\ClassMapper; use UserFrosting\Support\Exception\BadRequestException; use Valitron\Validator; @@ -26,7 +25,7 @@ abstract class Sprunje { /** - * @var UserFrosting\Sprinkle\Core\Util\ClassMapper + * @var ClassMapper */ protected $classMapper; @@ -164,7 +163,7 @@ public function __construct(ClassMapper $classMapper, array $options) * Extend the query by providing a callback. * * @param callable $callback A callback which accepts and returns a Builder instance. - * @return $this + * @return self */ public function extendQuery(callable $callback) { @@ -175,8 +174,8 @@ public function extendQuery(callable $callback) /** * Execute the query and build the results, and append them in the appropriate format to the response. * - * @param ResponseInterface $response - * @return ResponseInterface + * @param Response $response + * @return Response */ public function toResponse(Response $response) { @@ -221,7 +220,7 @@ public function getArray() /** * Run the query and build a CSV object by flattening the resulting collection. Ignores any pagination. * - * @return SplTempFileObject + * @return \SplTempFileObject */ public function getCsv() { @@ -345,7 +344,7 @@ public function getQuery() * Set the underlying QueryBuilder object. * * @param Builder $query - * @return $this + * @return self */ public function setQuery($query) { @@ -357,7 +356,7 @@ public function setQuery($query) * Apply any filters from the options, calling a custom filter callback when appropriate. * * @param Builder $query - * @return $this + * @return self */ public function applyFilters($query) { @@ -381,7 +380,7 @@ public function applyFilters($query) * Apply any sorts from the options, calling a custom sorter callback when appropriate. * * @param Builder $query - * @return $this + * @return self */ public function applySorts($query) { @@ -410,7 +409,7 @@ public function applySorts($query) * Apply pagination based on the `page` and `size` options. * * @param Builder $query - * @return $this + * @return self */ public function applyPagination($query) { @@ -432,7 +431,7 @@ public function applyPagination($query) * * @param Builder $query * @param mixed $value - * @return $this + * @return self */ protected function filterAll($query, $value) { @@ -454,7 +453,7 @@ protected function filterAll($query, $value) * @param Builder $query * @param string $name * @param mixed $value - * @return $this + * @return self */ protected function buildFilterQuery($query, $name, $value) { @@ -477,7 +476,7 @@ protected function buildFilterQuery($query, $name, $value) * @param Builder $query * @param string $name * @param mixed $value - * @return $this + * @return self */ protected function buildFilterDefaultFieldQuery($query, $name, $value) { @@ -505,7 +504,7 @@ protected function applyTransformations($collection) /** * Set the initial query used by your Sprunje. * - * @return Builder|Relation|Model + * @return Builder|\Illuminate\Database\Eloquent\Relations\Relation|\UserFrosting\Sprinkle\Core\Database\Models\Model */ abstract protected function baseQuery(); diff --git a/app/sprinkles/core/src/Throttle/ThrottleRule.php b/app/sprinkles/core/src/Throttle/ThrottleRule.php index b71f2962c..277eb3ee8 100644 --- a/app/sprinkles/core/src/Throttle/ThrottleRule.php +++ b/app/sprinkles/core/src/Throttle/ThrottleRule.php @@ -7,6 +7,8 @@ */ namespace UserFrosting\Sprinkle\Core\Throttle; +use Carbon\Carbon; + /** * ThrottleRule Class * @@ -45,10 +47,10 @@ public function __construct($method, $interval, $delays) /** * Get the current delay on this rule for a particular number of event counts. * - * @param Carbon\Carbon $lastEventTime The timestamp for the last countable event. + * @param Carbon $lastEventTime The timestamp for the last countable event. * @param int $count The total number of events which have occurred in an interval. */ - public function getDelay($lastEventTime, $count) + public function getDelay(Carbon $lastEventTime, $count) { // Zero occurrences always maps to a delay of 0 seconds. if ($count == 0) { @@ -103,7 +105,7 @@ public function getMethod() /** * Sets the current mapping of attempts (int) to delays (seconds). * - * @param int[] A mapping of minimum observation counts (x) to delays (y), in seconds. + * @param int[] $delays A mapping of minimum observation counts (x) to delays (y), in seconds. */ public function setDelays($delays) { @@ -117,7 +119,7 @@ public function setDelays($delays) /** * Sets the current throttling interval (seconds). * - * @param int The amount of time, in seconds, to look back in determining attempts to consider. + * @param int $interval The amount of time, in seconds, to look back in determining attempts to consider. */ public function setInterval($interval) { @@ -129,7 +131,7 @@ public function setInterval($interval) /** * Sets the current throttling method ('ip' or 'data'). * - * @param string Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling. + * @param string $method Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling. */ public function setMethod($method) { diff --git a/app/sprinkles/core/src/Throttle/Throttler.php b/app/sprinkles/core/src/Throttle/Throttler.php index 0d424423b..be45cf72e 100644 --- a/app/sprinkles/core/src/Throttle/Throttler.php +++ b/app/sprinkles/core/src/Throttle/Throttler.php @@ -8,6 +8,7 @@ namespace UserFrosting\Sprinkle\Core\Throttle; use Carbon\Carbon; +use Illuminate\Support\Collection; use UserFrosting\Sprinkle\Core\Util\ClassMapper; /** @@ -18,7 +19,7 @@ class Throttler { /** - * @var UserFrosting\Sprinkle\Core\Util\ClassMapper + * @var ClassMapper */ protected $classMapper; @@ -42,9 +43,9 @@ public function __construct(ClassMapper $classMapper) * Add a throttling rule for a particular throttle event type. * * @param string $type The type of throttle event to check against. - * @param ThrottleRule $rule The rule to use when throttling this type of event. + * @param ThrottleRule|null $rule The rule to use when throttling this type of event. */ - public function addThrottleRule($type, $rule) + public function addThrottleRule($type, ThrottleRule $rule = null) { if (!($rule instanceof ThrottleRule || ($rule === null))) { throw new ThrottlerException('$rule must be of type ThrottleRule (or null).'); @@ -160,11 +161,11 @@ public function logEvent($type, $requestData = []) /** * Returns the current delay for a specified throttle rule. * - * @param Throttle[] $events a Collection of throttle events. + * @param Collection $events a Collection of throttle events. * @param ThrottleRule $throttleRule a rule representing the strategy to use for throttling a particular type of event. * @return int seconds remaining until a particular event is permitted to be attempted again. */ - protected function computeDelay($events, $throttleRule) + protected function computeDelay(Collection $events, ThrottleRule $throttleRule) { // If no matching events found, then there is no delay if (!$events->count()) { diff --git a/app/sprinkles/core/src/Twig/CacheHelper.php b/app/sprinkles/core/src/Twig/CacheHelper.php index 14aea49e3..d44a4abab 100755 --- a/app/sprinkles/core/src/Twig/CacheHelper.php +++ b/app/sprinkles/core/src/Twig/CacheHelper.php @@ -36,7 +36,6 @@ public function __construct(ContainerInterface $ci) /** * Function that delete the Twig cache directory content * - * @access public * @return bool true/false if operation is successfull */ public function clearCache() @@ -45,7 +44,7 @@ public function clearCache() $path = $this->ci->locator->findResource('cache://twig', true, true); // Get Filesystem instance - $fs = new FileSystem; + $fs = new Filesystem; // Make sure directory exist and delete it if ($fs->exists($path)) { diff --git a/app/sprinkles/core/src/Twig/CoreExtension.php b/app/sprinkles/core/src/Twig/CoreExtension.php index f7d8f699b..24f71dbb9 100755 --- a/app/sprinkles/core/src/Twig/CoreExtension.php +++ b/app/sprinkles/core/src/Twig/CoreExtension.php @@ -79,8 +79,8 @@ public function getFilters() /** * Converts phone numbers to a standard format. * - * @param String $num A unformatted phone number - * @return String Returns the formatted phone number + * @param string $num A unformatted phone number + * @return string Returns the formatted phone number */ new \Twig_SimpleFilter('phone', function ($num) { return Util::formatPhoneNumber($num); diff --git a/app/sprinkles/core/src/Util/Captcha.php b/app/sprinkles/core/src/Util/Captcha.php index c788b7773..5b4177b02 100644 --- a/app/sprinkles/core/src/Util/Captcha.php +++ b/app/sprinkles/core/src/Util/Captcha.php @@ -31,7 +31,7 @@ class Captcha protected $image; /** - * @var UserFrosting\Session\Session We use the session object so that the hashed captcha token will automatically appear in the session. + * @var Session We use the session object so that the hashed captcha token will automatically appear in the session. */ protected $session; @@ -42,8 +42,11 @@ class Captcha /** * Create a new captcha. + * + * @param Session $session + * @param string $key */ - public function __construct($session, $key) + public function __construct(Session $session, $key) { $this->session = $session; $this->key = $key; @@ -73,6 +76,8 @@ public function generateRandomCode() /** * Returns the captcha code. + * + * @return string */ public function getCaptcha() { @@ -81,6 +86,8 @@ public function getCaptcha() /** * Returns the captcha image. + * + * @return string */ public function getImage() { @@ -89,9 +96,9 @@ public function getImage() /** * Check that the specified code, when hashed, matches the code in the session. - * * Also, stores the specified code in the session with an md5 hash. - * @param string + * + * @param string $code * @return bool */ public function verifyCode($code) @@ -101,8 +108,9 @@ public function verifyCode($code) /** * Generate the image for the current captcha. - * * This generates an image as a binary string. + * + * @return string */ protected function generateImage() { diff --git a/app/sprinkles/core/src/Util/CheckEnvironment.php b/app/sprinkles/core/src/Util/CheckEnvironment.php index 26925d973..0dfd2d884 100644 --- a/app/sprinkles/core/src/Util/CheckEnvironment.php +++ b/app/sprinkles/core/src/Util/CheckEnvironment.php @@ -7,9 +7,12 @@ */ namespace UserFrosting\Sprinkle\Core\Util; -use Psr\Http\Message\ResponseInterface; -use Psr\Http\Message\ServerRequestInterface; -use Slim\Http\Body; +use Psr\Http\Message\ResponseInterface as Response; +use Psr\Http\Message\ServerRequestInterface as Request; +use Illuminate\Cache\CacheManager; +use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; +use Slim\Views\Twig; + /** * Performs pre-flight tests on your server environment to check that it meets the requirements. @@ -19,7 +22,7 @@ class CheckEnvironment { /** - * @var \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator Locator service for stream resources. + * @var UniformResourceLocator Locator service for stream resources. */ protected $locator; @@ -34,22 +37,23 @@ class CheckEnvironment protected $resultsSuccess = []; /** - * @var \Slim\Views\Twig The view object, needed for rendering error page. + * @var Twig The view object, needed for rendering error page. */ protected $view; /** - * @var \Illuminate\Cache\CacheManager Cache service for cache access. + * @var CacheManager Cache service for cache access. */ protected $cache; /** * Constructor. * - * @param $view \Slim\Views\Twig The view object, needed for rendering error page. - * @param $locator \RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator Locator service for stream resources. + * @param Twig $view The view object, needed for rendering error page. + * @param UniformResourceLocator $locator Locator service for stream resources. + * @param CacheManager $cache Cache manager */ - public function __construct($view, $locator, $cache) + public function __construct(Twig $view, UniformResourceLocator $locator, $cache) { $this->view = $view; $this->locator = $locator; @@ -59,13 +63,12 @@ public function __construct($view, $locator, $cache) /** * Invoke the CheckEnvironment middleware, performing all pre-flight checks and returning an error page if problems were found. * - * @param \Psr\Http\Message\ServerRequestInterface $request PSR7 request - * @param \Psr\Http\Message\ResponseInterface $response PSR7 response - * @param callable $next Next middleware - * + * @param Request $request PSR7 request + * @param Response $response PSR7 response + * @param callable $next Next middleware * @return \Psr\Http\Message\ResponseInterface */ - public function __invoke($request, $response, $next) + public function __invoke(Request $request, Response $response, $next) { $problemsFound = false; diff --git a/app/sprinkles/core/src/Util/ClassMapper.php b/app/sprinkles/core/src/Util/ClassMapper.php index 5fa0881c2..57cab6884 100644 --- a/app/sprinkles/core/src/Util/ClassMapper.php +++ b/app/sprinkles/core/src/Util/ClassMapper.php @@ -20,7 +20,7 @@ class ClassMapper { /** - * Mapping of generic class identifiers to specific class names. + * @var array Mapping of generic class identifiers to specific class names. */ protected $classMappings = []; diff --git a/app/sprinkles/core/src/Util/EnvironmentInfo.php b/app/sprinkles/core/src/Util/EnvironmentInfo.php index aba983770..8cf0f1cc6 100644 --- a/app/sprinkles/core/src/Util/EnvironmentInfo.php +++ b/app/sprinkles/core/src/Util/EnvironmentInfo.php @@ -19,7 +19,7 @@ class EnvironmentInfo { /** - * @var ContainerInterface The DI container for your application. + * @var \Interop\Container\ContainerInterface The DI container for your application. */ public static $ci; @@ -37,13 +37,13 @@ public static function database() try { $results['type'] = $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); - } catch (Exception $e) { + } catch (\Exception $e) { $results['type'] = "Unknown"; } try { $results['version'] = $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION); - } catch (Exception $e) { + } catch (\Exception $e) { $results['version'] = ""; } diff --git a/app/sprinkles/core/src/Util/ShutdownHandler.php b/app/sprinkles/core/src/Util/ShutdownHandler.php index e7a69032d..2097fbb40 100755 --- a/app/sprinkles/core/src/Util/ShutdownHandler.php +++ b/app/sprinkles/core/src/Util/ShutdownHandler.php @@ -44,8 +44,6 @@ public function __construct(ContainerInterface $ci, $displayErrorInfo) /** * Register this class with the shutdown handler. - * - * @return void */ public function register() { @@ -146,7 +144,7 @@ protected function buildErrorPage($message) /** * Build an HTML error page from an error string. * - * @param string $errorMessage + * @param string $message * @return string */ protected function buildHtmlErrorPage($message) diff --git a/app/sprinkles/core/tests/DatabaseTransactions.php b/app/sprinkles/core/tests/DatabaseTransactions.php index 82676f133..65f8ba8fc 100644 --- a/app/sprinkles/core/tests/DatabaseTransactions.php +++ b/app/sprinkles/core/tests/DatabaseTransactions.php @@ -17,8 +17,6 @@ trait DatabaseTransactions { /** * Handle database transactions on the specified connections. - * - * @return void */ public function beginDatabaseTransaction() { diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php index 919ae0de3..b0d7deb66 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php @@ -59,8 +59,6 @@ public function tearDown() /** * Setup base mock and migrator instance. - * - * @return void */ public function setUp() { diff --git a/app/sprinkles/core/tests/Integration/DatabaseTests.php b/app/sprinkles/core/tests/Integration/DatabaseTests.php index d1d100a0f..e22d9480b 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseTests.php +++ b/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -9,12 +9,13 @@ class DatabaseTests extends TestCase { + /** + * @var string + */ protected $schemaName = 'test_integration'; /** * Setup the database schema. - * - * @return void */ public function setUp() { @@ -27,6 +28,9 @@ public function setUp() $this->createSchema(); } + /** + * createSchema + */ protected function createSchema() { $this->schema($this->schemaName)->create('users', function (Blueprint $table) { @@ -99,8 +103,6 @@ protected function createSchema() /** * Tear down the database schema. - * - * @return void */ public function tearDown() { @@ -240,6 +242,9 @@ public function testSyncMorphMany() ], $phones); } + /** + * testBelongsToManyUnique + */ public function testBelongsToManyUnique() { $user = EloquentTestUser::create(['name' => 'David']); @@ -275,6 +280,9 @@ public function testBelongsToManyUnique() $this->assertEquals($expectedRoles, $users->toArray()[0]['job_roles']); } + /** + * testMorphsToManyUnique + */ public function testMorphsToManyUnique() { $user = EloquentTestUser::create(['name' => 'David']); @@ -311,6 +319,9 @@ public function testMorphsToManyUnique() $this->assertEquals($expectedTasks, $users->toArray()[0]['assignment_tasks']); } + /** + * testMorphsToManyUniqueWithTertiary + */ public function testMorphsToManyUniqueWithTertiary() { $user = EloquentTestUser::create(['name' => 'David']); @@ -375,6 +386,9 @@ public function testMorphsToManyUniqueWithTertiary() $this->assertEquals($expectedTasks, $users->toArray()[0]['tasks']); } + /** + * testBelongsToManyUniqueWithTertiary + */ public function testBelongsToManyUniqueWithTertiary() { $user = EloquentTestUser::create(['name' => 'David']); @@ -444,6 +458,9 @@ public function testBelongsToManyUniqueWithTertiary() $this->assertEquals($expectedJobs, $users->toArray()[0]['jobs']); } + /** + * testBelongsToManyUniqueWithTertiaryEagerLoad + */ public function testBelongsToManyUniqueWithTertiaryEagerLoad() { $user1 = EloquentTestUser::create(['name' => 'David']); @@ -715,6 +732,9 @@ public function testBelongsToManyThroughWithVia() $this->assertBelongsToManyThroughForAlex($usersWithPermissions[1]['permissions']); } + /** + * testQueryExclude + */ public function testQueryExclude() { $this->generateRoles(); @@ -727,7 +747,9 @@ public function testQueryExclude() ], $job->toArray()); } - + /** + * testQueryExcludeOnJoinedTable + */ public function testQueryExcludeOnJoinedTable() { $this->generateRolesWithPermissions(); @@ -771,6 +793,9 @@ public function testQueryExcludeOnJoinedTable() ], $users->toArray()); } + /** + * testQueryExcludeUseQualifiedNamesOnJoinedTable + */ public function testQueryExcludeUseQualifiedNamesOnJoinedTable() { $this->generateRolesWithPermissions(); @@ -810,6 +835,9 @@ public function testQueryExcludeUseQualifiedNamesOnJoinedTable() ], $users->toArray()); } + /** + * testQueryExcludeWildcard + */ public function testQueryExcludeWildcard() { $this->generateRoles(); @@ -859,6 +887,9 @@ protected function schema($connection = 'test_integration') return $this->connection($connection)->getSchemaBuilder(); } + /** + * generateRoles + */ protected function generateRoles() { return [ @@ -879,6 +910,9 @@ protected function generateRoles() ]; } + /** + * generatePermissions + */ protected function generatePermissions() { return [ @@ -904,6 +938,9 @@ protected function generatePermissions() ]; } + /** + * generateRolesWithPermissions + */ protected function generateRolesWithPermissions() { $roles = $this->generateRoles(); @@ -918,6 +955,9 @@ protected function generateRolesWithPermissions() return $roles; } + /** + * generateJobs + */ protected function generateJobs() { @@ -960,6 +1000,9 @@ protected function generateJobs() ]; } + /** + * generateLocations + */ protected function generateLocations() { return [ @@ -975,6 +1018,9 @@ protected function generateLocations() ]; } + /** + * generateTasks + */ protected function generateTasks() { return [ @@ -995,6 +1041,9 @@ protected function generateTasks() ]; } + /** + * generateAssignments + */ protected function generateAssignments() { return [ @@ -1031,6 +1080,10 @@ protected function generateAssignments() ]; } + /** + * assertBelongsToManyThroughForDavid + * @param array $permissions + */ protected function assertBelongsToManyThroughForDavid($permissions) { // User should have effective permissions uri_harvest, uri_spit_acid, and uri_slash. @@ -1078,6 +1131,10 @@ protected function assertBelongsToManyThroughForDavid($permissions) ], $permissions[2]['roles_via']); } + /** + * assertBelongsToManyThroughForAlex + * @param array $permissions + */ protected function assertBelongsToManyThroughForAlex($permissions) { // User should have effective permissions uri_spit_acid, uri_slash, and uri_royal_jelly. @@ -1139,11 +1196,17 @@ class EloquentTestUser extends EloquentTestModel protected $table = 'users'; protected $guarded = []; + /** + * + */ public function emails() { return $this->hasMany('UserFrosting\Tests\Integration\EloquentTestEmail', 'user_id'); } + /** + * + */ public function phones() { return $this->morphMany('UserFrosting\Tests\Integration\EloquentTestPhone', 'phoneable'); @@ -1246,6 +1309,9 @@ class EloquentTestEmail extends EloquentTestModel protected $table = 'emails'; protected $guarded = []; + /** + * + */ public function user() { return $this->belongsTo('UserFrosting\Tests\Integration\EloquentTestUser', 'user_id'); @@ -1257,6 +1323,9 @@ class EloquentTestPhone extends EloquentTestModel protected $table = 'phones'; protected $guarded = []; + /** + * + */ public function phoneable() { return $this->morphTo(); @@ -1296,6 +1365,9 @@ class EloquentTestTask extends EloquentTestModel protected $table = 'tasks'; protected $guarded = []; + /** + * + */ public function locations() { return $this->belongsToMany( diff --git a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php index c84194dc5..9131218f4 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php @@ -9,8 +9,6 @@ class DeprecatedClassTable extends Migration { /** * Run the migrations. - * - * @return void */ public function up() { @@ -23,8 +21,6 @@ public function up() /** * Reverse the migrations. - * - * @return void */ public function down() { @@ -33,8 +29,6 @@ public function down() /** * Seed the database. - * - * @return void */ public function seed() { diff --git a/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php b/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php index f21a8058a..ec40669c3 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php @@ -11,7 +11,7 @@ class UnfulfillableTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ static public $dependencies = [ '\UserFrosting\Tests\Integration\Migrations\NonExistingMigration' @@ -19,8 +19,6 @@ class UnfulfillableTable extends Migration /** * Run the migrations. - * - * @return void */ public function up() { @@ -32,8 +30,6 @@ public function up() /** * Reverse the migrations. - * - * @return void */ public function down() { diff --git a/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php b/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php index 4f4470052..40678feaa 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php @@ -8,14 +8,12 @@ class CreatePasswordResetsTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public static $dependencies = []; /** * Run the migrations. - * - * @return void */ public function up() { @@ -28,8 +26,6 @@ public function up() /** * Reverse the migrations. - * - * @return void */ public function down() { diff --git a/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php b/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php index f193261ca..db5393605 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php @@ -9,14 +9,13 @@ class CreateUsersTable extends Migration { /** * {@inheritDoc} + * * N.B.: Not using static here to test old deprecated behavior */ public $dependencies = []; /** * Run the migrations. - * - * @return void */ public function up() { @@ -32,8 +31,6 @@ public function up() /** * Reverse the migrations. - * - * @return void */ public function down() { diff --git a/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php b/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php index c27cbad99..c2eae572d 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php @@ -8,7 +8,7 @@ class CreateFlightsTable extends Migration { /** - * {@inheritDoc} + * {@inheritdoc} */ public static $dependencies = [ '\UserFrosting\Tests\Integration\Migrations\one\CreateUsersTable', @@ -17,8 +17,6 @@ class CreateFlightsTable extends Migration /** * Run the migrations. - * - * @return void */ public function up() { @@ -30,8 +28,6 @@ public function up() /** * Reverse the migrations. - * - * @return void */ public function down() { diff --git a/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php b/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php index 5ffd86c97..5062501b3 100644 --- a/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php +++ b/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php @@ -19,8 +19,6 @@ class DatabaseTests extends TestCase /** * Setup our fake ci - * - * @return void */ public function setUp() { diff --git a/app/sprinkles/core/tests/RefreshDatabase.php b/app/sprinkles/core/tests/RefreshDatabase.php index 05a824f02..2a4be2036 100644 --- a/app/sprinkles/core/tests/RefreshDatabase.php +++ b/app/sprinkles/core/tests/RefreshDatabase.php @@ -22,8 +22,6 @@ trait RefreshDatabase /** * Define hooks to migrate the database before and after each test. - * - * @return void */ public function refreshDatabase() { @@ -45,8 +43,6 @@ protected function usingInMemoryDatabase() /** * Refresh the in-memory database. - * - * @return void */ protected function refreshInMemoryDatabase() { @@ -55,8 +51,6 @@ protected function refreshInMemoryDatabase() /** * Refresh a conventional test database. - * - * @return void */ protected function refreshTestDatabase() { @@ -74,8 +68,6 @@ protected function refreshTestDatabase() /** * Handle database transactions on the specified connections. - * - * @return void */ protected function beginDatabaseTransaction() { diff --git a/app/sprinkles/core/tests/Unit/RouterTest.php b/app/sprinkles/core/tests/Unit/RouterTest.php index 456305988..f77ed077b 100644 --- a/app/sprinkles/core/tests/Unit/RouterTest.php +++ b/app/sprinkles/core/tests/Unit/RouterTest.php @@ -8,8 +8,6 @@ class RouterTest extends TestCase { /** * Test router integration in Tests - * - * @return void */ public function testBasicTest() { diff --git a/app/system/Bakery/Bakery.php b/app/system/Bakery/Bakery.php index 1fe4c53b2..e460a501c 100644 --- a/app/system/Bakery/Bakery.php +++ b/app/system/Bakery/Bakery.php @@ -22,12 +22,12 @@ class Bakery { /** - * @var $app Symfony\Component\Console\Application + * @var \Symfony\Component\Console\Application $app */ protected $app; /** - * @var \Interop\Container\ContainerInterface The global container object, which holds all your services. + * @var \Interop\Container\ContainerInterface The global container object, which holds all your services. */ protected $ci; @@ -37,7 +37,7 @@ class Bakery protected $scheme = 'bakery://'; /** - * Constructor + * Constructor */ public function __construct() { @@ -61,9 +61,7 @@ public function __construct() } /** - * Run the Symfony Console App - * - * @return void + * Run the Symfony Console App */ public function run() { @@ -71,9 +69,7 @@ public function run() } /** - * Return the list of available commands for a specific sprinkle - * - * @return void + * Return the list of available commands for a specific sprinkle */ protected function loadCommands() { diff --git a/app/system/Bakery/BaseCommand.php b/app/system/Bakery/BaseCommand.php index 731dce960..b9e041e25 100644 --- a/app/system/Bakery/BaseCommand.php +++ b/app/system/Bakery/BaseCommand.php @@ -35,7 +35,7 @@ abstract class BaseCommand extends Command protected $ci; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function initialize(InputInterface $input, OutputInterface $output) { diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/system/Bakery/Command/BuildAssets.php index 7dc4cf257..a95de5b2f 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/system/Bakery/Command/BuildAssets.php @@ -9,7 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; @@ -27,7 +26,7 @@ class BuildAssets extends BaseCommand protected $buildPath; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -39,7 +38,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { @@ -69,9 +68,6 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Install npm package - * - * @access protected - * @return void */ protected function npmInstall() { @@ -93,9 +89,6 @@ protected function npmInstall() /** * Perform UF Assets installation - * - * @access protected - * @return void */ protected function assetsInstall() { @@ -119,9 +112,6 @@ protected function assetsInstall() /** * Build the production bundle. - * - * @access protected - * @return void */ protected function buildAssets() { @@ -162,9 +152,6 @@ protected function buildAssets() /** * Run the `uf-clean` command to delete installed assets, delete compiled * bundle config file and delete compiled assets - * - * @access protected - * @return void */ protected function clean() { diff --git a/app/system/Bakery/Command/Test.php b/app/system/Bakery/Command/Test.php index 553fdddc7..2b9302f7b 100644 --- a/app/system/Bakery/Command/Test.php +++ b/app/system/Bakery/Command/Test.php @@ -9,8 +9,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; /** @@ -27,7 +25,7 @@ class Test extends BaseCommand protected $buildPath; /** - * {@inheritDoc} + * {@inheritdoc} */ protected function configure() { @@ -37,7 +35,7 @@ protected function configure() } /** - * {@inheritDoc} + * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { diff --git a/app/system/Bakery/ConfirmableTrait.php b/app/system/Bakery/ConfirmableTrait.php index 2e3bc03c0..a4baec98f 100644 --- a/app/system/Bakery/ConfirmableTrait.php +++ b/app/system/Bakery/ConfirmableTrait.php @@ -7,8 +7,6 @@ */ namespace UserFrosting\System\Bakery; -use Closure; - /** * Confirmable Trait. Include method used to confirm action * @@ -20,6 +18,7 @@ trait ConfirmableTrait * Confirm before proceeding with the action. * This method only asks for confirmation in production. * + * @param bool $force * @param string $warning * @param \Closure|bool|null $callback * @return bool @@ -30,7 +29,7 @@ public function confirmToProceed($force = false, $warning = 'Application In Prod $callback = is_null($callback) ? $this->getDefaultConfirmCallback() : $callback; // Process callback to determine if we should ask for confirmation - $shouldConfirm = $callback instanceof Closure ? call_user_func($callback) : $callback; + $shouldConfirm = $callback instanceof \Closure ? call_user_func($callback) : $callback; if ($shouldConfirm & !$force) { diff --git a/app/system/Bakery/DatabaseTest.php b/app/system/Bakery/DatabaseTest.php index 0e4f3bf38..57bebc493 100644 --- a/app/system/Bakery/DatabaseTest.php +++ b/app/system/Bakery/DatabaseTest.php @@ -16,11 +16,9 @@ */ trait DatabaseTest { - /** * Function to test the db connexion. * - * @access protected * @return bool True if success */ protected function testDB() diff --git a/app/system/Bakery/Migration.php b/app/system/Bakery/Migration.php index 0b2843602..760e5fbe9 100644 --- a/app/system/Bakery/Migration.php +++ b/app/system/Bakery/Migration.php @@ -21,10 +21,10 @@ class Migration extends NewMigration { /** - * Constructor + * Constructor * - * @param Builder $schema The schema builder - * @param SymfonyStyle $io The SymfonyStyle instance + * @param Builder|null $schema The schema builder + * @param SymfonyStyle|null $io The SymfonyStyle instance */ public function __construct(Builder $schema = null, SymfonyStyle $io = null) { diff --git a/app/system/Facade.php b/app/system/Facade.php index 0d1ad8276..8ec704816 100644 --- a/app/system/Facade.php +++ b/app/system/Facade.php @@ -7,8 +7,8 @@ */ namespace UserFrosting\System; -use Illuminate\Support\Facades\Mockery; -use Illuminate\Support\Facades\Mockery\MockInterface; +use Mockery; +use Mockery\MockInterface; use Interop\Container\ContainerInterface; use RuntimeException; @@ -26,7 +26,7 @@ abstract class Facade /** * The Pimple container being facaded. * - * @var \Interop\Container\ContainerInterface + * @var ContainerInterface */ protected static $container; @@ -40,8 +40,7 @@ abstract class Facade /** * Hotswap the underlying service instance behind the facade. * - * @param mixed $instance - * @return void + * @param mixed $instance */ public static function swap($instance) { @@ -57,7 +56,6 @@ public static function swap($instance) /** * Initiate a mock expectation on the facade. * - * @param mixed * @return \Mockery\Expectation */ public static function shouldReceive() @@ -76,7 +74,7 @@ public static function shouldReceive() /** * Create a fresh mock instance for the given class. * - * @param string $name + * @param string $name * @return \Mockery\Expectation */ protected static function createFreshMockInstance($name) @@ -142,8 +140,6 @@ public static function getFacadeRoot() /** * Get the registered name of the component. * - * @return string - * * @throws \RuntimeException */ protected static function getFacadeAccessor() @@ -154,7 +150,7 @@ protected static function getFacadeAccessor() /** * Resolve the facade root instance from the container. * - * @param string|object $name + * @param string|object $name * @return mixed */ protected static function resolveFacadeInstance($name) @@ -174,7 +170,6 @@ protected static function resolveFacadeInstance($name) * Clear a resolved facade instance. * * @param string $name - * @return void */ public static function clearResolvedInstance($name) { @@ -183,8 +178,6 @@ public static function clearResolvedInstance($name) /** * Clear all of the resolved instances. - * - * @return void */ public static function clearResolvedInstances() { @@ -194,7 +187,7 @@ public static function clearResolvedInstances() /** * Get the container instance behind the facade. * - * @return \Interop\Container\ContainerInterface + * @return ContainerInterface */ public static function getFacadeContainer() { @@ -204,10 +197,9 @@ public static function getFacadeContainer() /** * Set the container instance. * - * @param \Interop\Container\ContainerInterface $container - * @return void + * @param ContainerInterface $container */ - public static function setFacadeContainer($container) + public static function setFacadeContainer(ContainerInterface $container) { static::$container = $container; } @@ -215,11 +207,10 @@ public static function setFacadeContainer($container) /** * Handle dynamic, static calls to the object. * + * @throws \RuntimeException * @param string $method * @param array $args * @return mixed - * - * @throws \RuntimeException */ public static function __callStatic($method, $args) { diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 42640b8b4..0f136e92f 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -38,7 +38,7 @@ public function register(ContainerInterface $container) /** * Path/file locator service. - * + * * Register custom streams for the application, and add paths for app-level streams. * * @return \UserFrosting\UniformResourceLocator\ResourceLocator diff --git a/app/system/SlimAppEvent.php b/app/system/SlimAppEvent.php index f1217a53f..7e146ca10 100644 --- a/app/system/SlimAppEvent.php +++ b/app/system/SlimAppEvent.php @@ -15,6 +15,9 @@ */ class SlimAppEvent extends Event { + /** + * @var App + */ protected $app; public function __construct(App $app) @@ -22,6 +25,9 @@ public function __construct(App $app) $this->app = $app; } + /** + * @return App + */ public function getApp() { return $this->app; diff --git a/app/system/Sprinkle/Sprinkle.php b/app/system/Sprinkle/Sprinkle.php index 47070251f..f9d4ce82b 100644 --- a/app/system/Sprinkle/Sprinkle.php +++ b/app/system/Sprinkle/Sprinkle.php @@ -9,7 +9,6 @@ use Interop\Container\ContainerInterface; use RocketTheme\Toolbox\Event\EventSubscriberInterface; -use Slim\App; /** * Sprinkle class diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index 41312f6e3..d03d9699a 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -73,6 +73,7 @@ public function addResources() * Creates an object of a subclass of UserFrosting\System\Sprinkle\Sprinkle if defined for the sprinkle (converting to StudlyCase). * Otherwise, returns null. * @param string $name The name of the Sprinkle to initialize. + * @return mixed Sprinkle class instance or null if no such class exist */ public function bootSprinkle($name) { @@ -112,7 +113,7 @@ public function getSprinkles() * Initialize a list of Sprinkles, instantiating their boot classes (if they exist), * and subscribing them to the event dispatcher. * - * @param string[] $baseSprinkleNames + * @param string[] $sprinkleNames */ public function init($sprinkleNames) { @@ -143,7 +144,8 @@ public function initFromSchema($schemaPath) * Return if a Sprinkle is available * Can be used by other Sprinkles to test if their dependencies are met * - * @param $name The name of the Sprinkle + * @param string $name The name of the Sprinkle + * @return bool */ public function isAvailable($name) { @@ -163,6 +165,8 @@ public function registerAllServices() /** * Register services for a specified Sprinkle. + * + * @param string $name */ public function registerServices($name) { diff --git a/app/tests/DatabaseTransactions.php b/app/tests/DatabaseTransactions.php index 88d853f11..fd1a5463d 100644 --- a/app/tests/DatabaseTransactions.php +++ b/app/tests/DatabaseTransactions.php @@ -17,8 +17,6 @@ trait DatabaseTransactions { /** * Handle database transactions on the specified connections. - * - * @return void */ public function beginDatabaseTransaction() { diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php index c5576871b..d68832378 100644 --- a/app/tests/TestCase.php +++ b/app/tests/TestCase.php @@ -49,8 +49,6 @@ class TestCase extends BaseTestCase /** * Setup the test environment. - * - * @return void */ protected function setUp() { @@ -70,8 +68,7 @@ protected function setUp() /** * Boot the testing helper traits. * - * @deprecated - * @return void + * @deprecated */ protected function setUpTraits() { @@ -85,8 +82,6 @@ protected function setUpTraits() /** * Refresh the application instance. - * - * @return void */ protected function refreshApplication() { @@ -105,8 +100,6 @@ protected function refreshApplication() /** * Clean up the testing environment before the next test. - * - * @return void */ protected function tearDown() { @@ -128,7 +121,6 @@ protected function tearDown() * Register a callback to be run after the application is created. * * @param callable $callback - * @return void */ public function afterApplicationCreated(callable $callback) { @@ -147,7 +139,6 @@ public function afterApplicationCreated(callable $callback) * @param string $key [description] * @param string $message [description] * @throws \PHPUnit_Framework_AssertionFailedError - * @return void */ public static function assertCollectionsSame($expected, $actual, $key = 'id', $message = '') { @@ -178,7 +169,6 @@ public static function assertCollectionsSame($expected, $actual, $key = 'id', $m * Register a callback to be run before the application is destroyed. * * @param callable $callback - * @return void */ protected function beforeApplicationDestroyed(callable $callback) { @@ -204,7 +194,6 @@ protected static function castToComparable($item) * Remove all relations on a collection of models. * * @param array $models - * @return void */ protected static function ignoreRelations($models) { diff --git a/app/tests/Unit/ExampleTest.php b/app/tests/Unit/ExampleTest.php index ec7a47ca3..4e60469f4 100644 --- a/app/tests/Unit/ExampleTest.php +++ b/app/tests/Unit/ExampleTest.php @@ -8,8 +8,6 @@ class ExampleTest extends TestCase { /** * A basic test example. - * - * @return void */ public function testBasicTest() { From bf395523a8ca70b8d39ef2801effbf928b8e3f30 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 17 Oct 2018 22:34:50 -0400 Subject: [PATCH 092/237] Finishing up with php-cs-fixer... --- app/sprinkles/account/locale/ar/validate.php | 36 +- .../account/locale/en_US/validate.php | 2 +- .../account/locale/es_ES/validate.php | 2 +- app/sprinkles/account/locale/fa/validate.php | 2 +- .../account/locale/fr_FR/validate.php | 2 +- .../account/locale/it_IT/validate.php | 2 +- .../account/locale/pt_PT/validate.php | 2 +- .../account/locale/ru_RU/validate.php | 2 +- .../account/locale/th_TH/messages.php | 328 +++++++++--------- .../account/locale/th_TH/validate.php | 36 +- app/sprinkles/account/locale/tr/validate.php | 2 +- .../account/locale/zh_CN/validate.php | 2 +- app/sprinkles/account/src/Account.php | 1 - .../account/src/Account/Registration.php | 4 +- .../account/src/Authenticate/Hasher.php | 1 - .../src/Authorize/AuthorizationException.php | 1 - .../src/Controller/AccountController.php | 6 +- .../Exception/SpammyRequestException.php | 1 - .../Migrations/v400/ActivitiesTable.php | 2 +- .../Database/Migrations/v400/GroupsTable.php | 2 +- .../Migrations/v400/PermissionsTable.php | 5 +- .../src/Database/Models/PasswordReset.php | 2 +- .../account/src/Database/Models/User.php | 2 +- .../src/Database/Models/Verification.php | 2 +- .../src/Repository/TokenRepository.php | 2 +- .../account/tests/Unit/FactoriesTest.php | 2 +- .../account/tests/Unit/RegistrationTest.php | 2 +- app/sprinkles/admin/locale/fa/messages.php | 48 +-- app/sprinkles/admin/locale/fr_FR/messages.php | 2 +- app/sprinkles/admin/locale/th_TH/messages.php | 268 +++++++------- app/sprinkles/admin/src/Admin.php | 1 - .../admin/src/Controller/GroupController.php | 8 +- .../admin/src/Controller/RoleController.php | 14 +- .../admin/src/Controller/UserController.php | 14 +- app/sprinkles/core/config/default.php | 2 +- app/sprinkles/core/config/dev.php | 2 +- app/sprinkles/core/locale/ar/messages.php | 6 +- app/sprinkles/core/locale/ar/validate.php | 2 +- app/sprinkles/core/locale/en_US/messages.php | 4 +- app/sprinkles/core/locale/en_US/validate.php | 2 +- app/sprinkles/core/locale/es_ES/messages.php | 4 +- app/sprinkles/core/locale/fa/messages.php | 4 +- app/sprinkles/core/locale/fa/validate.php | 2 +- app/sprinkles/core/locale/fr_FR/messages.php | 6 +- app/sprinkles/core/locale/fr_FR/validate.php | 4 +- app/sprinkles/core/locale/it_IT/messages.php | 6 +- app/sprinkles/core/locale/it_IT/validate.php | 2 +- app/sprinkles/core/locale/pt_PT/messages.php | 4 +- app/sprinkles/core/locale/pt_PT/validate.php | 2 +- app/sprinkles/core/locale/ru_RU/messages.php | 4 +- app/sprinkles/core/locale/ru_RU/validate.php | 2 +- app/sprinkles/core/locale/th_TH/errors.php | 102 +++--- app/sprinkles/core/locale/th_TH/messages.php | 204 +++++------ app/sprinkles/core/locale/th_TH/validate.php | 50 +-- app/sprinkles/core/locale/valitron/th.php | 68 ++-- app/sprinkles/core/locale/zh_CN/messages.php | 4 +- app/sprinkles/core/locale/zh_CN/validate.php | 2 +- app/sprinkles/core/routes/routes.php | 2 +- app/sprinkles/core/src/Alert/AlertStream.php | 4 +- app/sprinkles/core/src/Bakery/BakeCommand.php | 2 +- .../core/src/Bakery/ClearCacheCommand.php | 2 +- .../core/src/Bakery/SetupCommand.php | 2 +- .../core/src/Bakery/SetupDbCommand.php | 3 - .../core/src/Bakery/SetupSmtpCommand.php | 1 - app/sprinkles/core/src/Database/Migration.php | 8 +- .../Migrator/MigrationDependencyAnalyser.php | 7 +- .../core/src/Database/Migrator/Migrator.php | 3 +- .../Models/Concerns/HasRelationships.php | 41 ++- .../core/src/Database/Models/Throttle.php | 8 +- .../Relations/BelongsToManyConstrained.php | 3 +- .../Relations/BelongsToManyThrough.php | 9 +- .../Database/Relations/Concerns/Unique.php | 12 +- .../src/Error/Renderer/WhoopsRenderer.php | 4 +- app/sprinkles/core/src/Mail/Mailer.php | 12 +- .../src/ServicesProvider/ServicesProvider.php | 1 - app/sprinkles/core/src/Sprunje/Sprunje.php | 4 +- .../core/src/Throttle/ThrottlerException.php | 1 - app/sprinkles/core/src/Util/Captcha.php | 34 +- .../core/src/Util/CheckEnvironment.php | 28 +- app/sprinkles/core/src/Util/ClassMapper.php | 2 +- .../core/src/Util/RawAssetBundles.php | 93 +++-- .../core/src/Util/ShutdownHandler.php | 4 +- app/sprinkles/core/src/Util/Util.php | 27 +- .../DatabaseMigratorIntegrationTest.php | 18 +- .../core/tests/Integration/DatabaseTests.php | 12 +- .../Error/Renderer/WhoopsRendererTest.php | 2 +- .../Integration/MigrationLocatorTest.php | 2 +- .../Migrations/UnfulfillableTable.php | 8 +- .../Migrations/one/CreateUsersTable.php | 2 +- .../tests/Unit/BelongsToManyThroughTest.php | 10 +- app/sprinkles/core/tests/Unit/RouterTest.php | 2 +- app/sprinkles/core/tests/Unit/SprunjeTest.php | 6 +- app/system/Bakery/Bakery.php | 1 - app/system/Bakery/Command/BuildAssets.php | 8 +- app/system/Bakery/Command/Test.php | 2 +- app/system/Bakery/DatabaseTest.php | 2 +- app/system/ServicesProvider.php | 1 - app/tests/Unit/ExampleTest.php | 2 +- 98 files changed, 869 insertions(+), 822 deletions(-) diff --git a/app/sprinkles/account/locale/ar/validate.php b/app/sprinkles/account/locale/ar/validate.php index 37693fb4c..10543d0b8 100644 --- a/app/sprinkles/account/locale/ar/validate.php +++ b/app/sprinkles/account/locale/ar/validate.php @@ -1,18 +1,18 @@ - [ - "PASSWORD_MISMATCH" => "يجب أن تكون كلمة المرور وكلمة المرور التأكيدية نفس" - ] -]; + [ + "PASSWORD_MISMATCH" => "يجب أن تكون كلمة المرور وكلمة المرور التأكيدية نفس" + ] +]; diff --git a/app/sprinkles/account/locale/en_US/validate.php b/app/sprinkles/account/locale/en_US/validate.php index 00c0aef6c..f91ecfed7 100644 --- a/app/sprinkles/account/locale/en_US/validate.php +++ b/app/sprinkles/account/locale/en_US/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "Your password and confirmation password must match.", "USERNAME" => "Username may consist only of lowercase letters, numbers, '.', '-', and '_'." ] diff --git a/app/sprinkles/account/locale/es_ES/validate.php b/app/sprinkles/account/locale/es_ES/validate.php index bf4f27e0f..3f788fe16 100755 --- a/app/sprinkles/account/locale/es_ES/validate.php +++ b/app/sprinkles/account/locale/es_ES/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "Tu contraseña y contraseña de confirmación deben coincidir.", "USERNAME" => "El nombre de usuario puede consistir sólo en letras minúsculas, números, '.', '-' y '_'." ] diff --git a/app/sprinkles/account/locale/fa/validate.php b/app/sprinkles/account/locale/fa/validate.php index a63cae124..4e8dc74e0 100644 --- a/app/sprinkles/account/locale/fa/validate.php +++ b/app/sprinkles/account/locale/fa/validate.php @@ -13,7 +13,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "گذرواژه و تکرار آن باید با یکدیگر تطبیق پیدا کنند", "USERNAME" => "نام کاربری فقط میتواند از حروف کوچک، اعداد، '.'، '-' و '_' متشکل شوند." ] diff --git a/app/sprinkles/account/locale/fr_FR/validate.php b/app/sprinkles/account/locale/fr_FR/validate.php index 44b1bc19f..2d4d65fae 100644 --- a/app/sprinkles/account/locale/fr_FR/validate.php +++ b/app/sprinkles/account/locale/fr_FR/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "Votre mot de passe et votre mot de passe de confirmation doivent correspondre." ] ]; diff --git a/app/sprinkles/account/locale/it_IT/validate.php b/app/sprinkles/account/locale/it_IT/validate.php index c9144a0ad..46f7e6d66 100644 --- a/app/sprinkles/account/locale/it_IT/validate.php +++ b/app/sprinkles/account/locale/it_IT/validate.php @@ -14,7 +14,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "I due campi devono combaciare", "USERNAME" => "Il nome utente può essere composto solo da caratteri alfanumerici, '.', '-', e '_'." ] diff --git a/app/sprinkles/account/locale/pt_PT/validate.php b/app/sprinkles/account/locale/pt_PT/validate.php index c05f14c6d..4acc93e36 100644 --- a/app/sprinkles/account/locale/pt_PT/validate.php +++ b/app/sprinkles/account/locale/pt_PT/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "A password e respetiva confirmação têm de coincidir." ] ]; diff --git a/app/sprinkles/account/locale/ru_RU/validate.php b/app/sprinkles/account/locale/ru_RU/validate.php index 8ede5d8ec..4d39bbef0 100644 --- a/app/sprinkles/account/locale/ru_RU/validate.php +++ b/app/sprinkles/account/locale/ru_RU/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "Пароли не совпадают.", "USERNAME" => "Имя может состоять только из строчных букв, цифр, '.', '-' и «_»." ] diff --git a/app/sprinkles/account/locale/th_TH/messages.php b/app/sprinkles/account/locale/th_TH/messages.php index 642a7c5dd..012c7f4f8 100644 --- a/app/sprinkles/account/locale/th_TH/messages.php +++ b/app/sprinkles/account/locale/th_TH/messages.php @@ -1,164 +1,164 @@ - [ - "@TRANSLATION" => "บัญชี", - - "ACCESS_DENIED" => "หืมม ดูเหมือนว่าคุณไม่ได้รับอนุญาตให้ทำเช่นนั้น", - - "DISABLED" => "บัญชีนี้ถูกปิดการใช้งานไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม", - - "EMAIL_UPDATED" => "ปรับปรุงบัญชีอีเมลแล้ว", - - "INVALID" => "ไม่พบบัญชีนี้ มันอาจถูกลบไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม", - - "MASTER_NOT_EXISTS" => "คุณไม่สามารถสมัครสมาชิกได้จนกว่าจะสร้างบัญชีหลัก!", - "MY" => "บัญชีของฉัน", - - "SESSION_COMPROMISED" => "เซสชันของคุณถูกลักลอบใช้ คุณควรจะออกจากระบบบนอุปกรณ์ทั้งหมดแล้วกลับเข้าสู่ระบบและตรวจสอบให้แน่ใจว่าไม่มีการแก้ไขข้อมูลของคุณ", - "SESSION_COMPROMISED_TITLE" => "บัญชีของคุณอาจถูกบุกรุก", - "SESSION_EXPIRED" => "เซสชันของคุณหมดอายุ กรุณาเข้าสู่ระบบอีกครั้ง", - - "SETTINGS" => [ - "@TRANSLATION" => "การตั้งค่าบัญชี", - "DESCRIPTION" => "ปรับปรุงการตั้งค่าบัญชีของคุณ รวมไปถึงอีเมล ชื่อ และรหัสผ่าน", - "UPDATED" => "ปรับปรุงการตั้งค่าบัญชีของคุณแล้ว" - ], - - "TOOLS" => "เครื่องมือบัญชี", - - "UNVERIFIED" => "บัญชีของคุณยังไม่ได้รับการยืนยัน กรุณาตรวจสอบกล่องอีเมลและจดหมายขยะของคุณสำหรับขั้นตอนการเปิดใช้งานบัญชี", - - "VERIFICATION" => [ - "NEW_LINK_SENT" => "เราได้ส่งลิงก์สำหรับการยืนยันใหม่ไปยังอีเมล {{email}} กรุณาตรวจสอบอีเมลนี้ในกล่องอีเมลและจดหมายขยะของคุณ", - "RESEND" => "ส่งอีเมลยืนยันอีกครั้ง", - "COMPLETE" => "คุณได้ยืนยันอีเมลของคุณเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที", - "EMAIL" => "กรุณากรอกอีเมลที่คุณได้ใช้สมัครไว้แล้วอีเมลยืนยันจะถูกส่งไปให้ใหม่", - "PAGE" => "ส่งอีเมลยืนยันสำหรับบัญชีของฉันใหม่", - "SEND" => "ส่งอีเมลยืนยันให้บัญชีของฉัน", - "TOKEN_NOT_FOUND" => "ไม่พบโทเคนยืนยันอีเมล / บัญชีนี้ได้ยืนยันแล้ว", - ] - ], - - "EMAIL" => [ - "INVALID" => "อีเมล {{email}} ไม่มีอยู่จริง", - "IN_USE" => "อีเมล {{email}} ได้ถูกใช้งานแล้ว" - ], - - "FIRST_NAME" => "ชื่อจริง", - - "HEADER_MESSAGE_ROOT" => "คุณได้เข้าสู่ระบบเป็นผู้ดูแลสูงสุด", - - "LAST_NAME" => "นามสกุล", - - "LOCALE.ACCOUNT" => "ภาษาและสถานที่ที่จะใช้สำหรับบัญชีของคุณ", - - "LOGIN" => [ - "@TRANSLATION" => "เข้าสู่ะระบบ", - - "ALREADY_COMPLETE" => "คุณได้เข้าสู่ระบบอยู่แล้ว!", - "SOCIAL" => "หรือเข้าสู่ระบบด้วย", - "REQUIRED" => "ขออภัย คุณจะต้องเข้าสู่ระบบเพื่อเข้าถึงส่วนนี้" - ], - - "LOGOUT" => "ออกจากระบบ", - - "NAME" => "ชื่อ", - - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "เข้าสู่ระบบไปยังบัญชี {{site_name}} หรือสมัครสมาชิกสำหรับบัญชีใหม่", - "SUBTITLE" => "สมัครสมาชิกฟรี หรือเข้าสู่ระบบด้วยบัญชีที่มีอยู่", - "TITLE" => "มาเริ่มกันเลย!", - ] - ], - - "PASSWORD" => [ - "@TRANSLATION" => "รหัสผ่าน", - - "BETWEEN" => "ระหว่าง {{min}}-{{max}} ตัวอักษร", - - "CONFIRM" => "ยืนยันรหัสผ่าน", - "CONFIRM_CURRENT" => "กรุณายืนยันรหัสผ่านปัจจุบันของคุณ", - "CONFIRM_NEW" => "ยืนยันรหัสผ่านใหม่", - "CONFIRM_NEW_EXPLAIN" => "กรอกรหัสผ่านใหม่ของคุณอีกครั้ง", - "CONFIRM_NEW_HELP" => "กรอกเฉพาะเมื่อคุณต้องการตั้งรหัสผ่านใหม่", - "CURRENT" => "รหัสผ่านปัจจุบัน", - "CURRENT_EXPLAIN" => "คุณจะต้องยืนยันรหัสผ่านปัจจุบันเพื่อแก้ไขข้อมูล", - - "FORGOTTEN" => "ลืมรหัสผ่าน", - "FORGET" => [ - "@TRANSLATION" => "ฉันลืมรหัสผ่านของฉัน", - - "COULD_NOT_UPDATE" => "ไม่สามารถปรับปรุงรหัสผ่าน", - "EMAIL" => "กรุณากรอกที่อยู่อีเมลที่คุณเคยใช้เข้าสู่ระบบ ลิงก์ขั้นตอนการรีเซ็ตรหัสผ่านของคุณจะถูกส่งไปให้คุณ", - "EMAIL_SEND" => "ลิงก์รีเซ็ตรหัสผ่านจากอีเมล", - "INVALID" => "ขอรีเซ็ตรหัสผ่านนี้ไม่มีอยู่ หรือหมดอายุไปแล้ว กรุณาลอง ส่งคำขอของคุณอีกครั้ง", - "PAGE" => "รับลิงก์สำหรับการรีเซ็ตรหัสผ่านของคุณ", - "REQUEST_CANNED" => "คำขอลืมรหัสผ่านได้ถูกยกเลิก", - "REQUEST_SENT" => "หากอีเมล {{email}} ตรงกับบัญชีในระบบของเราลิงก์การรีเซ็ตรหัสผ่านจะถูกส่งไปที่ {{email}}" - ], - - "RESET" => [ - "@TRANSLATION" => "รีเซ็ตรหัสผ่าน", - "CHOOSE" => "กรุณาเลือกรหัสผ่านใหม่เพื่อดำเนินการต่อ", - "PAGE" => "เลือกรหัสผ่านใหม่สำหรับบัญชีของคุณ", - "SEND" => "ตั้งรหัสผ่านใหม่และเข้าสู่ระบบ" - ], - - "HASH_FAILED" => "เข้ารหัสรหัสผ่านล้มเหลว กรุณาติดต่อผู้ดูแลระบบของเว็บไซต์", - "INVALID" => "รหัสผ่านปัจจุบันไม่ตรงกับรหัสผ่านที่เราบันทึกไว้", - "NEW" => "รหัสผ่านใหม่", - "NOTHING_TO_UPDATE" => "คุณไม่สามารถปรังปรุงด้วยรหัสผ่านเดียวกัน", - "UPDATED" => "ปรังปรุงรหัสผ่านของบัญชีแล้ว" - ], - - "REGISTER" => "สมัครสมาชิก", - "REGISTER_ME" => "ให้ฉันสมัครสมาชิกด้วย", - - "REGISTRATION" => [ - "BROKEN" => "เราขออภัย มันมีปัญหาในการดำเนินการสมัครสมาชิกของเรา กรุณาติดต่อเราโดยตรงเพื่อขอความช่วยเหลือ", - "COMPLETE_TYPE1" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที", - "COMPLETE_TYPE2" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณจะได้รับอีเมลยืนยันที่มีลิงก์สำหรับเปิดใช้งานบัญชีของคุณอยู่ คุณจะไม่สามารถเข้าสู่ระบบจนกว่าคุณจะยืนยันอีเมลแล้ว", - "DISABLED" => "เราขออภัย ระบบสมัครสมาชิกได้ถูกปิดไว้", - "LOGOUT" => "เราขออภัย คุณไม่สามารถสมัครสมาชิกขณะที่เข้าสู่ระบบอยู่ กรุณาออกจากระบบก่อน", - "WELCOME" => "การสมัครสมาชิกนั้นรวดเร็ว และง่ายดาย" - ], - - "RATE_LIMIT_EXCEEDED" => "ถึงขีดจำกัดสำหรับการกระทำนี้แล้ว คุณจะต้องรออีก {{delay}} วินาที ก่อนที่คุณจะได้รับอนุญาตให้ลองใหม่อีกครั้ง", - "REMEMBER_ME" => "จำฉันไว้ในระบบ!", - "REMEMBER_ME_ON_COMPUTER" => "จำฉันไว้ในระบบบนคอมพิวเตอร์นี้ (ไม่แนะนำสำหรับคอมพิวเตอร์สาธารณะ)", - - "SIGNIN" => "เข้าสู่ะระบบ", - "SIGNIN_OR_REGISTER" => "เข้าสู่ระบบหรือสมัครสมาชิก", - "SIGNUP" => "สมัครสมาชิก", - - "TOS" => "ข้อตกลงและเงื่อนไข", - "TOS_AGREEMENT" => "ในการสมัครสมาชิกกับ {{site_title}} หมายถึงคุณยอมรับ ข้อตกลงและเงื่อนไข แล้ว", - "TOS_FOR" => "ข้อตกลงและเงื่อนไขสำหรับ {{title}}", - - "USERNAME" => [ - "@TRANSLATION" => "ชื่อผู้ใช้", - - "CHOOSE" => "เลือกชื่อผู้ใช้ที่เป็นเป็นเอกลักษณ์", - "INVALID" => "ชื่อผู้ใช้ไม่ถูกต้อง", - "IN_USE" => "ชื่อผู้ใช้ {{user_name}} ถูกใช้งานแล้ว" - ], - - "USER_ID_INVALID" => "ไม่พบหมายเลขผู้ใช้ที่ร้องขอมา", - "USER_OR_EMAIL_INVALID" => "ชื่อผู้ใช้หรือที่อยู่อีเมลไม่ถูกต้อง", - "USER_OR_PASS_INVALID" => "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง", - - "WELCOME" => "ยินดีต้อนรับ {{first_name}}" -]; + [ + "@TRANSLATION" => "บัญชี", + + "ACCESS_DENIED" => "หืมม ดูเหมือนว่าคุณไม่ได้รับอนุญาตให้ทำเช่นนั้น", + + "DISABLED" => "บัญชีนี้ถูกปิดการใช้งานไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม", + + "EMAIL_UPDATED" => "ปรับปรุงบัญชีอีเมลแล้ว", + + "INVALID" => "ไม่พบบัญชีนี้ มันอาจถูกลบไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม", + + "MASTER_NOT_EXISTS" => "คุณไม่สามารถสมัครสมาชิกได้จนกว่าจะสร้างบัญชีหลัก!", + "MY" => "บัญชีของฉัน", + + "SESSION_COMPROMISED" => "เซสชันของคุณถูกลักลอบใช้ คุณควรจะออกจากระบบบนอุปกรณ์ทั้งหมดแล้วกลับเข้าสู่ระบบและตรวจสอบให้แน่ใจว่าไม่มีการแก้ไขข้อมูลของคุณ", + "SESSION_COMPROMISED_TITLE" => "บัญชีของคุณอาจถูกบุกรุก", + "SESSION_EXPIRED" => "เซสชันของคุณหมดอายุ กรุณาเข้าสู่ระบบอีกครั้ง", + + "SETTINGS" => [ + "@TRANSLATION" => "การตั้งค่าบัญชี", + "DESCRIPTION" => "ปรับปรุงการตั้งค่าบัญชีของคุณ รวมไปถึงอีเมล ชื่อ และรหัสผ่าน", + "UPDATED" => "ปรับปรุงการตั้งค่าบัญชีของคุณแล้ว" + ], + + "TOOLS" => "เครื่องมือบัญชี", + + "UNVERIFIED" => "บัญชีของคุณยังไม่ได้รับการยืนยัน กรุณาตรวจสอบกล่องอีเมลและจดหมายขยะของคุณสำหรับขั้นตอนการเปิดใช้งานบัญชี", + + "VERIFICATION" => [ + "NEW_LINK_SENT" => "เราได้ส่งลิงก์สำหรับการยืนยันใหม่ไปยังอีเมล {{email}} กรุณาตรวจสอบอีเมลนี้ในกล่องอีเมลและจดหมายขยะของคุณ", + "RESEND" => "ส่งอีเมลยืนยันอีกครั้ง", + "COMPLETE" => "คุณได้ยืนยันอีเมลของคุณเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที", + "EMAIL" => "กรุณากรอกอีเมลที่คุณได้ใช้สมัครไว้แล้วอีเมลยืนยันจะถูกส่งไปให้ใหม่", + "PAGE" => "ส่งอีเมลยืนยันสำหรับบัญชีของฉันใหม่", + "SEND" => "ส่งอีเมลยืนยันให้บัญชีของฉัน", + "TOKEN_NOT_FOUND" => "ไม่พบโทเคนยืนยันอีเมล / บัญชีนี้ได้ยืนยันแล้ว", + ] + ], + + "EMAIL" => [ + "INVALID" => "อีเมล {{email}} ไม่มีอยู่จริง", + "IN_USE" => "อีเมล {{email}} ได้ถูกใช้งานแล้ว" + ], + + "FIRST_NAME" => "ชื่อจริง", + + "HEADER_MESSAGE_ROOT" => "คุณได้เข้าสู่ระบบเป็นผู้ดูแลสูงสุด", + + "LAST_NAME" => "นามสกุล", + + "LOCALE.ACCOUNT" => "ภาษาและสถานที่ที่จะใช้สำหรับบัญชีของคุณ", + + "LOGIN" => [ + "@TRANSLATION" => "เข้าสู่ะระบบ", + + "ALREADY_COMPLETE" => "คุณได้เข้าสู่ระบบอยู่แล้ว!", + "SOCIAL" => "หรือเข้าสู่ระบบด้วย", + "REQUIRED" => "ขออภัย คุณจะต้องเข้าสู่ระบบเพื่อเข้าถึงส่วนนี้" + ], + + "LOGOUT" => "ออกจากระบบ", + + "NAME" => "ชื่อ", + + "PAGE" => [ + "LOGIN" => [ + "DESCRIPTION" => "เข้าสู่ระบบไปยังบัญชี {{site_name}} หรือสมัครสมาชิกสำหรับบัญชีใหม่", + "SUBTITLE" => "สมัครสมาชิกฟรี หรือเข้าสู่ระบบด้วยบัญชีที่มีอยู่", + "TITLE" => "มาเริ่มกันเลย!", + ] + ], + + "PASSWORD" => [ + "@TRANSLATION" => "รหัสผ่าน", + + "BETWEEN" => "ระหว่าง {{min}}-{{max}} ตัวอักษร", + + "CONFIRM" => "ยืนยันรหัสผ่าน", + "CONFIRM_CURRENT" => "กรุณายืนยันรหัสผ่านปัจจุบันของคุณ", + "CONFIRM_NEW" => "ยืนยันรหัสผ่านใหม่", + "CONFIRM_NEW_EXPLAIN" => "กรอกรหัสผ่านใหม่ของคุณอีกครั้ง", + "CONFIRM_NEW_HELP" => "กรอกเฉพาะเมื่อคุณต้องการตั้งรหัสผ่านใหม่", + "CURRENT" => "รหัสผ่านปัจจุบัน", + "CURRENT_EXPLAIN" => "คุณจะต้องยืนยันรหัสผ่านปัจจุบันเพื่อแก้ไขข้อมูล", + + "FORGOTTEN" => "ลืมรหัสผ่าน", + "FORGET" => [ + "@TRANSLATION" => "ฉันลืมรหัสผ่านของฉัน", + + "COULD_NOT_UPDATE" => "ไม่สามารถปรับปรุงรหัสผ่าน", + "EMAIL" => "กรุณากรอกที่อยู่อีเมลที่คุณเคยใช้เข้าสู่ระบบ ลิงก์ขั้นตอนการรีเซ็ตรหัสผ่านของคุณจะถูกส่งไปให้คุณ", + "EMAIL_SEND" => "ลิงก์รีเซ็ตรหัสผ่านจากอีเมล", + "INVALID" => "ขอรีเซ็ตรหัสผ่านนี้ไม่มีอยู่ หรือหมดอายุไปแล้ว กรุณาลอง ส่งคำขอของคุณอีกครั้ง", + "PAGE" => "รับลิงก์สำหรับการรีเซ็ตรหัสผ่านของคุณ", + "REQUEST_CANNED" => "คำขอลืมรหัสผ่านได้ถูกยกเลิก", + "REQUEST_SENT" => "หากอีเมล {{email}} ตรงกับบัญชีในระบบของเราลิงก์การรีเซ็ตรหัสผ่านจะถูกส่งไปที่ {{email}}" + ], + + "RESET" => [ + "@TRANSLATION" => "รีเซ็ตรหัสผ่าน", + "CHOOSE" => "กรุณาเลือกรหัสผ่านใหม่เพื่อดำเนินการต่อ", + "PAGE" => "เลือกรหัสผ่านใหม่สำหรับบัญชีของคุณ", + "SEND" => "ตั้งรหัสผ่านใหม่และเข้าสู่ระบบ" + ], + + "HASH_FAILED" => "เข้ารหัสรหัสผ่านล้มเหลว กรุณาติดต่อผู้ดูแลระบบของเว็บไซต์", + "INVALID" => "รหัสผ่านปัจจุบันไม่ตรงกับรหัสผ่านที่เราบันทึกไว้", + "NEW" => "รหัสผ่านใหม่", + "NOTHING_TO_UPDATE" => "คุณไม่สามารถปรังปรุงด้วยรหัสผ่านเดียวกัน", + "UPDATED" => "ปรังปรุงรหัสผ่านของบัญชีแล้ว" + ], + + "REGISTER" => "สมัครสมาชิก", + "REGISTER_ME" => "ให้ฉันสมัครสมาชิกด้วย", + + "REGISTRATION" => [ + "BROKEN" => "เราขออภัย มันมีปัญหาในการดำเนินการสมัครสมาชิกของเรา กรุณาติดต่อเราโดยตรงเพื่อขอความช่วยเหลือ", + "COMPLETE_TYPE1" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที", + "COMPLETE_TYPE2" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณจะได้รับอีเมลยืนยันที่มีลิงก์สำหรับเปิดใช้งานบัญชีของคุณอยู่ คุณจะไม่สามารถเข้าสู่ระบบจนกว่าคุณจะยืนยันอีเมลแล้ว", + "DISABLED" => "เราขออภัย ระบบสมัครสมาชิกได้ถูกปิดไว้", + "LOGOUT" => "เราขออภัย คุณไม่สามารถสมัครสมาชิกขณะที่เข้าสู่ระบบอยู่ กรุณาออกจากระบบก่อน", + "WELCOME" => "การสมัครสมาชิกนั้นรวดเร็ว และง่ายดาย" + ], + + "RATE_LIMIT_EXCEEDED" => "ถึงขีดจำกัดสำหรับการกระทำนี้แล้ว คุณจะต้องรออีก {{delay}} วินาที ก่อนที่คุณจะได้รับอนุญาตให้ลองใหม่อีกครั้ง", + "REMEMBER_ME" => "จำฉันไว้ในระบบ!", + "REMEMBER_ME_ON_COMPUTER" => "จำฉันไว้ในระบบบนคอมพิวเตอร์นี้ (ไม่แนะนำสำหรับคอมพิวเตอร์สาธารณะ)", + + "SIGNIN" => "เข้าสู่ะระบบ", + "SIGNIN_OR_REGISTER" => "เข้าสู่ระบบหรือสมัครสมาชิก", + "SIGNUP" => "สมัครสมาชิก", + + "TOS" => "ข้อตกลงและเงื่อนไข", + "TOS_AGREEMENT" => "ในการสมัครสมาชิกกับ {{site_title}} หมายถึงคุณยอมรับ ข้อตกลงและเงื่อนไข แล้ว", + "TOS_FOR" => "ข้อตกลงและเงื่อนไขสำหรับ {{title}}", + + "USERNAME" => [ + "@TRANSLATION" => "ชื่อผู้ใช้", + + "CHOOSE" => "เลือกชื่อผู้ใช้ที่เป็นเป็นเอกลักษณ์", + "INVALID" => "ชื่อผู้ใช้ไม่ถูกต้อง", + "IN_USE" => "ชื่อผู้ใช้ {{user_name}} ถูกใช้งานแล้ว" + ], + + "USER_ID_INVALID" => "ไม่พบหมายเลขผู้ใช้ที่ร้องขอมา", + "USER_OR_EMAIL_INVALID" => "ชื่อผู้ใช้หรือที่อยู่อีเมลไม่ถูกต้อง", + "USER_OR_PASS_INVALID" => "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง", + + "WELCOME" => "ยินดีต้อนรับ {{first_name}}" +]; diff --git a/app/sprinkles/account/locale/th_TH/validate.php b/app/sprinkles/account/locale/th_TH/validate.php index 1a2e90a2b..14a7adb2d 100644 --- a/app/sprinkles/account/locale/th_TH/validate.php +++ b/app/sprinkles/account/locale/th_TH/validate.php @@ -1,18 +1,18 @@ - [ - "PASSWORD_MISMATCH" => "รหัสผ่านและรหัสผ่านยืนยันของคุณจะต้องตรงกัน" - ] -]; + [ + "PASSWORD_MISMATCH" => "รหัสผ่านและรหัสผ่านยืนยันของคุณจะต้องตรงกัน" + ] +]; diff --git a/app/sprinkles/account/locale/tr/validate.php b/app/sprinkles/account/locale/tr/validate.php index 298bdbc38..cd4380be4 100644 --- a/app/sprinkles/account/locale/tr/validate.php +++ b/app/sprinkles/account/locale/tr/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "Şifreniz ve onaylama şifreniz eşleşmiyor.", "USERNAME" => "Kullanıcı adınız sadece küçük harfler, sayılar, '.', '-', ve '_' içerebilir." ] diff --git a/app/sprinkles/account/locale/zh_CN/validate.php b/app/sprinkles/account/locale/zh_CN/validate.php index 3ca368ad2..db58c06cf 100644 --- a/app/sprinkles/account/locale/zh_CN/validate.php +++ b/app/sprinkles/account/locale/zh_CN/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "PASSWORD_MISMATCH" => "密码不一致.", "USERNAME" => "用户名必须以小写字母, 数字, '.', '-', 和 '_'组成." ] diff --git a/app/sprinkles/account/src/Account.php b/app/sprinkles/account/src/Account.php index 49c2de9ab..99cc8894e 100644 --- a/app/sprinkles/account/src/Account.php +++ b/app/sprinkles/account/src/Account.php @@ -16,5 +16,4 @@ */ class Account extends Sprinkle { - } diff --git a/app/sprinkles/account/src/Account/Registration.php b/app/sprinkles/account/src/Account/Registration.php index 7d5a36dbe..f88a3ce35 100644 --- a/app/sprinkles/account/src/Account/Registration.php +++ b/app/sprinkles/account/src/Account/Registration.php @@ -106,7 +106,7 @@ public function register() // All checks passed! log events/activities, create user, and send verification email (if required) // Begin transaction - DB will be rolled back if an exception occurs - $user = Capsule::transaction(function() { + $user = Capsule::transaction(function () { // Log throttleable event $this->ci->throttler->logEvent('registration_attempt'); @@ -326,4 +326,4 @@ public function setUserProperty($property, $value) { $this->userdata[$property] = $value; } -} \ No newline at end of file +} diff --git a/app/sprinkles/account/src/Authenticate/Hasher.php b/app/sprinkles/account/src/Authenticate/Hasher.php index ad126c204..25a09ed48 100644 --- a/app/sprinkles/account/src/Authenticate/Hasher.php +++ b/app/sprinkles/account/src/Authenticate/Hasher.php @@ -81,7 +81,6 @@ public function verify($password, $hash, array $options = []) $inputHash = $salt . sha1($salt . $password); return (hash_equals($inputHash, $hash) === true); - } elseif ($hashType == 'legacy') { // Homegrown implementation (assuming that current install has been using a cost parameter of 12) // Used for manual implementation of bcrypt. diff --git a/app/sprinkles/account/src/Authorize/AuthorizationException.php b/app/sprinkles/account/src/Authorize/AuthorizationException.php index 251b67fe4..8e4d90708 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationException.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationException.php @@ -19,5 +19,4 @@ */ class AuthorizationException extends ForbiddenException { - } diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 3dfd1e191..5db626be3 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -71,7 +71,7 @@ public function checkUsername(Request $request, Response $response, $args) // TODO: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException $e = new BadRequestException('Missing or malformed request data!'); foreach ($validator->errors() as $idx => $field) { - foreach($field as $eidx => $error) { + foreach ($field as $eidx => $error) { $e->addUserMessage($error); } } @@ -224,7 +224,7 @@ public function forgotPassword(Request $request, Response $response, $args) // All checks passed! log events/activities, update user, and send email // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $throttler, $throttleData, $config) { + Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config) { // Log throttleable event $throttler->logEvent('password_reset_request', $throttleData); @@ -977,7 +977,7 @@ public function resendVerification(Request $request, Response $response, $args) // All checks passed! log events/activities, create user, and send verification email (if required) // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $throttler, $throttleData, $config) { + Capsule::transaction(function () use ($classMapper, $data, $throttler, $throttleData, $config) { // Log throttleable event $throttler->logEvent('verification_request', $throttleData); diff --git a/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php b/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php index 971336048..1571763ce 100644 --- a/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php +++ b/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php @@ -16,5 +16,4 @@ */ class SpammyRequestException extends HttpException { - } diff --git a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php index bf38ca09b..c4cdf223f 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php @@ -49,4 +49,4 @@ public function down() { $this->schema->drop('activities'); } -} \ No newline at end of file +} diff --git a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php index d2c9ce418..aa87b22d3 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php @@ -27,7 +27,7 @@ class GroupsTable extends Migration public function up() { if (!$this->schema->hasTable('groups')) { - $this->schema->create('groups', function(Blueprint $table) { + $this->schema->create('groups', function (Blueprint $table) { $table->increments('id'); $table->string('slug'); $table->string('name'); diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php index a4fc7595d..f0149546e 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php @@ -26,7 +26,7 @@ class PermissionsTable extends Migration /** * {@inheritdoc} */ - static public $dependencies = [ + public static $dependencies = [ '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\RolesTable', '\UserFrosting\Sprinkle\Account\Database\Migrations\v400\PermissionRolesTable' ]; @@ -37,7 +37,7 @@ class PermissionsTable extends Migration public function up() { if (!$this->schema->hasTable('permissions')) { - $this->schema->create('permissions', function(Blueprint $table) { + $this->schema->create('permissions', function (Blueprint $table) { $table->increments('id'); $table->string('slug')->comment('A code that references a specific action or URI that an assignee of this permission has access to.'); $table->string('name'); @@ -53,7 +53,6 @@ public function up() // Skip this if table is not empty if (Permission::count() == 0) { - $defaultRoleIds = [ 'user' => Role::where('slug', 'user')->first()->id, 'group-admin' => Role::where('slug', 'group-admin')->first()->id, diff --git a/app/sprinkles/account/src/Database/Models/PasswordReset.php b/app/sprinkles/account/src/Database/Models/PasswordReset.php index 8cf7d00bc..01bb2abc0 100644 --- a/app/sprinkles/account/src/Database/Models/PasswordReset.php +++ b/app/sprinkles/account/src/Database/Models/PasswordReset.php @@ -65,7 +65,7 @@ public function setToken($value) /** * Get the user associated with this reset request. - * + * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index 8771738d6..9b2ff0a41 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -140,7 +140,7 @@ public function __get($name) return $this->lastActivityTime('sign_in'); } elseif ($name == 'avatar') { // Use Gravatar as the user avatar - $hash = md5(strtolower(trim( $this->email))); + $hash = md5(strtolower(trim($this->email))); return 'https://www.gravatar.com/avatar/' . $hash . '?d=mm'; } else { return parent::__get($name); diff --git a/app/sprinkles/account/src/Database/Models/Verification.php b/app/sprinkles/account/src/Database/Models/Verification.php index cb897acf9..8d03274bf 100644 --- a/app/sprinkles/account/src/Database/Models/Verification.php +++ b/app/sprinkles/account/src/Database/Models/Verification.php @@ -65,7 +65,7 @@ public function setToken($value) /** * Get the user associated with this verification request. - * + * * @return \Illuminate\Database\Eloquent\Relations\BelongsTo */ public function user() diff --git a/app/sprinkles/account/src/Repository/TokenRepository.php b/app/sprinkles/account/src/Repository/TokenRepository.php index 25b8b8afb..35a886ddc 100644 --- a/app/sprinkles/account/src/Repository/TokenRepository.php +++ b/app/sprinkles/account/src/Repository/TokenRepository.php @@ -212,7 +212,7 @@ protected function generateRandomToken($gen = null) { do { $gen = md5(uniqid(mt_rand(), false)); - } while($this->classMapper + } while ($this->classMapper ->staticMethod($this->modelIdentifier, 'where', 'hash', hash($this->algorithm, $gen)) ->first()); return $gen; diff --git a/app/sprinkles/account/tests/Unit/FactoriesTest.php b/app/sprinkles/account/tests/Unit/FactoriesTest.php index 766d408a9..19b8fd284 100644 --- a/app/sprinkles/account/tests/Unit/FactoriesTest.php +++ b/app/sprinkles/account/tests/Unit/FactoriesTest.php @@ -36,7 +36,7 @@ public function setUp() /** * Test the user factory */ - function testUserFactory() + public function testUserFactory() { $fm = $this->ci->factory; diff --git a/app/sprinkles/account/tests/Unit/RegistrationTest.php b/app/sprinkles/account/tests/Unit/RegistrationTest.php index ed92c98da..cb40e59cc 100644 --- a/app/sprinkles/account/tests/Unit/RegistrationTest.php +++ b/app/sprinkles/account/tests/Unit/RegistrationTest.php @@ -126,4 +126,4 @@ public function testMissingFields() $this->expectException(HttpException::class); $validation = $registration->validate(); } -} \ No newline at end of file +} diff --git a/app/sprinkles/admin/locale/fa/messages.php b/app/sprinkles/admin/locale/fa/messages.php index 75a8dee1c..1299c2c3e 100644 --- a/app/sprinkles/admin/locale/fa/messages.php +++ b/app/sprinkles/admin/locale/fa/messages.php @@ -13,30 +13,30 @@ */ return [ - "ACTIVITY" => [ - 1 => "فعالیت", - 2 => "فعالیت ها", - - "LAST" => "آخرین فعالیت", - "PAGE" => "لیستی از فعالیت های کاربر", - "TIME" => "زمان فعالیت" - ], - - "CACHE" => [ - "CLEAR" => "پاک سازی کش", - "CLEAR_CONFIRM" => "آیا مطمئن هستید که میخواهید کش سایت را پاک سازی کنید؟", - "CLEAR_CONFIRM_YES" => "بله، کش پاک سازی شود", - "CLEARED" => "کش با موفقیت پاک سازی شد" - ], - - "DASHBOARD" => "کارتابل", - "DELETE_MASTER" => "شما نمیتوانید کاربر اصلی را حذف کنید", - "DELETION_SUCCESSFUL" => "{{user_name}} با موفقیت حذف شد.", - "DETAILS_UPDATED" => "جزئیات {{user_name}} با موفقیت ذخیره شد.", - "DISABLE_MASTER" => "شما نمیتوانید کاربر اصلی را غیر فعال کنید.", - "DISABLE_SUCCESSFUL" => "حساب کاربری {{user_name}} با موفقیت غیر فعال شد.", - - "ENABLE_SUCCESSFUL" => "حساب کاربری {{user_name}} با موفقیت فعال شد.", + "ACTIVITY" => [ + 1 => "فعالیت", + 2 => "فعالیت ها", + + "LAST" => "آخرین فعالیت", + "PAGE" => "لیستی از فعالیت های کاربر", + "TIME" => "زمان فعالیت" + ], + + "CACHE" => [ + "CLEAR" => "پاک سازی کش", + "CLEAR_CONFIRM" => "آیا مطمئن هستید که میخواهید کش سایت را پاک سازی کنید؟", + "CLEAR_CONFIRM_YES" => "بله، کش پاک سازی شود", + "CLEARED" => "کش با موفقیت پاک سازی شد" + ], + + "DASHBOARD" => "کارتابل", + "DELETE_MASTER" => "شما نمیتوانید کاربر اصلی را حذف کنید", + "DELETION_SUCCESSFUL" => "{{user_name}} با موفقیت حذف شد.", + "DETAILS_UPDATED" => "جزئیات {{user_name}} با موفقیت ذخیره شد.", + "DISABLE_MASTER" => "شما نمیتوانید کاربر اصلی را غیر فعال کنید.", + "DISABLE_SUCCESSFUL" => "حساب کاربری {{user_name}} با موفقیت غیر فعال شد.", + + "ENABLE_SUCCESSFUL" => "حساب کاربری {{user_name}} با موفقیت فعال شد.", "GROUP" => [ 1 => "گروه", diff --git a/app/sprinkles/admin/locale/fr_FR/messages.php b/app/sprinkles/admin/locale/fr_FR/messages.php index 82bdf3ef9..5020cdf97 100644 --- a/app/sprinkles/admin/locale/fr_FR/messages.php +++ b/app/sprinkles/admin/locale/fr_FR/messages.php @@ -144,4 +144,4 @@ 1 => "{{plural}} utilisateur", 2 => "{{plural}} utilisateurs" ] -]; \ No newline at end of file +]; diff --git a/app/sprinkles/admin/locale/th_TH/messages.php b/app/sprinkles/admin/locale/th_TH/messages.php index 546232d25..e31090ae3 100644 --- a/app/sprinkles/admin/locale/th_TH/messages.php +++ b/app/sprinkles/admin/locale/th_TH/messages.php @@ -1,134 +1,134 @@ - [ - 1 => "กิจกรรม", - 2 => "กิจกรรม", - - "LAST" => "กิจกรรมล่าสุด", - "PAGE" => "รายการกิจกรรมของผู้ใช้", - "TIME" => "เวลาที่ทำกิจกรรม" - ], - - "CACHE" => [ - "CLEAR" => "ล้างแคช", - "CLEAR_CONFIRM" => "คุณแน่ใจหรือที่จะล้างแคชของเว็บ?", - "CLEAR_CONFIRM_YES" => "ใช่ ล้างแคชเลย", - "CLEARED" => "ล้างแคชเรียบร้อยแล้ว!" - ], - - "DASHBOARD" => "แผงควบคุม", - "DELETE_MASTER" => "คุณไม่สามารถลบบัญชีหลักได้!", - "DELETION_SUCCESSFUL" => "ลบผู้ใช้ {{user_name}} เรียบร้อยแล้ว", - "DETAILS_UPDATED" => "ปรับปรุงรายระเอียดบัญชีให้กับ {{user_name}} แล้ว", - "DISABLE_MASTER" => "คุณไม่สามารถปิดการใช้งานบัญชีหลัก!", - "DISABLE_SUCCESSFUL" => "ปิดการใช้งานบัญชีของผู้ใช้ {{user_name}} เรียบร้อยแล้ว", - - "ENABLE_SUCCESSFUL" => "เปิดการใช้งานบัญชีของผู้ใช้ {{user_name}} เรียบร้อยแล้ว", - - "GROUP" => [ - 1 => "กลุ่ม", - 2 => "กลุ่ม", - - "CREATE" => "สร้างกลุ่ม", - "DELETE" => "ลบกลุ่ม", - "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบกลุ่ม {{name}}?", - "DELETE_YES" => "ใช่ ลบกลุ่มนี้เลย", - "EDIT" => "แก้ไขกลุ่ม", - "ICON" => "ไอคอนกลุ่ม", - "ICON_EXPLAIN" => "ไอคอนสำหรับสมาชิกกลุ่ม", - "INFO_PAGE" => "หน้าข้อมูลกลุ่มสำหรับ {{name}}", - //"MANAGE" => "Manage group", - "NAME" => "ชื่อกลุ่ม", - "NAME_EXPLAIN" => "กรุณาตั้งชื่อสำหรับกลุ่มนี้", - "PAGE_DESCRIPTION" => "รายชื่อกลุ่มในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับการแก้ไขและลบกลุ่ม" - ], - - "MANUALLY_ACTIVATED" => "บัญชีของ {{user_name}} ได้เปิดใช้งานเองแล้ว", - "MASTER_ACCOUNT_EXISTS" => "มีบัญชีหลักอยู่แล้ว!", - "MIGRATION" => [ - "REQUIRED" => "ต้องการการปรับปรุงฐานข้อมูล" - ], - - "PERMISSION" => [ - 1 => "สิทธิการเข้าถึง", - 2 => "สิทธิการเข้าถึง", - - "ASSIGN_NEW" => "กำหนดสิทธิการเข้าถึงใหม่", - "HOOK_CONDITION" => "ข้อกำหนด/เงื่อนไข", - "MANAGE" => "จัดการสิทธิการเข้าถึง", - "PAGE_DESCRIPTION" => "รายการสิทธิการเข้าถึงในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับการแก้ไขและลบสิทธิการเข้าถึง", - "UPDATE" => "ปรับปรุงสิทธิการเข้าถึง" - ], - - "ROLE" => [ - 1 => "ตำแหน่ง", - 2 => "ตำแหน่ง", - - "ASSIGN_NEW" => "กำหนดตำแหน่งใหม่", - "CREATE" => "สร้างตำแหน่ง", - "DELETE" => "ลบตำแหน่ง", - "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบตำแหน่ง {{name}}?", - "DELETE_YES" => "ใช่ ลบตำแหน่งนี้เลย", - "EDIT" => "แก้ไขตำแหน่ง", - "INFO_PAGE" => "หน้าข้อมูลตำแหน่งสำหรับ {{name}}", - "MANAGE" => "จัดการตำแหน่ง", - "NAME" => "ชื่อ", - "NAME_EXPLAIN" => "กรุณาตั้งชื่อสำหรับตำแหน่งนี้", - "PAGE_DESCRIPTION" => "รายชื่อตำแหน่งในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับแก้ไขและลบตำแหน่ง", - "UPDATED" => "ปรับปรุงตำแหน่ง" - ], - - "SYSTEM_INFO" => [ - "@TRANSLATION" => "ข้อมูลระบบ", - - "DB_NAME" => "ชื่อฐานข้อมูล", - "DB_VERSION" => "เวอร์ชั่นฐานข้อมูล", - "DIRECTORY" => "ไดเรกทอรีของโปรเจค", - "PHP_VERSION" => "เวอร์ชั่น PHP", - "SERVER" => "ซอฟต์แวร์เว็บเซิร์ฟเวอร์", - "SPRINKLES" => "Sprinkles ที่ถูกโหลด", - "UF_VERSION" => "เวอร์ชั่น UserFrosting", - "URL" => "URL ของรากเว็บไซต์" - ], - - "USER" => [ - 1 => "ผู้ใช้", - 2 => "ผู้ใช้", - - "ADMIN" => [ - "CHANGE_PASSWORD" => "เปลี่ยนรหัสผ่านผู้ใช้", - "SEND_PASSWORD_LINK" => "ส่งลิงก์ที่จะอนุญาตให้ผู้ใช้เลือกรหัสผ่านเองให้กับผู้ใช้", - "SET_PASSWORD" => "ตั้งรหัสผ่านของผู้ใช้เป็น" - ], - - "ACTIVATE" => "เปิดใช้งานผู้ใช้", - "CREATE" => "สร้างผู้ใช้", - "DELETE" => "ลบผู้ใช้", - "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบผู้ใช้ {{name}}?", - "DELETE_YES" => "ใช่ ลบผู้ใช้นี้เลย", - "DISABLE" => "ปิดการใช้งานผู้ใช้", - "EDIT" => "แก้ไขผู้ใช้", - "ENABLE" => "เปิดการใช้งานผู้ใช้", - "INFO_PAGE" => "หน้าข้อมูลของผู้ใช้ {{name}}", - "PAGE_DESCRIPTION" => "รายชื่อผู้ใช้ในเว็บของคุณ ประกอบไปด้วยเครื่องมือสำหรับการจัดการ รวมทั้งความสามารถในการแก้ไขรายละเอียดผู้ใช้ การเปิดใช้งานผู้ใช้ การเปิด/ปิดบัญชีผู้ใช้และอื่น ๆ", - "LATEST" => "ผู้ใช้ล่าสุด", - "VIEW_ALL" => "ดูผู้ใช้ทั้งหมด" - ], - "X_USER" => [ - 0 => "ไม่มีผู้ใช้", - 1 => "{{plural}} ผู้ใช้", - 2 => "{{plural}} ผู้ใช้" - ] -]; \ No newline at end of file + [ + 1 => "กิจกรรม", + 2 => "กิจกรรม", + + "LAST" => "กิจกรรมล่าสุด", + "PAGE" => "รายการกิจกรรมของผู้ใช้", + "TIME" => "เวลาที่ทำกิจกรรม" + ], + + "CACHE" => [ + "CLEAR" => "ล้างแคช", + "CLEAR_CONFIRM" => "คุณแน่ใจหรือที่จะล้างแคชของเว็บ?", + "CLEAR_CONFIRM_YES" => "ใช่ ล้างแคชเลย", + "CLEARED" => "ล้างแคชเรียบร้อยแล้ว!" + ], + + "DASHBOARD" => "แผงควบคุม", + "DELETE_MASTER" => "คุณไม่สามารถลบบัญชีหลักได้!", + "DELETION_SUCCESSFUL" => "ลบผู้ใช้ {{user_name}} เรียบร้อยแล้ว", + "DETAILS_UPDATED" => "ปรับปรุงรายระเอียดบัญชีให้กับ {{user_name}} แล้ว", + "DISABLE_MASTER" => "คุณไม่สามารถปิดการใช้งานบัญชีหลัก!", + "DISABLE_SUCCESSFUL" => "ปิดการใช้งานบัญชีของผู้ใช้ {{user_name}} เรียบร้อยแล้ว", + + "ENABLE_SUCCESSFUL" => "เปิดการใช้งานบัญชีของผู้ใช้ {{user_name}} เรียบร้อยแล้ว", + + "GROUP" => [ + 1 => "กลุ่ม", + 2 => "กลุ่ม", + + "CREATE" => "สร้างกลุ่ม", + "DELETE" => "ลบกลุ่ม", + "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบกลุ่ม {{name}}?", + "DELETE_YES" => "ใช่ ลบกลุ่มนี้เลย", + "EDIT" => "แก้ไขกลุ่ม", + "ICON" => "ไอคอนกลุ่ม", + "ICON_EXPLAIN" => "ไอคอนสำหรับสมาชิกกลุ่ม", + "INFO_PAGE" => "หน้าข้อมูลกลุ่มสำหรับ {{name}}", + //"MANAGE" => "Manage group", + "NAME" => "ชื่อกลุ่ม", + "NAME_EXPLAIN" => "กรุณาตั้งชื่อสำหรับกลุ่มนี้", + "PAGE_DESCRIPTION" => "รายชื่อกลุ่มในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับการแก้ไขและลบกลุ่ม" + ], + + "MANUALLY_ACTIVATED" => "บัญชีของ {{user_name}} ได้เปิดใช้งานเองแล้ว", + "MASTER_ACCOUNT_EXISTS" => "มีบัญชีหลักอยู่แล้ว!", + "MIGRATION" => [ + "REQUIRED" => "ต้องการการปรับปรุงฐานข้อมูล" + ], + + "PERMISSION" => [ + 1 => "สิทธิการเข้าถึง", + 2 => "สิทธิการเข้าถึง", + + "ASSIGN_NEW" => "กำหนดสิทธิการเข้าถึงใหม่", + "HOOK_CONDITION" => "ข้อกำหนด/เงื่อนไข", + "MANAGE" => "จัดการสิทธิการเข้าถึง", + "PAGE_DESCRIPTION" => "รายการสิทธิการเข้าถึงในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับการแก้ไขและลบสิทธิการเข้าถึง", + "UPDATE" => "ปรับปรุงสิทธิการเข้าถึง" + ], + + "ROLE" => [ + 1 => "ตำแหน่ง", + 2 => "ตำแหน่ง", + + "ASSIGN_NEW" => "กำหนดตำแหน่งใหม่", + "CREATE" => "สร้างตำแหน่ง", + "DELETE" => "ลบตำแหน่ง", + "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบตำแหน่ง {{name}}?", + "DELETE_YES" => "ใช่ ลบตำแหน่งนี้เลย", + "EDIT" => "แก้ไขตำแหน่ง", + "INFO_PAGE" => "หน้าข้อมูลตำแหน่งสำหรับ {{name}}", + "MANAGE" => "จัดการตำแหน่ง", + "NAME" => "ชื่อ", + "NAME_EXPLAIN" => "กรุณาตั้งชื่อสำหรับตำแหน่งนี้", + "PAGE_DESCRIPTION" => "รายชื่อตำแหน่งในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับแก้ไขและลบตำแหน่ง", + "UPDATED" => "ปรับปรุงตำแหน่ง" + ], + + "SYSTEM_INFO" => [ + "@TRANSLATION" => "ข้อมูลระบบ", + + "DB_NAME" => "ชื่อฐานข้อมูล", + "DB_VERSION" => "เวอร์ชั่นฐานข้อมูล", + "DIRECTORY" => "ไดเรกทอรีของโปรเจค", + "PHP_VERSION" => "เวอร์ชั่น PHP", + "SERVER" => "ซอฟต์แวร์เว็บเซิร์ฟเวอร์", + "SPRINKLES" => "Sprinkles ที่ถูกโหลด", + "UF_VERSION" => "เวอร์ชั่น UserFrosting", + "URL" => "URL ของรากเว็บไซต์" + ], + + "USER" => [ + 1 => "ผู้ใช้", + 2 => "ผู้ใช้", + + "ADMIN" => [ + "CHANGE_PASSWORD" => "เปลี่ยนรหัสผ่านผู้ใช้", + "SEND_PASSWORD_LINK" => "ส่งลิงก์ที่จะอนุญาตให้ผู้ใช้เลือกรหัสผ่านเองให้กับผู้ใช้", + "SET_PASSWORD" => "ตั้งรหัสผ่านของผู้ใช้เป็น" + ], + + "ACTIVATE" => "เปิดใช้งานผู้ใช้", + "CREATE" => "สร้างผู้ใช้", + "DELETE" => "ลบผู้ใช้", + "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบผู้ใช้ {{name}}?", + "DELETE_YES" => "ใช่ ลบผู้ใช้นี้เลย", + "DISABLE" => "ปิดการใช้งานผู้ใช้", + "EDIT" => "แก้ไขผู้ใช้", + "ENABLE" => "เปิดการใช้งานผู้ใช้", + "INFO_PAGE" => "หน้าข้อมูลของผู้ใช้ {{name}}", + "PAGE_DESCRIPTION" => "รายชื่อผู้ใช้ในเว็บของคุณ ประกอบไปด้วยเครื่องมือสำหรับการจัดการ รวมทั้งความสามารถในการแก้ไขรายละเอียดผู้ใช้ การเปิดใช้งานผู้ใช้ การเปิด/ปิดบัญชีผู้ใช้และอื่น ๆ", + "LATEST" => "ผู้ใช้ล่าสุด", + "VIEW_ALL" => "ดูผู้ใช้ทั้งหมด" + ], + "X_USER" => [ + 0 => "ไม่มีผู้ใช้", + 1 => "{{plural}} ผู้ใช้", + 2 => "{{plural}} ผู้ใช้" + ] +]; diff --git a/app/sprinkles/admin/src/Admin.php b/app/sprinkles/admin/src/Admin.php index 8a6dcc1d7..7f7a5a97c 100644 --- a/app/sprinkles/admin/src/Admin.php +++ b/app/sprinkles/admin/src/Admin.php @@ -16,5 +16,4 @@ */ class Admin extends Sprinkle { - } diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index 23f113d43..f5a14f940 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -101,7 +101,7 @@ public function create(Request $request, Response $response, $args) // All checks passed! log events/activities and create group // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $ms, $config, $currentUser) { + Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) { // Create the group $group = $classMapper->createInstance('group', $data); @@ -186,7 +186,7 @@ public function delete(Request $request, Response $response, $args) $groupName = $group->name; // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($group, $groupName, $currentUser) { + Capsule::transaction(function () use ($group, $groupName, $currentUser) { $group->delete(); unset($group); @@ -731,7 +731,7 @@ public function updateInfo(Request $request, Response $response, $args) } // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($data, $group, $currentUser) { + Capsule::transaction(function () use ($data, $group, $currentUser) { // Update the group and generate success messages foreach ($data as $name => $value) { if ($value != $group->$name) { @@ -777,7 +777,7 @@ protected function getGroupFromParams($params) // TODO: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException $e = new BadRequestException(); foreach ($validator->errors() as $idx => $field) { - foreach($field as $eidx => $error) { + foreach ($field as $eidx => $error) { $e->addUserMessage($error); } } diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index 02d17a2e9..316c26933 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -101,7 +101,7 @@ public function create(Request $request, Response $response, $args) // All checks passed! log events/activities and create role // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $ms, $config, $currentUser) { + Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) { // Create the role $role = $classMapper->createInstance('role', $data); @@ -185,7 +185,7 @@ public function delete(Request $request, Response $response, $args) $roleName = $role->name; // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($role, $roleName, $currentUser) { + Capsule::transaction(function () use ($role, $roleName, $currentUser) { $role->delete(); unset($role); @@ -837,10 +837,10 @@ public function updateInfo(Request $request, Response $response, $args) } // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($data, $role, $currentUser) { + Capsule::transaction(function () use ($data, $role, $currentUser) { // Update the role and generate success messages foreach ($data as $name => $value) { - if ($value != $role->$name){ + if ($value != $role->$name) { $role->$name = $value; } } @@ -932,7 +932,7 @@ public function updateField(Request $request, Response $response, $args) // TODO: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException $e = new BadRequestException(); foreach ($validator->errors() as $idx => $field) { - foreach($field as $eidx => $error) { + foreach ($field as $eidx => $error) { $e->addUserMessage($error); } } @@ -946,7 +946,7 @@ public function updateField(Request $request, Response $response, $args) $ms = $this->ci->alerts; // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($fieldName, $fieldValue, $role, $currentUser) { + Capsule::transaction(function () use ($fieldName, $fieldValue, $role, $currentUser) { if ($fieldName == 'permissions') { $newPermissions = collect($fieldValue)->pluck('permission_id')->all(); $role->permissions()->sync($newPermissions); @@ -998,7 +998,7 @@ protected function getRoleFromParams($params) // TODO: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException $e = new BadRequestException(); foreach ($validator->errors() as $idx => $field) { - foreach($field as $eidx => $error) { + foreach ($field as $eidx => $error) { $e->addUserMessage($error); } } diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index be0b8f946..9eebf5956 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -124,7 +124,7 @@ public function create(Request $request, Response $response, $args) // All checks passed! log events/activities, create user, and send verification email (if required) // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($classMapper, $data, $ms, $config, $currentUser) { + Capsule::transaction(function () use ($classMapper, $data, $ms, $config, $currentUser) { // Create the user $user = $classMapper->createInstance('user', $data); @@ -214,7 +214,7 @@ public function createPasswordReset(Request $request, Response $response, $args) $ms = $this->ci->alerts; // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($user, $config) { + Capsule::transaction(function () use ($user, $config) { // Create a password reset and shoot off an email $passwordReset = $this->ci->repoPasswordReset->create($user, $config['password_reset.timeouts.reset']); @@ -292,7 +292,7 @@ public function delete(Request $request, Response $response, $args) $userName = $user->user_name; // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($user, $userName, $currentUser) { + Capsule::transaction(function () use ($user, $userName, $currentUser) { $user->delete(); unset($user); @@ -1155,7 +1155,7 @@ public function updateInfo(Request $request, Response $response, $args) } // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($data, $user, $currentUser) { + Capsule::transaction(function () use ($data, $user, $currentUser) { // Update the user and generate success messages foreach ($data as $name => $value) { if ($value != $user->$name) { @@ -1258,7 +1258,7 @@ public function updateField(Request $request, Response $response, $args) // TODO: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException $e = new BadRequestException(); foreach ($validator->errors() as $idx => $field) { - foreach($field as $eidx => $error) { + foreach ($field as $eidx => $error) { $e->addUserMessage($error); } } @@ -1294,7 +1294,7 @@ public function updateField(Request $request, Response $response, $args) } // Begin transaction - DB will be rolled back if an exception occurs - Capsule::transaction( function() use ($fieldName, $fieldValue, $user, $currentUser) { + Capsule::transaction(function () use ($fieldName, $fieldValue, $user, $currentUser) { if ($fieldName == 'roles') { $newRoles = collect($fieldValue)->pluck('role_id')->all(); $user->roles()->sync($newRoles); @@ -1356,7 +1356,7 @@ protected function getUserFromParams($params) // TODO: encapsulate the communication of error messages from ServerSideValidator to the BadRequestException $e = new BadRequestException(); foreach ($validator->errors() as $idx => $field) { - foreach($field as $eidx => $error) { + foreach ($field as $eidx => $error) { $e->addUserMessage($error); } } diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 56064df04..e6f92d561 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -32,7 +32,7 @@ ], 'cache' => [ 'driver' => 'file', // Set to one of `file`, `memcached`, `redis` - 'prefix' => 'userfrosting', // Edit prefix to something unique when multiple instance of memcached/redis are used on the same server + 'prefix' => 'userfrosting', // Edit prefix to something unique when multiple instance of memcached/redis are used on the same server 'memcached' => [ 'host' => '127.0.0.1', 'port' => 11211, diff --git a/app/sprinkles/core/config/dev.php b/app/sprinkles/core/config/dev.php index daab24c2b..81f7549a0 100644 --- a/app/sprinkles/core/config/dev.php +++ b/app/sprinkles/core/config/dev.php @@ -27,4 +27,4 @@ 'info' => true ] ] - ]; \ No newline at end of file + ]; diff --git a/app/sprinkles/core/locale/ar/messages.php b/app/sprinkles/core/locale/ar/messages.php index e1ee68551..45964a08b 100644 --- a/app/sprinkles/core/locale/ar/messages.php +++ b/app/sprinkles/core/locale/ar/messages.php @@ -16,8 +16,8 @@ "ABOUT" => "عن", - "CAPTCHA" => [ - "@TRANSLATION" => "كلمة التحقق", + "CAPTCHA" => [ + "@TRANSLATION" => "كلمة التحقق", "FAIL" => "لم تقم بإدخال رمز كلمة التحقق بشكل صحيح", "SPECIFY" => "أدخل كلمة التحقق", "VERIFY" => "التحقق من كلمة التحقق" @@ -38,7 +38,7 @@ ], "HOME" => "الصفحة الرئيسية", - + "LEGAL" => [ "@TRANSLATION" => "السياسة القانونية", "DESCRIPTION" => "تسري سياستنا القانونية على استخدامك لهذا الموقع وخدماتنا" diff --git a/app/sprinkles/core/locale/ar/validate.php b/app/sprinkles/core/locale/ar/validate.php index 669a21424..bbccab780 100644 --- a/app/sprinkles/core/locale/ar/validate.php +++ b/app/sprinkles/core/locale/ar/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "ARRAY" => "القيمات ل {{label}} يجب أن تكون في مجموعة", "BOOLEAN" => "القيم ل {{label}} يجب أن يكون إما '٠' أو '١'", "INTEGER" => "القيم ل {{label}} يجب أن يكون رقم", diff --git a/app/sprinkles/core/locale/en_US/messages.php b/app/sprinkles/core/locale/en_US/messages.php index 40668c878..b0827e262 100644 --- a/app/sprinkles/core/locale/en_US/messages.php +++ b/app/sprinkles/core/locale/en_US/messages.php @@ -16,8 +16,8 @@ "ABOUT" => "About", - "CAPTCHA" => [ - "@TRANSLATION" => "Captcha", + "CAPTCHA" => [ + "@TRANSLATION" => "Captcha", "FAIL" => "You did not enter the captcha code correctly.", "SPECIFY" => "Enter the captcha", "VERIFY" => "Verify the captcha" diff --git a/app/sprinkles/core/locale/en_US/validate.php b/app/sprinkles/core/locale/en_US/validate.php index c4225a25d..8e03c8453 100644 --- a/app/sprinkles/core/locale/en_US/validate.php +++ b/app/sprinkles/core/locale/en_US/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "ARRAY" => "The values for {{label}} must be in an array.", "BOOLEAN" => "The value for {{label}} must be either '0' or '1'.", "INTEGER" => "The value for {{label}} must be an integer.", diff --git a/app/sprinkles/core/locale/es_ES/messages.php b/app/sprinkles/core/locale/es_ES/messages.php index d365579b0..cd8a3e1aa 100755 --- a/app/sprinkles/core/locale/es_ES/messages.php +++ b/app/sprinkles/core/locale/es_ES/messages.php @@ -17,8 +17,8 @@ "ABOUT" => "Acerca de", "WELCOME_TO" => "¡Bienvenido a {{title}}!", - "CAPTCHA" => [ - "@TRANSLATION" => "Captcha", + "CAPTCHA" => [ + "@TRANSLATION" => "Captcha", "FAIL" => "No has introducido correctamente el código de captcha.", "SPECIFY" => "Introduzce el captcha", "VERIFY" => "Verificar el captcha" diff --git a/app/sprinkles/core/locale/fa/messages.php b/app/sprinkles/core/locale/fa/messages.php index 00611c561..2832b6ddf 100644 --- a/app/sprinkles/core/locale/fa/messages.php +++ b/app/sprinkles/core/locale/fa/messages.php @@ -17,8 +17,8 @@ "ABOUT" => "درباره", - "CAPTCHA" => [ - "@TRANSLATION" => "کد امنیتی", + "CAPTCHA" => [ + "@TRANSLATION" => "کد امنیتی", "FAIL" => "کد امنیتی درست نیست", "SPECIFY" => "کد امنیتی را وارد کنید", "VERIFY" => "کد امنیتی را بررسی کنید" diff --git a/app/sprinkles/core/locale/fa/validate.php b/app/sprinkles/core/locale/fa/validate.php index db364b178..54d7afe4b 100644 --- a/app/sprinkles/core/locale/fa/validate.php +++ b/app/sprinkles/core/locale/fa/validate.php @@ -13,7 +13,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "ARRAY" => "مقادیر {{label}} باید از یک آرایه باشند.", "BOOLEAN" => "مقدار {{label}} باید 1 یا 0 باشد.", "INTEGER" => "مقدار {{label}} باید یک عدد اینتجر باشد.", diff --git a/app/sprinkles/core/locale/fr_FR/messages.php b/app/sprinkles/core/locale/fr_FR/messages.php index c053569f0..90718421b 100644 --- a/app/sprinkles/core/locale/fr_FR/messages.php +++ b/app/sprinkles/core/locale/fr_FR/messages.php @@ -16,8 +16,8 @@ "ABOUT" => "À propos", - "CAPTCHA" => [ - "@TRANSLATE" => "Captcha", + "CAPTCHA" => [ + "@TRANSLATE" => "Captcha", "VERIFY" => "Vérification du captcha", "SPECIFY" => "Entrer la valeur du captcha", "FAIL" => "La valeur du captcha n'a pas été entrée correctement." @@ -102,4 +102,4 @@ // Misc. "BUILT_WITH_UF" => "Créé avec UserFrosting", "ADMINLTE_THEME_BY" => "Thème par Almsaeed Studio. Tous droits réservés" -]; \ No newline at end of file +]; diff --git a/app/sprinkles/core/locale/fr_FR/validate.php b/app/sprinkles/core/locale/fr_FR/validate.php index ea85677f8..0c8dd2886 100644 --- a/app/sprinkles/core/locale/fr_FR/validate.php +++ b/app/sprinkles/core/locale/fr_FR/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "ARRAY" => "Les valeurs de {{label}} doivent être dans un tableau.", "BOOLEAN" => "La valeur de {{label}} doit être '0' ou '1'.", "INTEGER" => "La valeur de {{label}} doit être un nombre entier.", @@ -30,4 +30,4 @@ "BAD_SORT" => "{{name}} ne peut pas être utilisé pour trier Sprunje." ] ] -]; \ No newline at end of file +]; diff --git a/app/sprinkles/core/locale/it_IT/messages.php b/app/sprinkles/core/locale/it_IT/messages.php index e2dad2862..5d8d7a888 100644 --- a/app/sprinkles/core/locale/it_IT/messages.php +++ b/app/sprinkles/core/locale/it_IT/messages.php @@ -18,8 +18,8 @@ "ABOUT" => "Su di noi", - "CAPTCHA" => [ - "@TRANSLATION" => "Captcha", + "CAPTCHA" => [ + "@TRANSLATION" => "Captcha", "FAIL" => "Captcha errato", "SPECIFY" => "Inserisci il captcha", "VERIFY" => "Verifica captcha" @@ -107,7 +107,7 @@ "SEARCH" => "Cerca", "SORT" => "Ordina", "SUBMIT" => "Invia", - "SUCCESS" => "Successo", + "SUCCESS" => "Successo", "PRINT" => "Stampa", "REMOVE" => "Rimuovi", "UNACTIVATED" => "Disattivato", diff --git a/app/sprinkles/core/locale/it_IT/validate.php b/app/sprinkles/core/locale/it_IT/validate.php index 16aa75abd..a4a02929e 100644 --- a/app/sprinkles/core/locale/it_IT/validate.php +++ b/app/sprinkles/core/locale/it_IT/validate.php @@ -14,7 +14,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "ARRAY" => "I valori per {{label}} devono essere in un array.", "BOOLEAN" => "Il valore per {{label}} deve essere '0' o '1'.", "INTEGER" => "Il valore per {{label}} deve essere un numero intero.", diff --git a/app/sprinkles/core/locale/pt_PT/messages.php b/app/sprinkles/core/locale/pt_PT/messages.php index a97704cdf..155bf9aa2 100644 --- a/app/sprinkles/core/locale/pt_PT/messages.php +++ b/app/sprinkles/core/locale/pt_PT/messages.php @@ -16,8 +16,8 @@ "ABOUT" => "Acerca", - "CAPTCHA" => [ - "@TRANSLATION" => "Captcha", + "CAPTCHA" => [ + "@TRANSLATION" => "Captcha", "FAIL" => "Código captcha não introduzido corretamente.", "SPECIFY" => "Introduza o código captcha", "VERIFY" => "Verifique o código captcha" diff --git a/app/sprinkles/core/locale/pt_PT/validate.php b/app/sprinkles/core/locale/pt_PT/validate.php index 55fce7611..bc9647c35 100644 --- a/app/sprinkles/core/locale/pt_PT/validate.php +++ b/app/sprinkles/core/locale/pt_PT/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "ARRAY" => "Os valores para {{label}} devem estar contidos num array.", "BOOLEAN" => "O valor para {{label}} deve ser '0' ou '1'.", "INTEGER" => "O valor para {{label}} deve ser um inteiro.", diff --git a/app/sprinkles/core/locale/ru_RU/messages.php b/app/sprinkles/core/locale/ru_RU/messages.php index 8de3730ea..c3c9a60ff 100644 --- a/app/sprinkles/core/locale/ru_RU/messages.php +++ b/app/sprinkles/core/locale/ru_RU/messages.php @@ -16,8 +16,8 @@ "ABOUT" => "О нас", - "CAPTCHA" => [ - "@TRANSLATION" => "Капча", + "CAPTCHA" => [ + "@TRANSLATION" => "Капча", "FAIL" => "Код безопасности был введен с ошибками.", "SPECIFY" => "Введите код капчи", "VERIFY" => "Проверьте капчу" diff --git a/app/sprinkles/core/locale/ru_RU/validate.php b/app/sprinkles/core/locale/ru_RU/validate.php index 6d684de78..e705fa443 100644 --- a/app/sprinkles/core/locale/ru_RU/validate.php +++ b/app/sprinkles/core/locale/ru_RU/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "ARRAY" => "Значения для {{label}} должны быть элементами массива.", "BOOLEAN" => "Значение {{label}} должно быть '0' или '1'.", "INTEGER" => "Значение {{label}} должно быть целым.", diff --git a/app/sprinkles/core/locale/th_TH/errors.php b/app/sprinkles/core/locale/th_TH/errors.php index 8f9413e8b..7b3d41de2 100644 --- a/app/sprinkles/core/locale/th_TH/errors.php +++ b/app/sprinkles/core/locale/th_TH/errors.php @@ -1,51 +1,51 @@ - [ - "@TRANSLATION" => "ข้อผิดพลาด", - - "400" => [ - "TITLE" => "ข้อผิดพลาด 400: การร้องขอไม่ถูกต้อง", - "DESCRIPTION" => "นี่ไม่น่าจะเป็นความผิดพลาดของคุณ", - ], - - "404" => [ - "TITLE" => "ข้อผิดพลาด 404: ไม่พบหน้านี้", - "DESCRIPTION" => "ดูเหมือนเราจะไม่สามารถหาสิ่งที่คุณต้องการได้", - "DETAIL" => "เราพยายามได้ที่จะหาหน้าของคุณ...", - "EXPLAIN" => "เราไม่สามารถหาหน้าที่คุณมองหาอยู่ได้", - "RETURN" => 'อย่างไรก็ตาม คลิก ที่นี่ เพื่อกลับไปยังหน้าแรก' - ], - - "CONFIG" => [ - "TITLE" => "เกิดปัญหาจากการตั้งค่า UserFrosting!", - "DESCRIPTION" => "การตั้งค่าบางอย่างของ UserFrosting ยังไม่ตรงตามความต้องการ", - "DETAIL" => "มีบางอย่างไม่ถูกต้องอยู่", - "RETURN" => 'กรุณาแก้ไขข้อผิดพลาดดังกล่าว จากนั้น โหลดหน้านี้อีกครั้ง' - ], - - "DESCRIPTION" => "เรารู้สึกความโกลาหลในกองทัพได้เป็นอย่างดี", - "DETAIL" => "นี่คือสิ่งที่เราพบ:", - - "ENCOUNTERED" => "อืมม...บางอย่างเกิดขึ้น แต่เราไม่รู้ว่าคืออะไร", - - "MAIL" => "เกิดข้อผิดพลาดร้ายแรงระหว่างการพยายามส่งอีเมล กรุณาติดต่อผู้ดูแลระบบของเซิฟเวอร์นี้ หากคุณเป็นผู้ดูแล กรุณาตรวจสอบบันทึกอีเมลของ UF", - - "RETURN" => 'คลิก ที่นี่ เพื่อกลับไปยังหน้าแรก', - - "SERVER" => "โอ้ว ดูเหมือนระบบของเราอาจจะผิดพลาดเอง หากคุณเป็นผู้ดูแล กรุณาตรวจสอบบันทึกข้อผิดพลาดของ PHP หรือ UF", - - "TITLE" => "เกิดความโกลาหลในกองทัพ" - ] -]; + [ + "@TRANSLATION" => "ข้อผิดพลาด", + + "400" => [ + "TITLE" => "ข้อผิดพลาด 400: การร้องขอไม่ถูกต้อง", + "DESCRIPTION" => "นี่ไม่น่าจะเป็นความผิดพลาดของคุณ", + ], + + "404" => [ + "TITLE" => "ข้อผิดพลาด 404: ไม่พบหน้านี้", + "DESCRIPTION" => "ดูเหมือนเราจะไม่สามารถหาสิ่งที่คุณต้องการได้", + "DETAIL" => "เราพยายามได้ที่จะหาหน้าของคุณ...", + "EXPLAIN" => "เราไม่สามารถหาหน้าที่คุณมองหาอยู่ได้", + "RETURN" => 'อย่างไรก็ตาม คลิก ที่นี่ เพื่อกลับไปยังหน้าแรก' + ], + + "CONFIG" => [ + "TITLE" => "เกิดปัญหาจากการตั้งค่า UserFrosting!", + "DESCRIPTION" => "การตั้งค่าบางอย่างของ UserFrosting ยังไม่ตรงตามความต้องการ", + "DETAIL" => "มีบางอย่างไม่ถูกต้องอยู่", + "RETURN" => 'กรุณาแก้ไขข้อผิดพลาดดังกล่าว จากนั้น โหลดหน้านี้อีกครั้ง' + ], + + "DESCRIPTION" => "เรารู้สึกความโกลาหลในกองทัพได้เป็นอย่างดี", + "DETAIL" => "นี่คือสิ่งที่เราพบ:", + + "ENCOUNTERED" => "อืมม...บางอย่างเกิดขึ้น แต่เราไม่รู้ว่าคืออะไร", + + "MAIL" => "เกิดข้อผิดพลาดร้ายแรงระหว่างการพยายามส่งอีเมล กรุณาติดต่อผู้ดูแลระบบของเซิฟเวอร์นี้ หากคุณเป็นผู้ดูแล กรุณาตรวจสอบบันทึกอีเมลของ UF", + + "RETURN" => 'คลิก ที่นี่ เพื่อกลับไปยังหน้าแรก', + + "SERVER" => "โอ้ว ดูเหมือนระบบของเราอาจจะผิดพลาดเอง หากคุณเป็นผู้ดูแล กรุณาตรวจสอบบันทึกข้อผิดพลาดของ PHP หรือ UF", + + "TITLE" => "เกิดความโกลาหลในกองทัพ" + ] +]; diff --git a/app/sprinkles/core/locale/th_TH/messages.php b/app/sprinkles/core/locale/th_TH/messages.php index 9d1404142..0073a40a2 100644 --- a/app/sprinkles/core/locale/th_TH/messages.php +++ b/app/sprinkles/core/locale/th_TH/messages.php @@ -1,102 +1,102 @@ - 1, - - "ABOUT" => "เกี่ยวกับ", - - "CAPTCHA" => [ - "@TRANSLATION" => "รหัสยืนยัน", - "FAIL" => "คุณยังกรอกรหัสยืนยันไม่ถูกต้อง", - "SPECIFY" => "กรอกรหัสยืนยัน", - "VERIFY" => "ตรวจสอบรหัสยืนยัน" - ], - - "CSRF_MISSING" => "ไม่พบโทเคน CSRF กรุณารีเฟรชแล้วส่งข้อมูลใหม่", - - "DB_INVALID" => "ไม่สามารถเชื่อมต่อกับฐานข้อมูลได้ หากคุณเป็นผู้ดูแลระบบ กรุณาตรวจสอบบันทึกข้อผิดพลาด", - "DESCRIPTION" => "รายละเอียด", - "DOWNLOAD" => [ - "@TRANSLATION" => "ดาวน์โหลด", - "CSV" => "ดาวน์โหลด CSV" - ], - - "EMAIL" => [ - "@TRANSLATION" => "อีเมล", - "YOUR" => "ที่อยู่อีเมลของคุณ" - ], - - "HOME" => "หน้าแรก", - - "LEGAL" => "นโยบายทางกฎหมาย", - - "LOCALE" => [ - "@TRANSLATION" => "ภาษา" - ], - - "NAME" => "ชื่อ", - "NAVIGATION" => "เมนูนำทาง", - - "PAGINATION" => [ - "GOTO" => "ข้ามไปยังหน้า", - "SHOW" => "แสดง", - "OUTPUT" => "{startRow} to {endRow} of {filteredRows} ({totalRows})" - ], - "PRIVACY" => "นโยบายความเป็นส่วนตัว", - - "SLUG" => "ข้อกำหนด", - "SLUG_CONDITION" => "ข้อกำหนด/เงื่อนไข", - "STATUS" => "สถานะ", - - "UNKNOWN" => "ไม่ทราบ", - - // Actions words - "ACTIONS" => "การดำเนินการ", - "ACTIVATE" => "เปิดใช้งาน", - "ACTIVE" => "เปิดใช้งานอยู่", - "ADD" => "เพิ่ม", - "CANCEL" => "ยกเลิก", - "CONFIRM" => "ยืนยัน", - "CREATE" => "สร้าง", - "DELETE" => "ลบ", - "DELETE_CONFIRM" => "คุณต้องการที่จะลบใช่หรือไม่?", - "DELETE_CONFIRM_YES" => "ใช่ ลบเลย", - "DELETE_CONFIRM_NAMED" => "คุณต้องการที่จะลบ {{name}} ใช่หรือไม่?", - "DELETE_CONFIRM_YES_NAMED" => "ใช่ ลบ {{name}} เลย", - "DELETE_CANNOT_UNDONE" => "การดำเนินการนี้ไม่สามารถยกเลิกได้", - "DELETE_NAMED" => "ลบ {{name}}", - "DENY" => "ปฏิเสธ", - "DISABLE" => "ปิดการใช้งาน", - "DISABLED" => "ปิดการใช้งานอยู่", - "EDIT" => "แก้ไข", - "ENABLE" => "เปิด", - "ENABLED" => "เปิดอยู่", - "OVERRIDE" => "เขียนทับ", - "RESET" => "รีเซ็ต", - "SAVE" => "บันทึก", - "SEARCH" => "ค้นหา", - "SORT" => "ประเภท", - "SUBMIT" => "ส่ง", - "PRINT" => "พิมพ์", - "REMOVE" => "เอาออก", - "UNACTIVATED" => "ไม่มีการเปิดใช้", - "UPDATE" => "ปรับปรุง", - "YES" => "ใช่", - "NO" => "ไม่", - "OPTIONAL" => "ตัวเลือกเพิ่มเติม", - - // Misc. - "BUILT_WITH_UF" => "สร้างด้วย UserFrosting", - "ADMINLTE_THEME_BY" => "ธีมโดย Almsaeed Studio สงวนลิขสิทธิ์" -]; + 1, + + "ABOUT" => "เกี่ยวกับ", + + "CAPTCHA" => [ + "@TRANSLATION" => "รหัสยืนยัน", + "FAIL" => "คุณยังกรอกรหัสยืนยันไม่ถูกต้อง", + "SPECIFY" => "กรอกรหัสยืนยัน", + "VERIFY" => "ตรวจสอบรหัสยืนยัน" + ], + + "CSRF_MISSING" => "ไม่พบโทเคน CSRF กรุณารีเฟรชแล้วส่งข้อมูลใหม่", + + "DB_INVALID" => "ไม่สามารถเชื่อมต่อกับฐานข้อมูลได้ หากคุณเป็นผู้ดูแลระบบ กรุณาตรวจสอบบันทึกข้อผิดพลาด", + "DESCRIPTION" => "รายละเอียด", + "DOWNLOAD" => [ + "@TRANSLATION" => "ดาวน์โหลด", + "CSV" => "ดาวน์โหลด CSV" + ], + + "EMAIL" => [ + "@TRANSLATION" => "อีเมล", + "YOUR" => "ที่อยู่อีเมลของคุณ" + ], + + "HOME" => "หน้าแรก", + + "LEGAL" => "นโยบายทางกฎหมาย", + + "LOCALE" => [ + "@TRANSLATION" => "ภาษา" + ], + + "NAME" => "ชื่อ", + "NAVIGATION" => "เมนูนำทาง", + + "PAGINATION" => [ + "GOTO" => "ข้ามไปยังหน้า", + "SHOW" => "แสดง", + "OUTPUT" => "{startRow} to {endRow} of {filteredRows} ({totalRows})" + ], + "PRIVACY" => "นโยบายความเป็นส่วนตัว", + + "SLUG" => "ข้อกำหนด", + "SLUG_CONDITION" => "ข้อกำหนด/เงื่อนไข", + "STATUS" => "สถานะ", + + "UNKNOWN" => "ไม่ทราบ", + + // Actions words + "ACTIONS" => "การดำเนินการ", + "ACTIVATE" => "เปิดใช้งาน", + "ACTIVE" => "เปิดใช้งานอยู่", + "ADD" => "เพิ่ม", + "CANCEL" => "ยกเลิก", + "CONFIRM" => "ยืนยัน", + "CREATE" => "สร้าง", + "DELETE" => "ลบ", + "DELETE_CONFIRM" => "คุณต้องการที่จะลบใช่หรือไม่?", + "DELETE_CONFIRM_YES" => "ใช่ ลบเลย", + "DELETE_CONFIRM_NAMED" => "คุณต้องการที่จะลบ {{name}} ใช่หรือไม่?", + "DELETE_CONFIRM_YES_NAMED" => "ใช่ ลบ {{name}} เลย", + "DELETE_CANNOT_UNDONE" => "การดำเนินการนี้ไม่สามารถยกเลิกได้", + "DELETE_NAMED" => "ลบ {{name}}", + "DENY" => "ปฏิเสธ", + "DISABLE" => "ปิดการใช้งาน", + "DISABLED" => "ปิดการใช้งานอยู่", + "EDIT" => "แก้ไข", + "ENABLE" => "เปิด", + "ENABLED" => "เปิดอยู่", + "OVERRIDE" => "เขียนทับ", + "RESET" => "รีเซ็ต", + "SAVE" => "บันทึก", + "SEARCH" => "ค้นหา", + "SORT" => "ประเภท", + "SUBMIT" => "ส่ง", + "PRINT" => "พิมพ์", + "REMOVE" => "เอาออก", + "UNACTIVATED" => "ไม่มีการเปิดใช้", + "UPDATE" => "ปรับปรุง", + "YES" => "ใช่", + "NO" => "ไม่", + "OPTIONAL" => "ตัวเลือกเพิ่มเติม", + + // Misc. + "BUILT_WITH_UF" => "สร้างด้วย UserFrosting", + "ADMINLTE_THEME_BY" => "ธีมโดย Almsaeed Studio สงวนลิขสิทธิ์" +]; diff --git a/app/sprinkles/core/locale/th_TH/validate.php b/app/sprinkles/core/locale/th_TH/validate.php index b28c02111..6d141aab3 100644 --- a/app/sprinkles/core/locale/th_TH/validate.php +++ b/app/sprinkles/core/locale/th_TH/validate.php @@ -1,25 +1,25 @@ - [ - "ARRAY" => "ค่าของ {{label}} จะต้องเป็น Array", - "BOOLEAN" => "ค่าของ {{label}} จะต้องเป็น '0' หรือ '1'", - "INTEGER" => "ค่าของ {{label}} จะต้องเป็นตัวเลข", - "INVALID_EMAIL" => "ที่อยู่อีเมลไม่ถูกต้อง", - "LENGTH_RANGE" => "ความยาวของ {{label}} จะต้องอยู่ระหว่าง {{min}} ถึง {{max}} ตัวอักษร", - "NO_LEAD_WS" => "ค่าของ {{label}} ไม่สามารถเริ่มต้นด้วยช่องว่าง หรือ แท็บ", - "NO_TRAIL_WS" => "ค่าของ {{label}} ไม่สามารถลงท้ายด้วยช่องว่าง หรือ แท็บ", - "REQUIRED" => "กรุณากำหนดค่าของ {{label}}" - ] -]; + [ + "ARRAY" => "ค่าของ {{label}} จะต้องเป็น Array", + "BOOLEAN" => "ค่าของ {{label}} จะต้องเป็น '0' หรือ '1'", + "INTEGER" => "ค่าของ {{label}} จะต้องเป็นตัวเลข", + "INVALID_EMAIL" => "ที่อยู่อีเมลไม่ถูกต้อง", + "LENGTH_RANGE" => "ความยาวของ {{label}} จะต้องอยู่ระหว่าง {{min}} ถึง {{max}} ตัวอักษร", + "NO_LEAD_WS" => "ค่าของ {{label}} ไม่สามารถเริ่มต้นด้วยช่องว่าง หรือ แท็บ", + "NO_TRAIL_WS" => "ค่าของ {{label}} ไม่สามารถลงท้ายด้วยช่องว่าง หรือ แท็บ", + "REQUIRED" => "กรุณากำหนดค่าของ {{label}}" + ] +]; diff --git a/app/sprinkles/core/locale/valitron/th.php b/app/sprinkles/core/locale/valitron/th.php index 2e4fa254d..95e6ba5db 100644 --- a/app/sprinkles/core/locale/valitron/th.php +++ b/app/sprinkles/core/locale/valitron/th.php @@ -1,34 +1,34 @@ - "ต้องการ", - 'equals' => "จะต้องเหมือนกับ '%s'", - 'different' => "จะต้องไม่ใช่ '%s'", - 'accepted' => "จะต้องยอมรับ", - 'numeric' => "จะต้องเป็นตัวเลข", - 'integer' => "จะต้องเป็นตัวเลขหลักเดียว (0-9)", - 'length' => "จะต้องมีความยาวมากกว่า %d", - 'min' => "จะต้องมีอย่างน้อย %s", - 'max' => "จะต้องมีไม่มากไปกว่า %s", - 'in' => "ประกอบด้วยค่าที่ไม่ถูกต้อง", - 'notIn' => "ประกอบด้วยค่าที่ไม่ถูกต้อง", - 'ip' => "ไม่ใช่ที่อยู่ไอพีที่ถูกต้อง", - 'email' => "ไม่ใช่ที่อยู่อีเมลที่ถูกต้อง", - 'url' => "ไม่ใช่ลิงก์", - 'urlActive' => "จะต้องเป็นโดเมนที่มีการใช้งานอยู่", - 'alpha' => "จะต้องประกอบไปด้วยตัวอักษร a-z เท่านั้น", - 'alphaNum' => "จะต้องประกอบไปด้วยตัวอักษร a-z และ/หรือ เลข 0-9", - 'slug' => "จะต้องประกอบไปด้วยตัวอักษร a-z เลข 0-9 ขีดกลาง และขีดล่าง", - 'regex' => "ประกอบด้วยอักขระที่ไม่ถูกต้อง", - 'date' => "ไม่ใช่วันที่ที่ถูกต้อง", - 'dateFormat' => "จะต้องเป็นวันที่ที่มีรูปแบบ '%s'", - 'dateBefore' => "จะต้องเป็นวันที่ก่อน '%s'", - 'dateAfter' => "จะต้องเป็นวันที่หลังจาก '%s'", - 'contains' => "จะต้องประกอบไปด้วย %s", - 'boolean' => "จะต้องเป็นใช่ หรือ ไม่ใช่", - 'lengthBetween' => "จะต้องอยู่ระหว่าง %d ถึง %d ตัวอักษร", - 'creditCard' => "จะต้องเป็นหมายเลขบัตรเครดิตที่ถูกต้อง", - "lengthMin" => "จะต้องมีความยาวมากกว่า %d ตัวอักษร", - "lengthMax" => "จะต้องมีความยาวน้อยกว่า %d ตัวอักษร", - "instanceOf" => "จะต้องเป็นกรณีของ '%s'" -); + "ต้องการ", + 'equals' => "จะต้องเหมือนกับ '%s'", + 'different' => "จะต้องไม่ใช่ '%s'", + 'accepted' => "จะต้องยอมรับ", + 'numeric' => "จะต้องเป็นตัวเลข", + 'integer' => "จะต้องเป็นตัวเลขหลักเดียว (0-9)", + 'length' => "จะต้องมีความยาวมากกว่า %d", + 'min' => "จะต้องมีอย่างน้อย %s", + 'max' => "จะต้องมีไม่มากไปกว่า %s", + 'in' => "ประกอบด้วยค่าที่ไม่ถูกต้อง", + 'notIn' => "ประกอบด้วยค่าที่ไม่ถูกต้อง", + 'ip' => "ไม่ใช่ที่อยู่ไอพีที่ถูกต้อง", + 'email' => "ไม่ใช่ที่อยู่อีเมลที่ถูกต้อง", + 'url' => "ไม่ใช่ลิงก์", + 'urlActive' => "จะต้องเป็นโดเมนที่มีการใช้งานอยู่", + 'alpha' => "จะต้องประกอบไปด้วยตัวอักษร a-z เท่านั้น", + 'alphaNum' => "จะต้องประกอบไปด้วยตัวอักษร a-z และ/หรือ เลข 0-9", + 'slug' => "จะต้องประกอบไปด้วยตัวอักษร a-z เลข 0-9 ขีดกลาง และขีดล่าง", + 'regex' => "ประกอบด้วยอักขระที่ไม่ถูกต้อง", + 'date' => "ไม่ใช่วันที่ที่ถูกต้อง", + 'dateFormat' => "จะต้องเป็นวันที่ที่มีรูปแบบ '%s'", + 'dateBefore' => "จะต้องเป็นวันที่ก่อน '%s'", + 'dateAfter' => "จะต้องเป็นวันที่หลังจาก '%s'", + 'contains' => "จะต้องประกอบไปด้วย %s", + 'boolean' => "จะต้องเป็นใช่ หรือ ไม่ใช่", + 'lengthBetween' => "จะต้องอยู่ระหว่าง %d ถึง %d ตัวอักษร", + 'creditCard' => "จะต้องเป็นหมายเลขบัตรเครดิตที่ถูกต้อง", + "lengthMin" => "จะต้องมีความยาวมากกว่า %d ตัวอักษร", + "lengthMax" => "จะต้องมีความยาวน้อยกว่า %d ตัวอักษร", + "instanceOf" => "จะต้องเป็นกรณีของ '%s'" +); diff --git a/app/sprinkles/core/locale/zh_CN/messages.php b/app/sprinkles/core/locale/zh_CN/messages.php index 55e769a12..ecbde8423 100644 --- a/app/sprinkles/core/locale/zh_CN/messages.php +++ b/app/sprinkles/core/locale/zh_CN/messages.php @@ -16,8 +16,8 @@ "ABOUT" => "关于", - "CAPTCHA" => [ - "@TRANSLATION" => "验证码", + "CAPTCHA" => [ + "@TRANSLATION" => "验证码", "FAIL" => "Y验证码输入错误.", "SPECIFY" => "输入验证码", "VERIFY" => "验证" diff --git a/app/sprinkles/core/locale/zh_CN/validate.php b/app/sprinkles/core/locale/zh_CN/validate.php index ed68198d8..f4b3ed8da 100644 --- a/app/sprinkles/core/locale/zh_CN/validate.php +++ b/app/sprinkles/core/locale/zh_CN/validate.php @@ -12,7 +12,7 @@ */ return [ - "VALIDATE" => [ + "VALIDATE" => [ "ARRAY" => " {{label}} 的值必须在一个数组中.", "BOOLEAN" => " {{label}} 的值必须是 '0' 或 '1'.", "INTEGER" => " {{label}} 必须是整数.", diff --git a/app/sprinkles/core/routes/routes.php b/app/sprinkles/core/routes/routes.php index 3598b7ea7..af360064f 100755 --- a/app/sprinkles/core/routes/routes.php +++ b/app/sprinkles/core/routes/routes.php @@ -13,7 +13,7 @@ ->add('checkEnvironment') ->setName('index'); -$app->get('/about','UserFrosting\Sprinkle\Core\Controller\CoreController:pageAbout')->add('checkEnvironment'); +$app->get('/about', 'UserFrosting\Sprinkle\Core\Controller\CoreController:pageAbout')->add('checkEnvironment'); $app->get('/alerts', 'UserFrosting\Sprinkle\Core\Controller\CoreController:jsonAlerts'); diff --git a/app/sprinkles/core/src/Alert/AlertStream.php b/app/sprinkles/core/src/Alert/AlertStream.php index d65dc1fb6..dda2c73f2 100644 --- a/app/sprinkles/core/src/Alert/AlertStream.php +++ b/app/sprinkles/core/src/Alert/AlertStream.php @@ -83,7 +83,7 @@ public function addMessage($type, $message) */ public function addMessageTranslated($type, $messageId, $placeholders = array()) { - if (!$this->messageTranslator){ + if (!$this->messageTranslator) { throw new \RuntimeException("No translator has been set! Please call MessageStream::setTranslator first."); } @@ -113,7 +113,7 @@ public function getAndClearMessages() public function addValidationErrors(ServerSideValidator $validator) { foreach ($validator->errors() as $idx => $field) { - foreach($field as $eidx => $error) { + foreach ($field as $eidx => $error) { $this->addMessage("danger", $error); } } diff --git a/app/sprinkles/core/src/Bakery/BakeCommand.php b/app/sprinkles/core/src/Bakery/BakeCommand.php index 19358beec..3144bc07e 100644 --- a/app/sprinkles/core/src/Bakery/BakeCommand.php +++ b/app/sprinkles/core/src/Bakery/BakeCommand.php @@ -75,4 +75,4 @@ protected function execute(InputInterface $input, OutputInterface $output) $command = $this->getApplication()->find('clear-cache'); $command->run($input, $output); } -} \ No newline at end of file +} diff --git a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php index eb68b5815..d88e0a1bb 100644 --- a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php +++ b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php @@ -85,4 +85,4 @@ protected function clearRouterCache() { return $this->ci->router->clearCache(); } -} \ No newline at end of file +} diff --git a/app/sprinkles/core/src/Bakery/SetupCommand.php b/app/sprinkles/core/src/Bakery/SetupCommand.php index dbb3700ae..80158c5ff 100644 --- a/app/sprinkles/core/src/Bakery/SetupCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupCommand.php @@ -43,4 +43,4 @@ protected function execute(InputInterface $input, OutputInterface $output) $command = $this->getApplication()->find('setup:env'); $command->run($input, $output); } -} \ No newline at end of file +} diff --git a/app/sprinkles/core/src/Bakery/SetupDbCommand.php b/app/sprinkles/core/src/Bakery/SetupDbCommand.php index 08c946cca..c70035990 100644 --- a/app/sprinkles/core/src/Bakery/SetupDbCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupDbCommand.php @@ -85,7 +85,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $config["db.default.database"] != $keys['DB_NAME'] || $config["db.default.username"] != $keys['DB_USER'] || $config["db.default.password"] != $keys['DB_PASSWORD']) { - $this->io->warning("Current database configuration differ from the configuration defined in `{$this->envPath}`. Global system environment variables might be defined."); if (!$this->io->confirm('Continue?', false)) { @@ -161,7 +160,6 @@ protected function askForDatabase(InputInterface $args) // Ask further questions based on driver if ($driver['driver'] == 'sqlite') { - $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); return [ @@ -172,7 +170,6 @@ protected function askForDatabase(InputInterface $args) 'username' => '', 'password' => '' ]; - } else { $defaultPort = $driver['defaultPort']; diff --git a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php index ffb201596..ee808f398 100644 --- a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php @@ -92,7 +92,6 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($config['mail.host'] != $keys['SMTP_HOST'] || $config['mail.username'] != $keys['SMTP_USER'] || $config['mail.password'] != $keys['SMTP_PASSWORD']) { - $this->io->warning("Current SMTP configuration differ from the configuration defined in `{$this->envPath}`. Global system environment variables might be defined."); if (!$this->io->confirm('Continue?', false)) { diff --git a/app/sprinkles/core/src/Database/Migration.php b/app/sprinkles/core/src/Database/Migration.php index ce6071e4e..8afed782b 100644 --- a/app/sprinkles/core/src/Database/Migration.php +++ b/app/sprinkles/core/src/Database/Migration.php @@ -42,10 +42,14 @@ public function __construct(Builder $schema = null) /** * Method to apply changes to the database */ - public function up() {} + public function up() + { + } /** * Method to revert changes applied by the `up` method */ - public function down() {} + public function down() + { + } } diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php index 49647ef1d..967eac0ef 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php @@ -190,11 +190,12 @@ protected function markAsUnfulfillable($migration) * @param string $migration The migration class * @return array The dependency list */ - protected function getMigrationDependencies($migration) { + protected function getMigrationDependencies($migration) + { // Make sure class exists if (!class_exists($migration)) { - throw new BadClassNameException("Unable to find the migration class '$migration'." ); + throw new BadClassNameException("Unable to find the migration class '$migration'."); } // If the `dependencies` property exist and is static, use this one. @@ -202,7 +203,7 @@ protected function getMigrationDependencies($migration) { $reflectionClass = new ReflectionClass($migration); if ($reflectionClass->hasProperty('dependencies') && $reflectionClass->getProperty('dependencies')->isStatic()) { return $migration::$dependencies; - } else if (property_exists($migration, 'dependencies')) { + } elseif (property_exists($migration, 'dependencies')) { Debug::debug("`$migration` uses a non static `dependencies` property. Please change the `dependencies` property to a static property."); $instance = new $migration(); return $instance->dependencies; diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index dc32acd20..28bd58b7e 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -391,7 +391,6 @@ protected function runMigration($migration, $method) } else { $callback(); } - } /** @@ -438,7 +437,7 @@ protected function getQueries($migration, $method) public function resolve($migrationClass) { if (!class_exists($migrationClass)) { - throw new BadClassNameException("Unable to find the migration class '$migrationClass'." ); + throw new BadClassNameException("Unable to find the migration class '$migrationClass'."); } return new $migrationClass($this->getSchemaBuilder()); diff --git a/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php b/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php index 1c022bd1f..70e11f8aa 100644 --- a/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php +++ b/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php @@ -48,7 +48,10 @@ public function hasMany($related, $foreignKey = null, $localKey = null) $localKey = $localKey ?: $this->getKeyName(); return new HasManySyncable( - $instance->newQuery(), $this, $instance->getTable().'.'.$foreignKey, $localKey + $instance->newQuery(), + $this, + $instance->getTable().'.'.$foreignKey, + $localKey ); } @@ -103,8 +106,7 @@ public function belongsToManyThrough( $secondRelatedKey = null, $throughRelation = null, $relation = null - ) - { + ) { // If no relationship name was passed, we will pull backtraces to get the // name of the calling function. We will use that function name as the // title of this relation since that is a great convention to apply. @@ -142,7 +144,13 @@ public function belongsToManyThrough( // Now we set up the relationship with the related model. $query = new BelongsToManyThrough( - $related->newQuery(), $this, $intermediateRelationship, $secondJoiningTable, $secondForeignKey, $secondRelatedKey, $relation + $related->newQuery(), + $this, + $intermediateRelationship, + $secondJoiningTable, + $secondForeignKey, + $secondRelatedKey, + $relation ); return $query; @@ -185,7 +193,12 @@ public function belongsToManyUnique($related, $table = null, $foreignKey = null, } return new BelongsToManyUnique( - $instance->newQuery(), $this, $table, $foreignKey, $relatedKey, $relation + $instance->newQuery(), + $this, + $table, + $foreignKey, + $relatedKey, + $relation ); } @@ -221,8 +234,14 @@ public function morphToManyUnique($related, $name, $table = null, $foreignKey = $table = $table ?: Str::plural($name); return new MorphToManyUnique( - $query, $this, $name, $table, $foreignKey, - $otherKey, $caller, $inverse + $query, + $this, + $name, + $table, + $foreignKey, + $otherKey, + $caller, + $inverse ); } @@ -266,7 +285,13 @@ public function belongsToManyConstrained($related, $constraintKey, $table = null } return new BelongsToManyConstrained( - $instance->newQuery(), $this, $constraintKey, $table, $foreignKey, $relatedKey, $relation + $instance->newQuery(), + $this, + $constraintKey, + $table, + $foreignKey, + $relatedKey, + $relation ); } diff --git a/app/sprinkles/core/src/Database/Models/Throttle.php b/app/sprinkles/core/src/Database/Models/Throttle.php index d13a7c102..779dbf6aa 100644 --- a/app/sprinkles/core/src/Database/Models/Throttle.php +++ b/app/sprinkles/core/src/Database/Models/Throttle.php @@ -17,10 +17,10 @@ * @property string request_data */ class Throttle extends Model -{ +{ /** * @var string The name of the table for the current model. - */ + */ protected $table = "throttles"; protected $fillable = [ @@ -31,6 +31,6 @@ class Throttle extends Model /** * @var bool Enable timestamps for Throttles. - */ - public $timestamps = true; + */ + public $timestamps = true; } diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php index 2a6329699..ba87a8b41 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php @@ -97,7 +97,8 @@ public function match(array $models, Collection $results, $relation) // Only match children if their pivot key value matches that of the parent model $items = $this->findMatchingPivots($dictionary[$key], $pivotValue); $model->setRelation( - $relation, $this->related->newCollection($items) + $relation, + $this->related->newCollection($items) ); } } diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php index f27e5dea0..636202bf3 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php @@ -92,7 +92,7 @@ public function withVia($viaRelationName = null, $viaCallback = null) ? function () { // } - : $viaCallback; + : $viaCallback; return $this; } @@ -120,7 +120,9 @@ protected function addWhereConstraints() $parentKeyName = $this->getParentKeyName(); $this->query->where( - $parentKeyName, '=', $this->parent->getKey() + $parentKeyName, + '=', + $this->parent->getKey() ); return $this; @@ -161,7 +163,8 @@ public function match(array $models, Collection $results, $relation) } $model->setRelation( - $relation, $items + $relation, + $items ); } } diff --git a/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php b/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php index 4b75278af..ae730bf2f 100644 --- a/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php +++ b/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php @@ -164,7 +164,7 @@ public function withTertiary($tertiaryRelated, $tertiaryRelationName = null, $te ? function () { // } - : $tertiaryCallback; + : $tertiaryCallback; return $this; } @@ -195,7 +195,9 @@ public function count() public function getRelationExistenceCountQuery(Builder $query, Builder $parentQuery) { return $this->getRelationExistenceQuery( - $query, $parentQuery, new Expression("count(distinct {$this->relatedKey})") + $query, + $parentQuery, + new Expression("count(distinct {$this->relatedKey})") ); } @@ -229,7 +231,8 @@ public function match(array $models, Collection $results, $relation) } $model->setRelation( - $relation, $items + $relation, + $items ); } } @@ -546,7 +549,8 @@ protected function matchTertiaryModels(array $dictionary, Collection $results) $tertiaryModels = $dictionary[$key]; $model->setRelation( - $this->tertiaryRelationName, $this->tertiaryRelated->newCollection($tertiaryModels) + $this->tertiaryRelationName, + $this->tertiaryRelated->newCollection($tertiaryModels) ); } } diff --git a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php index e316af424..a373ce1e5 100644 --- a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php @@ -603,7 +603,7 @@ protected function getEditor($filePath, $line) } if (is_string($this->editor) && isset($this->editors[$this->editor]) && !is_callable($this->editors[$this->editor])) { - return [ + return [ 'ajax' => false, 'url' => $this->editors[$this->editor], ]; @@ -700,7 +700,7 @@ private function masked(array $superGlobal, $superGlobalName) $blacklisted = $this->blacklist[$superGlobalName]; $values = $superGlobal; - foreach($blacklisted as $key) { + foreach ($blacklisted as $key) { if (isset($superGlobal[$key])) { $values[$key] = str_repeat('*', strlen($superGlobal[$key])); } diff --git a/app/sprinkles/core/src/Mail/Mailer.php b/app/sprinkles/core/src/Mail/Mailer.php index 5b346b46d..b007a8bf0 100755 --- a/app/sprinkles/core/src/Mail/Mailer.php +++ b/app/sprinkles/core/src/Mail/Mailer.php @@ -71,7 +71,7 @@ public function __construct($logger, $config = []) } // Pass logger into phpMailer object - $this->phpMailer->Debugoutput = function($message, $level) { + $this->phpMailer->Debugoutput = function ($message, $level) { $this->logger->debug($message); }; } @@ -107,13 +107,13 @@ public function send(MailMessage $message, $clearRecipients = true) // Add any CCs and BCCs if ($recipient->getCCs()) { - foreach($recipient->getCCs() as $cc) { + foreach ($recipient->getCCs() as $cc) { $this->phpMailer->addCC($cc['email'], $cc['name']); } } if ($recipient->getBCCs()) { - foreach($recipient->getBCCs() as $bcc) { + foreach ($recipient->getBCCs() as $bcc) { $this->phpMailer->addBCC($bcc['email'], $bcc['name']); } } @@ -136,7 +136,7 @@ public function send(MailMessage $message, $clearRecipients = true) } /** - * Send a MailMessage message, sending a separate email to each recipient. + * Send a MailMessage message, sending a separate email to each recipient. * * If the message object supports message templates, this will render the template with the corresponding placeholder values for each recipient. * @param MailMessage $message @@ -155,13 +155,13 @@ public function sendDistinct(MailMessage $message, $clearRecipients = true) // Add any CCs and BCCs if ($recipient->getCCs()) { - foreach($recipient->getCCs() as $cc) { + foreach ($recipient->getCCs() as $cc) { $this->phpMailer->addCC($cc['email'], $cc['name']); } } if ($recipient->getBCCs()) { - foreach($recipient->getBCCs() as $bcc) { + foreach ($recipient->getBCCs() as $bcc) { $this->phpMailer->addBCC($bcc['email'], $bcc['name']); } } diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 22ce66408..288d7687b 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -163,7 +163,6 @@ public function register(ContainerInterface $container) * @return \Illuminate\Cache\Repository */ $container['cache'] = function ($c) { - $config = $c->config; if ($config['cache.driver'] == 'file') { diff --git a/app/sprinkles/core/src/Sprunje/Sprunje.php b/app/sprinkles/core/src/Sprunje/Sprunje.php index 113221f65..950c7fad2 100644 --- a/app/sprinkles/core/src/Sprunje/Sprunje.php +++ b/app/sprinkles/core/src/Sprunje/Sprunje.php @@ -139,10 +139,10 @@ public function __construct(ClassMapper $classMapper, array $options) $v->rule('regex', 'format', '/json|csv/i'); // TODO: translated rules - if(!$v->validate()) { + if (!$v->validate()) { $e = new BadRequestException(); foreach ($v->errors() as $idx => $field) { - foreach($field as $eidx => $error) { + foreach ($field as $eidx => $error) { $e->addUserMessage($error); } } diff --git a/app/sprinkles/core/src/Throttle/ThrottlerException.php b/app/sprinkles/core/src/Throttle/ThrottlerException.php index 2fd90356f..9e1009640 100644 --- a/app/sprinkles/core/src/Throttle/ThrottlerException.php +++ b/app/sprinkles/core/src/Throttle/ThrottlerException.php @@ -14,5 +14,4 @@ */ class ThrottlerException extends \RuntimeException { - } diff --git a/app/sprinkles/core/src/Util/Captcha.php b/app/sprinkles/core/src/Util/Captcha.php index 5b4177b02..53544ffec 100644 --- a/app/sprinkles/core/src/Util/Captcha.php +++ b/app/sprinkles/core/src/Util/Captcha.php @@ -64,7 +64,7 @@ public function __construct(Session $session, $key) */ public function generateRandomCode() { - $md5_hash = md5(rand(0,99999)); + $md5_hash = md5(rand(0, 99999)); $this->code = substr($md5_hash, 25, 5); $enc = md5($this->code); @@ -122,39 +122,39 @@ protected function generateImage() //color pallette $white = imagecolorallocate($image, 255, 255, 255); $black = imagecolorallocate($image, 0, 0, 0); - $red = imagecolorallocate($image,255,0,0); + $red = imagecolorallocate($image, 255, 0, 0); $yellow = imagecolorallocate($image, 255, 255, 0); - $dark_grey = imagecolorallocate($image, 64,64,64); - $blue = imagecolorallocate($image, 0,0,255); + $dark_grey = imagecolorallocate($image, 64, 64, 64); + $blue = imagecolorallocate($image, 0, 0, 255); //create white rectangle - imagefilledrectangle($image,0,0,150,30,$white); + imagefilledrectangle($image, 0, 0, 150, 30, $white); //add some lines - for($i=0;$i<2;$i++) { - imageline($image,0,rand()%10,10,rand()%30,$dark_grey); - imageline($image,0,rand()%30,150,rand()%30,$red); - imageline($image,0,rand()%30,150,rand()%30,$yellow); + for ($i=0;$i<2;$i++) { + imageline($image, 0, rand()%10, 10, rand()%30, $dark_grey); + imageline($image, 0, rand()%30, 150, rand()%30, $red); + imageline($image, 0, rand()%30, 150, rand()%30, $yellow); } // RandTab color pallette $randc[0] = imagecolorallocate($image, 0, 0, 0); - $randc[1] = imagecolorallocate($image,255,0,0); + $randc[1] = imagecolorallocate($image, 255, 0, 0); $randc[2] = imagecolorallocate($image, 255, 255, 0); - $randc[3] = imagecolorallocate($image, 64,64,64); - $randc[4] = imagecolorallocate($image, 0,0,255); + $randc[3] = imagecolorallocate($image, 64, 64, 64); + $randc[4] = imagecolorallocate($image, 0, 0, 255); //add some dots - for($i=0;$i<1000;$i++) { - imagesetpixel($image,rand()%200,rand()%50,$randc[rand()%5]); + for ($i=0;$i<1000;$i++) { + imagesetpixel($image, rand()%200, rand()%50, $randc[rand()%5]); } //calculate center of text - $x = ( 150 - 0 - imagefontwidth( 5 ) * strlen( $this->code ) ) / 2 + 0 + 5; + $x = (150 - 0 - imagefontwidth(5) * strlen($this->code)) / 2 + 0 + 5; //write string twice - imagestring($image,5, $x, 7, $this->code, $black); - imagestring($image,5, $x, 7, $this->code, $black); + imagestring($image, 5, $x, 7, $this->code, $black); + imagestring($image, 5, $x, 7, $this->code, $black); //start ob ob_start(); imagepng($image); diff --git a/app/sprinkles/core/src/Util/CheckEnvironment.php b/app/sprinkles/core/src/Util/CheckEnvironment.php index 0dfd2d884..a8b066e35 100644 --- a/app/sprinkles/core/src/Util/CheckEnvironment.php +++ b/app/sprinkles/core/src/Util/CheckEnvironment.php @@ -13,7 +13,6 @@ use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use Slim\Views\Twig; - /** * Performs pre-flight tests on your server environment to check that it meets the requirements. * @@ -104,17 +103,29 @@ public function checkAll() { $problemsFound = false; - if ($this->checkApache()) $problemsFound = true; + if ($this->checkApache()) { + $problemsFound = true; + } - if ($this->checkPhp()) $problemsFound = true; + if ($this->checkPhp()) { + $problemsFound = true; + } - if ($this->checkPdo()) $problemsFound = true; + if ($this->checkPdo()) { + $problemsFound = true; + } - if ($this->checkGd()) $problemsFound = true; + if ($this->checkGd()) { + $problemsFound = true; + } - if ($this->checkImageFunctions()) $problemsFound = true; + if ($this->checkImageFunctions()) { + $problemsFound = true; + } - if ($this->checkPermissions()) $problemsFound = true; + if ($this->checkPermissions()) { + $problemsFound = true; + } return $problemsFound; } @@ -128,7 +139,6 @@ public function checkApache() // Perform some Apache checks. We may also need to do this before any routing takes place. if (strpos(php_sapi_name(), 'apache') !== false) { - $require_apache_modules = ['mod_rewrite']; $apache_modules = apache_get_modules(); @@ -248,7 +258,7 @@ public function checkPdo() /** * Check that log, cache, and session directories are writable, and that other directories are set appropriately for the environment. */ - function checkPermissions() + public function checkPermissions() { $problemsFound = false; diff --git a/app/sprinkles/core/src/Util/ClassMapper.php b/app/sprinkles/core/src/Util/ClassMapper.php index 57cab6884..bf29d8d93 100644 --- a/app/sprinkles/core/src/Util/ClassMapper.php +++ b/app/sprinkles/core/src/Util/ClassMapper.php @@ -68,7 +68,7 @@ public function setClassMapping($identifier, $className) { // Check that class exists if (!class_exists($className)) { - throw new BadClassNameException("Unable to find the class '$className'." ); + throw new BadClassNameException("Unable to find the class '$className'."); } $this->classMappings[$identifier] = $className; diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index 561a9c431..a2000eaad 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -18,7 +18,8 @@ * * @author Alex Weissman (https://alexanderweissman.com) */ - class RawAssetBundles extends GulpBundleAssetsRawBundles { + class RawAssetBundles extends GulpBundleAssetsRawBundles + { /** * Extends the currently loaded bundles with another bundle schema. @@ -29,30 +30,30 @@ class RawAssetBundles extends GulpBundleAssetsRawBundles { * @throws \UserFrosting\Support\Exception\JsonException if file cannot be parsed as JSON. * @throws InvalidBundlesFileException if unexpected value encountered. */ - public function extend($filePath) - { - if (!is_string($filePath)) { - throw new \InvalidArgumentException("\$filePath must of type string but was " . gettype($filePath)); - } + public function extend($filePath) + { + if (!is_string($filePath)) { + throw new \InvalidArgumentException("\$filePath must of type string but was " . gettype($filePath)); + } - // Read file - $bundlesFile = $this->readSchema($filePath); + // Read file + $bundlesFile = $this->readSchema($filePath); - // Process bundles - if (isset($bundlesFile->bundle)) { - foreach ($bundlesFile->bundle as $bundleName => $bundle) { - // Get collision setting. - $collisionRule = ($bundle->options->sprinkle->onCollision ?: 'replace'); + // Process bundles + if (isset($bundlesFile->bundle)) { + foreach ($bundlesFile->bundle as $bundleName => $bundle) { + // Get collision setting. + $collisionRule = ($bundle->options->sprinkle->onCollision ?: 'replace'); - // Handle CSS bundle if specified. - if (isset($bundle->styles)) { - // Attempt to add CSS bundle - try { - $standardisedBundle = $this->standardiseBundle($bundle->styles); - if (!array_key_exists($bundleName, $this->cssBundles)) { - $this->cssBundles[$bundleName] = $standardisedBundle; - } else { - switch ($collisionRule) { + // Handle CSS bundle if specified. + if (isset($bundle->styles)) { + // Attempt to add CSS bundle + try { + $standardisedBundle = $this->standardiseBundle($bundle->styles); + if (!array_key_exists($bundleName, $this->cssBundles)) { + $this->cssBundles[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { case 'replace': // Replaces the existing bundle. $this->cssBundles[$bundleName] = $standardisedBundle; @@ -74,22 +75,21 @@ public function extend($filePath) throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); break; } - } - } - catch (\Exception $e) { - throw new InvalidBundlesFileException("Encountered issue processing styles property for '$bundleName' for file '$filePath'", 0, $e); - } - } + } + } catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing styles property for '$bundleName' for file '$filePath'", 0, $e); + } + } - // Handle JS bundle if specified. - if (isset($bundle->scripts)) { - // Attempt to add JS bundle - try { - $standardisedBundle = $this->standardiseBundle($bundle->scripts); - if (!array_key_exists($bundleName, $this->jsBundles)) { - $this->jsBundles[$bundleName] = $standardisedBundle; - } else { - switch ($collisionRule) { + // Handle JS bundle if specified. + if (isset($bundle->scripts)) { + // Attempt to add JS bundle + try { + $standardisedBundle = $this->standardiseBundle($bundle->scripts); + if (!array_key_exists($bundleName, $this->jsBundles)) { + $this->jsBundles[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { case 'replace': // Replaces the existing bundle. $this->jsBundles[$bundleName] = $standardisedBundle; @@ -111,13 +111,12 @@ public function extend($filePath) throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); break; } - } - } - catch (\Exception $e) { - throw new InvalidBundlesFileException("Encountered issue processing scripts property for '$bundleName' for file '$filePath'", 0, $e); - } - } - } - } - } -} \ No newline at end of file + } + } catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing scripts property for '$bundleName' for file '$filePath'", 0, $e); + } + } + } + } + } + } diff --git a/app/sprinkles/core/src/Util/ShutdownHandler.php b/app/sprinkles/core/src/Util/ShutdownHandler.php index 2097fbb40..bb5f50058 100755 --- a/app/sprinkles/core/src/Util/ShutdownHandler.php +++ b/app/sprinkles/core/src/Util/ShutdownHandler.php @@ -65,7 +65,7 @@ public function fatalHandler() ]; // Handle fatal errors and parse errors - if ($error !== NULL && in_array($error['type'], $fatalErrorTypes)) { + if ($error !== null && in_array($error['type'], $fatalErrorTypes)) { // Build the appropriate error message (debug or client) if ($this->displayErrorInfo) { @@ -76,7 +76,7 @@ public function fatalHandler() // For CLI, just print the message and exit. if (php_sapi_name() === 'cli') { - exit($errorMessage . PHP_EOL); + exit($errorMessage . PHP_EOL); } // For all other environments, print a debug response for the requested data type diff --git a/app/sprinkles/core/src/Util/Util.php b/app/sprinkles/core/src/Util/Util.php index ae551cf91..6af17c0f1 100644 --- a/app/sprinkles/core/src/Util/Util.php +++ b/app/sprinkles/core/src/Util/Util.php @@ -24,7 +24,7 @@ class Util * @param bool $remove * @return mixed[] */ - static public function extractFields(&$inputArray, $fieldArray, $remove = true) + public static function extractFields(&$inputArray, $fieldArray, $remove = true) { $result = []; @@ -48,7 +48,7 @@ static public function extractFields(&$inputArray, $fieldArray, $remove = true) * @param string $str * @return string */ - static public function extractDigits($str) + public static function extractDigits($str) { return preg_replace('/[^0-9]/', '', $str); } @@ -59,7 +59,7 @@ static public function extractDigits($str) * @param string $phone * @return string */ - static public function formatPhoneNumber($phone) + public static function formatPhoneNumber($phone) { $num = static::extractDigits($phone); @@ -81,23 +81,23 @@ static public function formatPhoneNumber($phone) * @param array $arr * @return string */ - static public function prettyPrintArray(array $arr) + public static function prettyPrintArray(array $arr) { $json = json_encode($arr); $result = ''; $level = 0; $inQuotes = false; $inEscape = false; - $endsLineLevel = NULL; + $endsLineLevel = null; $jsonLength = strlen($json); for ($i = 0; $i < $jsonLength; $i++) { $char = $json[$i]; - $newLineLevel = NULL; + $newLineLevel = null; $post = ''; - if ($endsLineLevel !== NULL) { + if ($endsLineLevel !== null) { $newLineLevel = $endsLineLevel; - $endsLineLevel = NULL; + $endsLineLevel = null; } if ($inEscape) { $inEscape = false; @@ -107,13 +107,14 @@ static public function prettyPrintArray(array $arr) switch ($char) { case '}': case ']': $level--; - $endsLineLevel = NULL; + $endsLineLevel = null; $newLineLevel = $level; break; case '{': case '[': $level++; + // no break case ',': $endsLineLevel = $level; break; @@ -125,15 +126,15 @@ static public function prettyPrintArray(array $arr) case ' ': case '\t': case '\n': case '\r': $char = ''; $endsLineLevel = $newLineLevel; - $newLineLevel = NULL; + $newLineLevel = null; break; } } elseif ($char === '\\') { $inEscape = true; } - if ($newLineLevel !== NULL) { - $result .= '
'.str_repeat( '  ', $newLineLevel); + if ($newLineLevel !== null) { + $result .= '
'.str_repeat('  ', $newLineLevel); } $result .= $char.$post; @@ -151,7 +152,7 @@ static public function prettyPrintArray(array $arr) * @param string $separator * @return string */ - static public function randomPhrase($numAdjectives, $maxLength = 9999999, $maxTries = 10, $separator = '-') + public static function randomPhrase($numAdjectives, $maxLength = 9999999, $maxTries = 10, $separator = '-') { $adjectives = include('extra://adjectives.php'); $nouns = include('extra://nouns.php'); diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php index 56e6b752d..2f5bba1ec 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php @@ -300,7 +300,8 @@ public function testSpecificMigrationRollbackWithDependencies() } } -class MigrationLocatorStub extends MigrationLocator { +class MigrationLocatorStub extends MigrationLocator +{ public function getMigrations() { return [ @@ -310,7 +311,8 @@ public function getMigrations() } } -class FlightsTableMigrationLocatorStub extends MigrationLocator { +class FlightsTableMigrationLocatorStub extends MigrationLocator +{ public function getMigrations() { return [ @@ -322,7 +324,8 @@ public function getMigrations() /** * This stub contain migration which file doesn't exists */ -class InvalidMigrationLocatorStub extends MigrationLocator { +class InvalidMigrationLocatorStub extends MigrationLocator +{ public function getMigrations() { return [ @@ -336,7 +339,8 @@ public function getMigrations() * than the order the file are returned because of dependencies management. * The `two` migration should be run last since it depends on the other two */ -class DependableMigrationLocatorStub extends MigrationLocator { +class DependableMigrationLocatorStub extends MigrationLocator +{ public function getMigrations() { return [ @@ -351,7 +355,8 @@ public function getMigrations() * This stub contain migration which order they need to be run is different * than the order the file are returned because of dependencies management */ -class UnfulfillableMigrationLocatorStub extends MigrationLocator { +class UnfulfillableMigrationLocatorStub extends MigrationLocator +{ public function getMigrations() { return [ @@ -366,7 +371,8 @@ public function getMigrations() * This stub contain migration which order they need to be run is different * than the order the file are returned because of dependencies management */ -class DeprecatedMigrationLocatorStub extends MigrationLocator { +class DeprecatedMigrationLocatorStub extends MigrationLocator +{ public function getMigrations() { return [ diff --git a/app/sprinkles/core/tests/Integration/DatabaseTests.php b/app/sprinkles/core/tests/Integration/DatabaseTests.php index e22d9480b..271f1f142 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseTests.php +++ b/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -71,29 +71,29 @@ protected function createSchema() $table->integer('role_id')->unsigned(); }); - $this->schema($this->schemaName)->create('permissions', function($table) { + $this->schema($this->schemaName)->create('permissions', function ($table) { $table->increments('id'); $table->string('slug'); }); // A user can be assigned to a specific task at a specific location - $this->schema($this->schemaName)->create('tasks', function($table) { + $this->schema($this->schemaName)->create('tasks', function ($table) { $table->increments('id'); $table->string('name'); }); - $this->schema($this->schemaName)->create('locations', function($table) { + $this->schema($this->schemaName)->create('locations', function ($table) { $table->increments('id'); $table->string('name'); }); - $this->schema($this->schemaName)->create('assignments', function($table) { + $this->schema($this->schemaName)->create('assignments', function ($table) { $table->integer('task_id')->unsigned(); $table->integer('location_id')->unsigned(); $table->morphs('assignable'); }); - $this->schema($this->schemaName)->create('jobs', function($table) { + $this->schema($this->schemaName)->create('jobs', function ($table) { $table->integer('user_id')->unsigned(); $table->integer('location_id')->unsigned(); $table->integer('role_id')->unsigned(); @@ -624,7 +624,7 @@ public function testBelongsToManyThrough() 'permission_id' => 4 ] ] - ],$usersWithPermissions[1]['permissions']); + ], $usersWithPermissions[1]['permissions']); // Test counting related models (withCount) $users = EloquentTestUser::withCount('permissions')->get(); diff --git a/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php b/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php index 89533c887..d3cb65827 100644 --- a/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php +++ b/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php @@ -30,4 +30,4 @@ public function testRenderWhoopsPage() $this->assertTrue(!!preg_match('/RuntimeException: This is my exception in file /', $renderBody)); $this->assertTrue(!!preg_match('/This is my exception<\/span>/', $renderBody)); } -} \ No newline at end of file +} diff --git a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php index 21f6d07f8..44406bb48 100644 --- a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php @@ -110,7 +110,7 @@ public function testGetMigrations() /** * Test MigratonLocator against the real thing, no Mockery */ - function testActualInstance() + public function testActualInstance() { // Get sprinkle manager and make sure `core` is returned $this->assertContains('core', $this->ci->sprinkleManager->getSprinkleNames()); diff --git a/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php b/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php index ec40669c3..91d22fca5 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php @@ -10,10 +10,10 @@ */ class UnfulfillableTable extends Migration { - /** - * {@inheritdoc} - */ - static public $dependencies = [ + /** + * {@inheritdoc} + */ + public static $dependencies = [ '\UserFrosting\Tests\Integration\Migrations\NonExistingMigration' ]; diff --git a/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php b/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php index db5393605..33e4e54f6 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php @@ -9,7 +9,7 @@ class CreateUsersTable extends Migration { /** * {@inheritDoc} - * + * * N.B.: Not using static here to test old deprecated behavior */ public $dependencies = []; diff --git a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php index 9413f046a..d335e1420 100644 --- a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php +++ b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php @@ -25,7 +25,7 @@ public function tearDown() m::close(); } - function testPaginatedQuery() + public function testPaginatedQuery() { // Creates a real BelongsToManyThrough object $relation = $this->getRelation(); @@ -87,7 +87,13 @@ protected function getRelation() // Now we set up the relationship with the related model. return new BelongsToManyThrough( - $builder, $related, $intermediateRelationship, 'role_users', 'role_id', 'user_id', 'relation_name' + $builder, + $related, + $intermediateRelationship, + 'role_users', + 'role_id', + 'user_id', + 'relation_name' ); } } diff --git a/app/sprinkles/core/tests/Unit/RouterTest.php b/app/sprinkles/core/tests/Unit/RouterTest.php index f77ed077b..ebdca7980 100644 --- a/app/sprinkles/core/tests/Unit/RouterTest.php +++ b/app/sprinkles/core/tests/Unit/RouterTest.php @@ -22,4 +22,4 @@ public function testBasicTest() $path = $router->pathFor('index'); $this->assertEquals('/', $path); } -} \ No newline at end of file +} diff --git a/app/sprinkles/core/tests/Unit/SprunjeTest.php b/app/sprinkles/core/tests/Unit/SprunjeTest.php index c77925a80..bc4942cec 100644 --- a/app/sprinkles/core/tests/Unit/SprunjeTest.php +++ b/app/sprinkles/core/tests/Unit/SprunjeTest.php @@ -25,7 +25,7 @@ public function tearDown() m::close(); } - function testSprunjeApplyFiltersDefault() + public function testSprunjeApplyFiltersDefault() { $sprunje = new SprunjeStub([ 'filters' => [ @@ -47,7 +47,7 @@ function testSprunjeApplyFiltersDefault() $sprunje->applyFilters($builder); } - function testSprunjeApplySortsDefault() + public function testSprunjeApplySortsDefault() { $sprunje = new SprunjeStub([ 'sorts' => [ @@ -59,7 +59,6 @@ function testSprunjeApplySortsDefault() $builder->shouldReceive('orderBy')->once()->with('species', 'asc'); $sprunje->applySorts($builder); } - } class SprunjeStub extends Sprunje @@ -93,4 +92,3 @@ class SprunjeTestModelStub extends Model { protected $table = 'table'; } - diff --git a/app/system/Bakery/Bakery.php b/app/system/Bakery/Bakery.php index e460a501c..9a78e8de6 100644 --- a/app/system/Bakery/Bakery.php +++ b/app/system/Bakery/Bakery.php @@ -120,7 +120,6 @@ protected function getResourceClass(Resource $file) $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); $className = str_replace('/', '\\', $basePath) . $file->getFilename(); $classPath = "\\UserFrosting\\Sprinkle\\$sprinkleName\\Bakery\\$className"; - } else { // Getting the classpath $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/system/Bakery/Command/BuildAssets.php index a95de5b2f..8a3fb63d6 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/system/Bakery/Command/BuildAssets.php @@ -139,12 +139,16 @@ protected function buildAssets() exit(1); } - if ($exitCode !== 0) $this->io->warning("bundling may have failed, check output"); + if ($exitCode !== 0) { + $this->io->warning("bundling may have failed, check output"); + } $this->io->writeln("> npm run uf-bundle-clean"); passthru("npm run uf-bundle-clean"); - if ($exitCode !== 0) $this->io->warning("bundling cleanup has failed, which while unusual shouldn't cause any problems"); + if ($exitCode !== 0) { + $this->io->warning("bundling cleanup has failed, which while unusual shouldn't cause any problems"); + } chdir($wd); } diff --git a/app/system/Bakery/Command/Test.php b/app/system/Bakery/Command/Test.php index 2b9302f7b..c2dddf7f4 100644 --- a/app/system/Bakery/Command/Test.php +++ b/app/system/Bakery/Command/Test.php @@ -51,4 +51,4 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->writeln("> $command"); passthru($command); } -} \ No newline at end of file +} diff --git a/app/system/Bakery/DatabaseTest.php b/app/system/Bakery/DatabaseTest.php index 57bebc493..97ecfd3a2 100644 --- a/app/system/Bakery/DatabaseTest.php +++ b/app/system/Bakery/DatabaseTest.php @@ -47,4 +47,4 @@ protected function testDB() return true; } -} \ No newline at end of file +} diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 0f136e92f..c815885a3 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -44,7 +44,6 @@ public function register(ContainerInterface $container) * @return \UserFrosting\UniformResourceLocator\ResourceLocator */ $container['locator'] = function ($c) { - $locator = new ResourceLocator(\UserFrosting\ROOT_DIR); // Register shared streams diff --git a/app/tests/Unit/ExampleTest.php b/app/tests/Unit/ExampleTest.php index 4e60469f4..304fcf196 100644 --- a/app/tests/Unit/ExampleTest.php +++ b/app/tests/Unit/ExampleTest.php @@ -13,4 +13,4 @@ public function testBasicTest() { $this->assertTrue(true); } -} \ No newline at end of file +} From dbc1c5f3719d544a2c4ec07d99e1c0e2969ec58c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 20 Oct 2018 16:58:18 -0400 Subject: [PATCH 093/237] Added `filesystem` service Merging `feature-develop-storage` into develop --- .gitignore | 6 +- CHANGELOG.md | 1 + app/sprinkles/core/composer.json | 5 + app/sprinkles/core/config/default.php | 53 +++++++ app/sprinkles/core/config/testing.php | 15 +- app/sprinkles/core/defines.php | 2 + app/sprinkles/core/src/Facades/Storage.php | 28 ++++ .../core/src/Filesystem/FilesystemManager.php | 108 +++++++++++++ .../src/ServicesProvider/ServicesProvider.php | 9 ++ .../core/tests/Unit/FilesystemTest.php | 149 ++++++++++++++++++ app/storage/.gitkeep | 0 11 files changed, 373 insertions(+), 3 deletions(-) create mode 100644 app/sprinkles/core/src/Facades/Storage.php create mode 100644 app/sprinkles/core/src/Filesystem/FilesystemManager.php create mode 100644 app/sprinkles/core/tests/Unit/FilesystemTest.php create mode 100644 app/storage/.gitkeep diff --git a/.gitignore b/.gitignore index 5fe92c603..9f8a0e655 100644 --- a/.gitignore +++ b/.gitignore @@ -14,15 +14,17 @@ app/.env composer.lock composer.phar -# Ignore log, cache, and sessions directories +# Ignore log, cache, sessions and storage directories app/cache/* app/logs/* app/sessions/* +app/storage/* -# Unignore log, cache, and sessions .gitkeeps +# Unignore log, cache, sessions and storage .gitkeeps !app/cache/.gitkeep !app/logs/.gitkeep !app/sessions/.gitkeep +!app/storage/.gitkeep # Ignore bower vendor assets /app/sprinkles/*/assets/vendor/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 057dba699..a3a95b702 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added arguments to the `create-admin` and `setup` Bakery commands so it can be used in a non-interactive way (#808) - Added tests for migrator and it's components - Added tests for `migrate` Bakery command and sub-commands +- Added new `filesystem` service ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index 1d51b00e2..f070c5aad 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -32,6 +32,11 @@ "illuminate/events": "5.4.*", "illuminate/filesystem": "5.4.*", "league/csv": "^8.1", + "league/flysystem": "~1.0", + "league/flysystem-aws-s3-v3": "~1.0", + "league/flysystem-cached-adapter": "~1.0", + "league/flysystem-rackspace": "~1.0", + "league/flysystem-sftp": "~1.0", "monolog/monolog": "^1", "phpmailer/phpmailer": "5.2.10", "rockettheme/toolbox": "1.3.1", diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index e6f92d561..f76ba9f66 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -79,6 +79,59 @@ 'smtp' => false, 'twig' => false ], + + /** + * ---------------------------------------------------------------------- + * Filesystem Configuration + * ---------------------------------------------------------------------- + * + * You may configure as many filesystem "disks" as you wish, and you + * may even configure multiple disks of the same driver. You may also + * select the default filesystem disk that should be used by UserFrosting. + * + * Supported Drivers for disk: "local", "ftp", "sftp", "s3", "rackspace" + */ + 'filesystems' => [ + 'default' => getenv('FILESYSTEM_DRIVER') ?: 'local', + 'cloud' => getenv('FILESYSTEM_CLOUD') ?: 's3', + + 'disks' => [ + /** + * Default storage disk. Default path is `app/storage/`. All + * files are accessible throught the FilesystemManager, but not + * publicly accessible throught an URL. Can still be downloaded + * using the `download` method in a custom controller + */ + 'local' => [ + 'driver' => 'local', + 'root' => \UserFrosting\STORAGE_DIR + ], + /** + * Public files are directly accessible throught the webserver for + * better performances, but at the expanse of all files being public. + * Direct access from http://{url}/files/, physically located in `/public/files` + * Great storage disk for assets (images, avatar, etc). + */ + 'public' => [ + 'driver' => 'local', + 'root' => \UserFrosting\STORAGE_PUBLIC_DIR, + 'url' => 'files/' + ], + /** + * Amazon S3 Bucket Config. Config should go in .env file. For help, see : + * https://aws.amazon.com/en/blogs/security/wheres-my-secret-access-key/ + */ + 's3' => [ + 'driver' => 's3', + 'key' => getenv('AWS_ACCESS_KEY_ID') ?: '', + 'secret' => getenv('AWS_SECRET_ACCESS_KEY') ?: '', + 'region' => getenv('AWS_DEFAULT_REGION') ?: '', // See : http://docs.aws.amazon.com/general/latest/gr/rande.html + 'bucket' => getenv('AWS_BUCKET') ?: '', + 'url' => getenv('AWS_URL') ?: '', + ], + ], + ], + 'mail' => [ 'mailer' => 'smtp', // Set to one of 'smtp', 'mail', 'qmail', 'sendmail' 'host' => getenv('SMTP_HOST') ?: null, diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index d048b508b..d8d3b0280 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -36,5 +36,18 @@ */ 'settings' => [ 'displayErrorDetails' => false - ] + ], + 'filesystems' => [ + 'disks' => [ + 'testing' => [ + 'driver' => 'local', + 'root' => \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testing', + 'url' => 'files/testing/', + ], + 'testingDriver' => [ + 'driver' => 'localTest', + 'root' => \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testingDriver' + ], + ] + ] ]; diff --git a/app/sprinkles/core/defines.php b/app/sprinkles/core/defines.php index a71edcf75..51873819c 100644 --- a/app/sprinkles/core/defines.php +++ b/app/sprinkles/core/defines.php @@ -5,3 +5,5 @@ // Names of directories within Sprinkles define('UserFrosting\MIGRATIONS_DIR', SRC_DIR_NAME . DS . 'Database' . DS . 'Migrations'); define('UserFrosting\SEEDS_DIR', SRC_DIR_NAME . DS . 'Database' . DS . 'Seeds'); +define('UserFrosting\STORAGE_DIR', APP_DIR . DS . 'storage'); +define('UserFrosting\STORAGE_PUBLIC_DIR', PUBLIC_DIR_NAME . DS . 'files'); diff --git a/app/sprinkles/core/src/Facades/Storage.php b/app/sprinkles/core/src/Facades/Storage.php new file mode 100644 index 000000000..22b97fc78 --- /dev/null +++ b/app/sprinkles/core/src/Facades/Storage.php @@ -0,0 +1,28 @@ +config = $config; + } + + /** + * Call a custom driver creator. + * + * @param array $config + * @return \Illuminate\Contracts\Filesystem\Filesystem + */ + protected function callCustomCreator(array $config) + { + $driver = $this->customCreators[$config['driver']]($this->config, $config); + + if ($driver instanceof FilesystemInterface) { + return $this->adapt($driver); + } + + return $driver; + } + + /** + * Create a cache store instance. + * + * @param mixed $config + * @return \League\Flysystem\Cached\CacheInterface + * + * @throws \InvalidArgumentException + */ + // N.B.: Introduced after laravel 5.4 + /*protected function createCacheStore($config) + { + if ($config === true) { + return new MemoryStore; + } + + return new Cache( + $this->cache->store($config['store']), + $config['prefix'] ?? 'flysystem', + $config['expire'] ?? null + ); + }*/ + + /** + * Get the filesystem connection configuration. + * + * @param string $name + * @return array + */ + protected function getConfig($name) + { + return $this->config["filesystems.disks.{$name}"]; + } + + /** + * Get the default driver name. + * + * @return string + */ + public function getDefaultDriver() + { + return $this->config['filesystems.default']; + } + + /** + * Get the default cloud driver name. + * + * @return string + */ + public function getDefaultCloudDriver() + { + return $this->config['filesystems.cloud']; + } +} diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 288d7687b..ded29128c 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -45,6 +45,7 @@ use UserFrosting\Sprinkle\Core\Database\Migrator\Migrator; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocator; use UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository; +use \UserFrosting\Sprinkle\Core\Filesystem\FilesystemManager; use UserFrosting\Sprinkle\Core\Router; use UserFrosting\Sprinkle\Core\Throttle\Throttler; use UserFrosting\Sprinkle\Core\Throttle\ThrottleRule; @@ -425,6 +426,14 @@ public function register(ContainerInterface $container) return $fm; }; + /** + * Filesystem Service + * @return \UserFrosting\Sprinkle\Core\Filesystem\FilesystemManager + */ + $container['filesystem'] = function ($c) { + return new FilesystemManager($c->config); + }; + /** * Builds search paths for locales in all Sprinkles. * diff --git a/app/sprinkles/core/tests/Unit/FilesystemTest.php b/app/sprinkles/core/tests/Unit/FilesystemTest.php new file mode 100644 index 000000000..0a85d9140 --- /dev/null +++ b/app/sprinkles/core/tests/Unit/FilesystemTest.php @@ -0,0 +1,149 @@ +testDir = $this->ci->config["filesystems.disks.{$this->testDisk}.root"]; + } + + /** + * Test the service and FilesystemManager + */ + public function testService() + { + // Force this test to use the testing disk + $this->ci->config['filesystems.default'] = $this->testDisk; + + // Filesystem service will return an instance of FilesystemManger + $filesystem = $this->ci->filesystem; + $this->assertInstanceOf(FilesystemManager::class, $filesystem); + + // Main aspect of our FilesystemManager is to adapt our config structure + // to Laravel class we'll make sure here the forced config actually works + $this->assertEquals($this->testDisk, $filesystem->getDefaultDriver()); + + // The disk won't return a Manager, but an Adapter. + $disk = $filesystem->disk($this->testDisk); + $this->assertInstanceOf(FilesystemAdapter::class, $disk); + + return $disk; + } + + /** + * @depends testService + */ + public function testFacade() + { + $this->assertInstanceOf(FilesystemAdapter::class, Storage::disk($this->testDisk)); + } + + /** + * @param FilesystemAdapter $files + * @depends testService + */ + public function testAdapter(FilesystemAdapter $files) + { + // Test basic "put" + $this->assertTrue($files->put('file.txt', 'Something inside')); + $this->assertStringEqualsFile($this->testDir . '/file.txt', 'Something inside'); + + // Test "exist" & "get" + // We'll assume Laravel test covers the rest ;) + $this->assertTrue($files->exists('file.txt')); + $this->assertEquals('Something inside', $files->get('file.txt')); + + // We'll delete the test file now + $this->assertTrue($files->delete('file.txt')); + $this->assertFileNotExists($this->testDir.'/file.txt'); + } + + /** + * @param FilesystemAdapter $files + * @depends testService + * NOTE : The `download` method was introduced in Laravel 5.5. + * We'll need to enable this once we can upgrade to newer version of Laravel + */ + /*public function testDownload(FilesystemAdapter $files) + { + // We'll test the file download feature + $response = $files->download('file.txt', 'hello.txt'); + $this->assertInstanceOf(StreamedResponse::class, $response); + // $this->assertEquals('attachment; filename="hello.txt"', $response->headers->get('content-disposition')); + }*/ + + /** + * @param FilesystemAdapter $files + * @depends testService + */ + public function testUrl(FilesystemAdapter $files) + { + // Test the URL + $this->assertTrue($files->put('file.txt', 'Blah!')); + $url = $files->url('file.txt'); + $this->assertEquals('files/testing/file.txt', $url); + $this->assertTrue($files->delete('file.txt')); + $this->assertFileNotExists($this->testDir.'/file.txt'); + } + + /** + * Test to make sure we can still add custom adapter + */ + public function testNonExistingAdapter() + { + $filesystemManager = $this->ci->filesystem; + + // InvalidArgumentException + $this->expectException("InvalidArgumentException"); + $filesystemManager->disk('testingDriver'); + } + + /** + * @depends testNonExistingAdapter + */ + public function testAddingAdapter() + { + $filesystemManager = $this->ci->filesystem; + + $filesystemManager->extend('localTest', function ($configService, $config) { + return new Filesystem(new LocalAdapter($config['root'])); + }); + + $disk = $filesystemManager->disk('testingDriver'); + $this->assertInstanceOf(FilesystemAdapter::class, $disk); + + // Make sure the path was set correctly + $this->assertEquals(\UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testingDriver' . \UserFrosting\DS, $disk->path('')); + } +} diff --git a/app/storage/.gitkeep b/app/storage/.gitkeep new file mode 100644 index 000000000..e69de29bb From 050dd6e5b59790083bd0e59c0f4c5f960874d2a6 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 21 Oct 2018 15:31:08 -0400 Subject: [PATCH 094/237] Updated develop changelog --- CHANGELOG.md | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbd257494..e88aa6d26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added -- Use locale requested by browser when possible for guests (#718) -- Add locale drop down to registration page, with the currently applied locale selected (#718) +- Use locale requested by browser when possible for guests ([#718](https://github.com/userfrosting/UserFrosting/pull/718)) +- Add locale drop down to registration page, with the currently applied locale selected ([#718](https://github.com/userfrosting/UserFrosting/pull/718)) - Integrated improvements from [v4.0.25-Alpha](#v4025-alpha) - Added `database` option for `migrate` and `migrate:*` Bakery commands - New `isProduction` method for Bakery command to test if app is in production mode @@ -18,25 +18,32 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `RefreshDatabase` test Trait to use a fresh database for a test - Added `TestDatabase` test Trait to use the in memory database for a test - Implement `withRaw`, `withSum`, `withAvg`, `withMin`, `withMax` (see https://github.com/laravel/framework/pull/16815) -- Include Vagrant integration directly inside UF (#829) -- Added arguments to the `create-admin` and `setup` Bakery commands so it can be used in a non-interactive way (#808) +- Include Vagrant integration directly inside UF ([#829](https://github.com/userfrosting/UserFrosting/pull/829)) +- Added arguments to the `create-admin` and `setup` Bakery commands so it can be used in a non-interactive way ([#808](https://github.com/userfrosting/UserFrosting/pull/808)) - Added tests for migrator and it's components - Added tests for `migrate` Bakery command and sub-commands -- Added new `filesystem` service +- Added new `filesystem` service ([#869](https://github.com/userfrosting/UserFrosting/pull/869)) +- Added new `Seeder` and `seed` Bakery command ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle -- Re-written Migrator. The migrator is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider (#795) +- Re-written the migrator. It is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider ([#795](https://github.com/userfrosting/UserFrosting/pull/795)) - Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace -- Move User registration out of the `AccountController` (#793) +- Move User registration out of the `AccountController` ([#793](https://github.com/userfrosting/UserFrosting/pull/793)) - Temporarily undeprecate `AssetLoader` until the new asset system can be refactored (https://github.com/userfrosting/assets/issues/4) - Rewrite `AssetLoader` to act as a wrapper for `Assets` +- Improved `route:list` Bakery command +- Rewritten the `locator` service so it's better suited for sprinkle system + +### Fix +- Sprinkle without a `template/` folder won't cause error anymore +- Fixed routes not available in Tests [and Bakery] ([#854](https://github.com/userfrosting/UserFrosting/pull/854)) ### Deprecated - Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration` - Migrations dependencies property should now be a static property - Deprecated migration `seed` method. Database seeding should now be done using the new Seeder -- Trait `\UserFrosting\Tests\DatabaseTransactions` has been deprecated. Tests should now use the `\UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` trait instead. (#826) +- Trait `\UserFrosting\Tests\DatabaseTransactions` has been deprecated. Tests should now use the `\UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` trait instead. ([#826](https://github.com/userfrosting/UserFrosting/pull/826)) ### Removed - The console IO instance is not available anymore in migrations From 859072a9a234350619cacc91a04dde479554c29f Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 21 Oct 2018 15:59:34 -0400 Subject: [PATCH 095/237] Fix bad type in `ExceptionHandlerInterface` --- .../Handler/ExceptionHandlerInterface.php | 4 +- .../Error/Handler/ExceptionHandlerTest.php | 50 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php index 3118a653e..8cafbf940 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php @@ -22,10 +22,10 @@ interface ExceptionHandlerInterface * @param ContainerInterface $ci * @param ServerRequestInterface $request * @param ResponseInterface $response - * @param \Exception $exception + * @param \Throwable $exception * @param bool $displayErrorDetails */ - public function __construct(ContainerInterface $ci, ServerRequestInterface $request, ResponseInterface $response, \Exception $exception, $displayErrorDetails = false); + public function __construct(ContainerInterface $ci, ServerRequestInterface $request, ResponseInterface $response, \Throwable $exception, $displayErrorDetails = false); /** * @return ResponseInterface diff --git a/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php b/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php new file mode 100644 index 000000000..6bf4d201a --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php @@ -0,0 +1,50 @@ +ci, $this->getRequest(), $this->getResponse(), $this->getException(), false); + $this->assertInstanceOf(ExceptionHandler::class, $handler); + return $handler; + } + + /** + * @return ServerRequestInterface + */ + private function getRequest() + { + return $this->getMockBuilder(ServerRequestInterface::class) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * @return ResponseInterface + */ + private function getResponse() + { + return $this->getMockBuilder(ResponseInterface::class) + ->disableOriginalConstructor() + ->getMock(); + } + + /** + * @return RuntimeException + */ + private function getException() + { + return new RuntimeException('This is my exception'); + } +} From 5a38e68848dfd09b7bb06b557f640df54925ece5 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 21 Oct 2018 16:17:43 -0400 Subject: [PATCH 096/237] \Throwable is not available in php 5.6 #doh --- .gitignore | 3 ++- app/sprinkles/core/src/Error/ExceptionHandlerManager.php | 2 +- app/sprinkles/core/src/Error/Handler/ExceptionHandler.php | 2 +- .../core/src/Error/Handler/ExceptionHandlerInterface.php | 2 +- app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php | 6 +++--- .../core/src/Error/Renderer/ErrorRendererInterface.php | 4 ++-- app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 9f8a0e655..4eb87a889 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ -# Ignores my text editor metadata +# Ignores text editor metadata *.komodoproject +.php_cs.cache # Ignores Mac metadata. You can configure this globally if you use a Mac: http://islegend.com/development/setting-global-gitignore-mac-windows/ .DS_Store diff --git a/app/sprinkles/core/src/Error/ExceptionHandlerManager.php b/app/sprinkles/core/src/Error/ExceptionHandlerManager.php index 886ee3208..abf956e24 100755 --- a/app/sprinkles/core/src/Error/ExceptionHandlerManager.php +++ b/app/sprinkles/core/src/Error/ExceptionHandlerManager.php @@ -54,7 +54,7 @@ public function __construct(ContainerInterface $ci, $displayErrorDetails = false * @param \Throwable $exception The caught Exception object * @return ResponseInterface */ - public function __invoke(ServerRequestInterface $request, ResponseInterface $response, \Throwable $exception) + public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $exception) { // Default exception handler class $handlerClass = '\UserFrosting\Sprinkle\Core\Error\Handler\ExceptionHandler'; diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php index 757880428..46dd8aa5b 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php @@ -82,7 +82,7 @@ public function __construct( ContainerInterface $ci, ServerRequestInterface $request, ResponseInterface $response, - \Throwable $exception, + $exception, $displayErrorDetails = false ) { $this->ci = $ci; diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php index 8cafbf940..0611d5e54 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php @@ -25,7 +25,7 @@ interface ExceptionHandlerInterface * @param \Throwable $exception * @param bool $displayErrorDetails */ - public function __construct(ContainerInterface $ci, ServerRequestInterface $request, ResponseInterface $response, \Throwable $exception, $displayErrorDetails = false); + public function __construct(ContainerInterface $ci, ServerRequestInterface $request, ResponseInterface $response, $exception, $displayErrorDetails = false); /** * @return ResponseInterface diff --git a/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php b/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php index 295e4573a..c46221abd 100644 --- a/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php @@ -28,7 +28,7 @@ abstract class ErrorRenderer implements ErrorRendererInterface protected $response; /** - * @var \Exception + * @var \Throwable */ protected $exception; @@ -45,10 +45,10 @@ abstract class ErrorRenderer implements ErrorRendererInterface * * @param ServerRequestInterface $request The most recent Request object * @param ResponseInterface $response The most recent Response object - * @param \Exception $exception The caught Exception object + * @param \Throwable $exception The caught Exception object * @param bool $displayErrorDetails */ - public function __construct(ServerRequestInterface $request, ResponseInterface $response, \Exception $exception, $displayErrorDetails = false) + public function __construct(ServerRequestInterface $request, ResponseInterface $response, $exception, $displayErrorDetails = false) { $this->request = $request; $this->response = $response; diff --git a/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php b/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php index 3153e4661..8e485bda1 100755 --- a/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php +++ b/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php @@ -18,10 +18,10 @@ interface ErrorRendererInterface /** * @param ServerRequestInterface $request The most recent Request object * @param ResponseInterface $response The most recent Response object - * @param \Exception $exception The caught Exception object + * @param \Throwable $exception The caught Exception object * @param bool $displayErrorDetails */ - public function __construct(ServerRequestInterface $request, ResponseInterface $response, \Exception $exception, $displayErrorDetails = false); + public function __construct(ServerRequestInterface $request, ResponseInterface $response, $exception, $displayErrorDetails = false); /** * @return string diff --git a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php index a373ce1e5..2978b5f7a 100644 --- a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php @@ -116,7 +116,7 @@ class WhoopsRenderer extends ErrorRenderer /** * {@inheritdoc} */ - public function __construct(ServerRequestInterface $request, ResponseInterface $response, \Exception $exception, $displayErrorDetails = false) + public function __construct(ServerRequestInterface $request, ResponseInterface $response, $exception, $displayErrorDetails = false) { $this->request = $request; $this->response = $response; From 088f6fee82332d780293aa506f3df266f5a3f68d Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 21 Oct 2018 16:38:48 -0400 Subject: [PATCH 097/237] Fix wrong locator in CheckEnvironment --- .../core/src/Util/CheckEnvironment.php | 8 ++++---- .../tests/Integration/CheckEnvironmentTest.php | 17 +++++++++++++++++ 2 files changed, 21 insertions(+), 4 deletions(-) create mode 100644 app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php diff --git a/app/sprinkles/core/src/Util/CheckEnvironment.php b/app/sprinkles/core/src/Util/CheckEnvironment.php index a8b066e35..d4341568a 100644 --- a/app/sprinkles/core/src/Util/CheckEnvironment.php +++ b/app/sprinkles/core/src/Util/CheckEnvironment.php @@ -10,8 +10,8 @@ use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; use Illuminate\Cache\CacheManager; -use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator; use Slim\Views\Twig; +use UserFrosting\UniformResourceLocator\ResourceLocator; /** * Performs pre-flight tests on your server environment to check that it meets the requirements. @@ -21,7 +21,7 @@ class CheckEnvironment { /** - * @var UniformResourceLocator Locator service for stream resources. + * @var ResourceLocator Locator service for stream resources. */ protected $locator; @@ -49,10 +49,10 @@ class CheckEnvironment * Constructor. * * @param Twig $view The view object, needed for rendering error page. - * @param UniformResourceLocator $locator Locator service for stream resources. + * @param ResourceLocator $locator Locator service for stream resources. * @param CacheManager $cache Cache manager */ - public function __construct(Twig $view, UniformResourceLocator $locator, $cache) + public function __construct(Twig $view, ResourceLocator $locator, $cache) { $this->view = $view; $this->locator = $locator; diff --git a/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php b/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php new file mode 100644 index 000000000..8cbd58458 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php @@ -0,0 +1,17 @@ +assertInstanceOf(CheckEnvironment::class, $this->ci->checkEnvironment); + } +} From 475f297416c4cb926eff6c23a91fde7ae8a984c6 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 21 Oct 2018 17:12:31 -0400 Subject: [PATCH 098/237] Wrong TypeHint for Builder --- .../account/src/Database/Models/Activity.php | 6 +++--- .../account/src/Database/Models/Permission.php | 4 ++-- app/sprinkles/account/src/Database/Models/Role.php | 2 +- app/sprinkles/account/src/Database/Models/User.php | 4 ++-- app/sprinkles/admin/src/Sprunje/ActivitySprunje.php | 4 ++-- .../admin/src/Sprunje/PermissionSprunje.php | 6 +++--- app/sprinkles/admin/src/Sprunje/RoleSprunje.php | 2 +- app/sprinkles/admin/src/Sprunje/UserSprunje.php | 12 ++++++------ 8 files changed, 20 insertions(+), 20 deletions(-) diff --git a/app/sprinkles/account/src/Database/Models/Activity.php b/app/sprinkles/account/src/Database/Models/Activity.php index 75d1109e6..27b8b901a 100644 --- a/app/sprinkles/account/src/Database/Models/Activity.php +++ b/app/sprinkles/account/src/Database/Models/Activity.php @@ -8,7 +8,7 @@ namespace UserFrosting\Sprinkle\Account\Database\Models; use Illuminate\Database\Capsule\Manager as Capsule; -use Illuminate\Database\Query\Builder; +use Illuminate\Database\Eloquent\Builder; use UserFrosting\Sprinkle\Core\Database\Models\Model; /** @@ -42,7 +42,7 @@ class Activity extends Model * * @param Builder $query */ - public function scopeJoinUser(Builder $query) + public function scopeJoinUser($query) { $query = $query->select('activities.*'); @@ -57,7 +57,7 @@ public function scopeJoinUser(Builder $query) * @param Builder $query * @return Builder */ - public function scopeMostRecentEvents(Builder $query) + public function scopeMostRecentEvents($query) { return $query->select('user_id', 'event_type', Capsule::raw('MAX(occurred_at) as occurred_at')) ->groupBy('user_id') diff --git a/app/sprinkles/account/src/Database/Models/Permission.php b/app/sprinkles/account/src/Database/Models/Permission.php index 37a504527..c6ced1378 100644 --- a/app/sprinkles/account/src/Database/Models/Permission.php +++ b/app/sprinkles/account/src/Database/Models/Permission.php @@ -74,7 +74,7 @@ public function roles() * @param int $roleId * @return Builder */ - public function scopeForRole(Builder $query, $roleId) + public function scopeForRole($query, $roleId) { return $query->join('permission_roles', function ($join) use ($roleId) { $join->on('permission_roles.permission_id', 'permissions.id') @@ -89,7 +89,7 @@ public function scopeForRole(Builder $query, $roleId) * @param int $roleId * @return Builder */ - public function scopeNotForRole(Builder $query, $roleId) + public function scopeNotForRole($query, $roleId) { return $query->join('permission_roles', function ($join) use ($roleId) { $join->on('permission_roles.permission_id', 'permissions.id') diff --git a/app/sprinkles/account/src/Database/Models/Role.php b/app/sprinkles/account/src/Database/Models/Role.php index e8f12199f..ec61b14fd 100644 --- a/app/sprinkles/account/src/Database/Models/Role.php +++ b/app/sprinkles/account/src/Database/Models/Role.php @@ -84,7 +84,7 @@ public function permissions() * @param int $userId * @return Builder */ - public function scopeForUser(Builder $query, $userId) + public function scopeForUser($query, $userId) { return $query->join('role_users', function ($join) use ($userId) { $join->on('role_users.role_id', 'roles.id') diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index 9b2ff0a41..9e1e872cf 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -451,7 +451,7 @@ public function roles() * @param int $roleId * @return Builder */ - public function scopeForRole(Builder $query, $roleId) + public function scopeForRole($query, $roleId) { return $query->join('role_users', function ($join) use ($roleId) { $join->on('role_users.user_id', 'users.id') @@ -465,7 +465,7 @@ public function scopeForRole(Builder $query, $roleId) * @param Builder $query * @return Builder */ - public function scopeJoinLastActivity(Builder $query) + public function scopeJoinLastActivity($query) { $query = $query->select('users.*'); diff --git a/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php b/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php index adde7bb4a..393e7ea1f 100644 --- a/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php +++ b/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php @@ -50,7 +50,7 @@ protected function baseQuery() * @param mixed $value * @return self */ - protected function filterUser(Builder $query, $value) + protected function filterUser($query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -71,7 +71,7 @@ protected function filterUser(Builder $query, $value) * @param string $direction * @return self */ - protected function sortUser(Builder $query, $direction) + protected function sortUser($query, $direction) { $query->orderBy('users.last_name', $direction); return $this; diff --git a/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php b/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php index 4e7dddbb9..d828e0941 100644 --- a/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php @@ -51,7 +51,7 @@ protected function baseQuery() * @param mixed $value * @return self */ - protected function filterInfo(Builder $query, $value) + protected function filterInfo($query, $value) { return $this->filterProperties($query, $value); } @@ -63,7 +63,7 @@ protected function filterInfo(Builder $query, $value) * @param mixed $value * @return self */ - protected function filterProperties(Builder $query, $value) + protected function filterProperties($query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -84,7 +84,7 @@ protected function filterProperties(Builder $query, $value) * @param string $direction * @return self */ - protected function sortProperties(Builder $query, $direction) + protected function sortProperties($query, $direction) { $query->orderBy('slug', $direction); return $this; diff --git a/app/sprinkles/admin/src/Sprunje/RoleSprunje.php b/app/sprinkles/admin/src/Sprunje/RoleSprunje.php index cefcf7cb5..a71da5c70 100644 --- a/app/sprinkles/admin/src/Sprunje/RoleSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/RoleSprunje.php @@ -51,7 +51,7 @@ protected function baseQuery() * @param mixed $value * @return self */ - protected function filterInfo(Builder $query, $value) + protected function filterInfo($query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); diff --git a/app/sprinkles/admin/src/Sprunje/UserSprunje.php b/app/sprinkles/admin/src/Sprunje/UserSprunje.php index d0f033031..d525c5c0d 100644 --- a/app/sprinkles/admin/src/Sprunje/UserSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/UserSprunje.php @@ -60,7 +60,7 @@ protected function baseQuery() * @param mixed $value * @return self */ - protected function filterLastActivity(Builder $query, $value) + protected function filterLastActivity($query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -79,7 +79,7 @@ protected function filterLastActivity(Builder $query, $value) * @param mixed $value * @return self */ - protected function filterName(Builder $query, $value) + protected function filterName($query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -100,7 +100,7 @@ protected function filterName(Builder $query, $value) * @param mixed $value * @return self */ - protected function filterStatus(Builder $query, $value) + protected function filterStatus($query, $value) { // Split value on separator for OR queries $values = explode($this->orSeparator, $value); @@ -150,7 +150,7 @@ protected function listStatus() * @param string $direction * @return self */ - protected function sortLastActivity(Builder $query, $direction) + protected function sortLastActivity($query, $direction) { $query->orderBy('activities.occurred_at', $direction); return $this; @@ -163,7 +163,7 @@ protected function sortLastActivity(Builder $query, $direction) * @param string $direction * @return self */ - protected function sortName(Builder $query, $direction) + protected function sortName($query, $direction) { $query->orderBy('last_name', $direction); return $this; @@ -176,7 +176,7 @@ protected function sortName(Builder $query, $direction) * @param string $direction * @return self */ - protected function sortStatus(Builder $query, $direction) + protected function sortStatus($query, $direction) { $query->orderBy('flag_enabled', $direction)->orderBy('flag_verified', $direction); return $this; From adc4016779bc3f3d49e253cb95840faaa22293fa Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 22 Oct 2018 21:20:00 -0400 Subject: [PATCH 099/237] Fix error if no `sprinkle` option is defined --- app/sprinkles/core/src/Util/RawAssetBundles.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index a2000eaad..20ddf8f3d 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -43,7 +43,7 @@ public function extend($filePath) if (isset($bundlesFile->bundle)) { foreach ($bundlesFile->bundle as $bundleName => $bundle) { // Get collision setting. - $collisionRule = ($bundle->options->sprinkle->onCollision ?: 'replace'); + $collisionRule = isset($bundle->options->sprinkle->onCollision) ? $bundle->options->sprinkle->onCollision : 'replace'; // Handle CSS bundle if specified. if (isset($bundle->styles)) { From d73a866a27b6942889e41f6c7b3f9f8111364c77 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 22 Oct 2018 21:56:07 -0400 Subject: [PATCH 100/237] Added simple CoreController test + TestController Trait --- .../Controllers/CoreControllerTest.php | 36 ++++++++++++++ app/sprinkles/core/tests/TestController.php | 49 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php create mode 100644 app/sprinkles/core/tests/TestController.php diff --git a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php new file mode 100644 index 000000000..8064150d1 --- /dev/null +++ b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php @@ -0,0 +1,36 @@ +ci); + $this->assertInstanceOf(CoreController::class, $controller); + return $controller; + } + + /** + * @depends testControllerConstructor + * @param CoreController $controller + */ + public function testPageIndex(CoreController $controller) + { + $result = $controller->pageIndex($this->getRequest(), $this->getResponse(), []); + $this->assertSame($result->getStatusCode(), 200); + $this->assertTrue(!!preg_match('/<\/html>/', (string) $result->getBody())); + } +} diff --git a/app/sprinkles/core/tests/TestController.php b/app/sprinkles/core/tests/TestController.php new file mode 100644 index 000000000..a0eb9d7ab --- /dev/null +++ b/app/sprinkles/core/tests/TestController.php @@ -0,0 +1,49 @@ + Date: Mon, 22 Oct 2018 22:08:35 -0400 Subject: [PATCH 101/237] Use the test db for controller tests + (trying to) make Travis happy --- .travis.yml | 2 ++ app/sprinkles/core/tests/TestController.php | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/.travis.yml b/.travis.yml index d011db724..01e29f4b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,8 @@ before_install: before_script: # install deps and UF - composer install + - php bakery debug + - php bakery build-assets - php bakery migrate script: diff --git a/app/sprinkles/core/tests/TestController.php b/app/sprinkles/core/tests/TestController.php index a0eb9d7ab..77fdb33f8 100644 --- a/app/sprinkles/core/tests/TestController.php +++ b/app/sprinkles/core/tests/TestController.php @@ -10,6 +10,8 @@ use Slim\Http\Environment; use Slim\Http\Request; use Slim\Http\Response; +use UserFrosting\Sprinkle\Core\Tests\TestDatabase; +use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; /** * Helper trait to handle Controller Test @@ -19,6 +21,9 @@ */ trait TestController { + use TestDatabase; + use RefreshDatabase; + /** * Force session to start to avoid PHPUnit headers already sent error * @see https://stackoverflow.com/a/23400885/445757 @@ -27,6 +32,10 @@ public function setUp() { @session_start(); parent::setUp(); + + // Setup test database + $this->setupTestDatabase(); + $this->refreshDatabase(); } /** From fe20c17dbb2f09ee17baae7f64d115c1df0dcc58 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 23 Oct 2018 20:06:30 -0400 Subject: [PATCH 102/237] Fix WhoopsRenderer integration --- app/sprinkles/core/composer.json | 2 +- .../src/Error/Renderer/WhoopsRenderer.php | 48 +++++++++++-------- .../Error/Renderer/WhoopsRendererTest.php | 32 +++++++++++++ 3 files changed, 60 insertions(+), 22 deletions(-) diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index 60b7e6ad6..c6542f5d9 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -26,7 +26,7 @@ ], "require": { "doctrine/dbal": "^2.5", - "filp/whoops": "~2.2.0", + "filp/whoops": "^2.3.1", "illuminate/cache": "5.4.*", "illuminate/database": "5.4.*", "illuminate/events": "5.4.*", diff --git a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php index 2978b5f7a..f91a34be2 100644 --- a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php @@ -18,6 +18,7 @@ use Whoops\Exception\Formatter; use Whoops\Exception\Inspector; use Whoops\Handler\PlainTextHandler; +use Whoops\Handler\Handler; use Whoops\Util\Misc; use Whoops\Util\TemplateHelper; @@ -169,7 +170,7 @@ public function render() if (!$this->handleUnconditionally()) { // Check conditions for outputting HTML: // @todo: Make this more robust - if (php_sapi_name() === 'cli') { + if (PHP_SAPI === 'cli') { // Help users who have been relying on an internal test value // fix their code to the proper method if (isset($_ENV['whoops-test'])) { @@ -186,6 +187,7 @@ public function render() $templateFile = $this->getResource("views/layout.html.php"); $cssFile = $this->getResource("css/whoops.base.css"); $zeptoFile = $this->getResource("js/zepto.min.js"); + $prettifyFile = $this->getResource("js/prettify.min.js"); $clipboard = $this->getResource("js/clipboard.min.js"); $jsFile = $this->getResource("js/whoops.base.js"); @@ -196,19 +198,12 @@ public function render() $inspector = $this->getInspector(); $frames = $inspector->getFrames(); - $code = $inspector->getException()->getCode(); - - if ($inspector->getException() instanceof \ErrorException) { - // ErrorExceptions wrap the php-error types within the "severity" property - $code = Misc::translateErrorCode($inspector->getException()->getSeverity()); - } - // Detect frames that belong to the application. - if ($this->applicationPaths) { + if ($this->getApplicationPaths()) { /* @var \Whoops\Exception\Frame $frame */ foreach ($frames as $frame) { - foreach ($this->applicationPaths as $path) { - if (substr($frame->getFile(), 0, strlen($path)) === $path) { + foreach ($this->getApplicationPaths() as $path) { + if (strpos($frame->getFile(), $path) === 0) { $frame->setApplication(true); break; } @@ -216,6 +211,13 @@ public function render() } } + $code = $inspector->getException()->getCode(); + + if ($inspector->getException() instanceof \ErrorException) { + // ErrorExceptions wrap the php-error types within the "severity" property + $code = Misc::translateErrorCode($inspector->getException()->getSeverity()); + } + // Nicely format the session object $session = isset($_SESSION) ? $this->masked($_SESSION, '_SESSION') : []; $session = ['session' => Util::prettyPrintArray($session)]; @@ -227,6 +229,7 @@ public function render() // @todo: Asset compiler "stylesheet" => file_get_contents($cssFile), "zepto" => file_get_contents($zeptoFile), + "prettify" => file_get_contents($prettifyFile), "clipboard" => file_get_contents($clipboard), "javascript" => file_get_contents($jsFile), @@ -243,16 +246,19 @@ public function render() "frame_code" => $this->getResource("views/frame_code.html.php"), "env_details" => $this->getResource("views/env_details.html.php"), - "title" => $this->getPageTitle(), - "name" => explode("\\", $inspector->getExceptionName()), - "message" => $inspector->getException()->getMessage(), - "code" => $code, - "plain_exception" => Formatter::formatExceptionPlain($inspector), - "frames" => $frames, - "has_frames" => !!count($frames), - "handler" => $this, - "handlers" => [$this], - "prettify" => true, + "title" => $this->getPageTitle(), + "name" => explode("\\", $inspector->getExceptionName()), + "message" => $inspector->getExceptionMessage(), + "previousMessages" => $inspector->getPreviousExceptionMessages(), + "docref_url" => $inspector->getExceptionDocrefUrl(), + "code" => $code, + "previousCodes" => $inspector->getPreviousExceptionCodes(), + "plain_exception" => Formatter::formatExceptionPlain($inspector), + "frames" => $frames, + "has_frames" => !!count($frames), + "handler" => $this, + "handlers" => [$this], + "prettify" => true, "active_frames_tab" => count($frames) && $frames->offsetGet(0)->isApplication() ? 'application' : 'all', "has_frames_tabs" => $this->getApplicationPaths(), diff --git a/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php b/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php index d3cb65827..09ad932ca 100644 --- a/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php +++ b/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php @@ -6,9 +6,30 @@ use Psr\Http\Message\ResponseInterface; use UserFrosting\Sprinkle\Core\Error\Renderer\WhoopsRenderer; use UserFrosting\Tests\TestCase; +use Whoops\Exception\Inspector; class WhoopsRendererTest extends TestCase { + /** + * @covers Whoops\Exception\Inspector::getPreviousExceptionMessages + */ + public function testGetPreviousExceptionMessages() + { + $exception1 = $this->getException('My first exception'); + $exception2 = $this->getException('My second exception', 0, $exception1); + $exception3 = $this->getException('And the third one', 0, $exception2); + + $inspector = new Inspector($exception3); + + $previousExceptions = $inspector->getPreviousExceptionMessages(); + + $this->assertEquals($exception2->getMessage(), $previousExceptions[0]); + $this->assertEquals($exception1->getMessage(), $previousExceptions[1]); + } + + /** + * @depends testGetPreviousExceptionMessages + */ public function testRenderWhoopsPage() { $request = $this->getMockBuilder(ServerRequestInterface::class) @@ -30,4 +51,15 @@ public function testRenderWhoopsPage() $this->assertTrue(!!preg_match('/RuntimeException: This is my exception in file /', $renderBody)); $this->assertTrue(!!preg_match('/This is my exception<\/span>/', $renderBody)); } + + /** + * @param string $message + * @param int $code + * @param \Exception $previous + * @return \Exception + */ + protected function getException($message = null, $code = 0, $previous = null) + { + return new \Exception($message, $code, $previous); + } } From b3ea5cac59ba81bb0315274e56537b2fb30cb5bb Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 23 Oct 2018 20:50:47 -0400 Subject: [PATCH 103/237] Changed deprecations to `warning`, and suppressed them in tests --- app/sprinkles/account/src/Database/Models/User.php | 6 +++--- app/sprinkles/core/config/default.php | 1 + app/sprinkles/core/config/testing.php | 6 ++++++ .../src/Database/Migrator/MigrationDependencyAnalyser.php | 5 ++++- app/sprinkles/core/src/Database/Migrator/Migrator.php | 5 ++++- app/sprinkles/core/src/Model/UFModel.php | 2 +- app/system/Bakery/Migration.php | 5 ++++- app/tests/TestCase.php | 2 +- 8 files changed, 24 insertions(+), 8 deletions(-) diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index 9e1e872cf..138b242b3 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -361,15 +361,15 @@ public function onLogin($params = []) if ($passwordType != 'modern') { if (!isset($params['password'])) { - Debug::debug('Notice: Unhashed password must be supplied to update to modern password hashing.'); + Debug::notice('Notice: Unhashed password must be supplied to update to modern password hashing.'); } else { // Hash the user's password and update $passwordHash = Password::hash($params['password']); if ($passwordHash === null) { - Debug::debug('Notice: outdated password hash could not be updated because the new hashing algorithm is not supported. Are you running PHP >= 5.3.7?'); + Debug::notice('Notice: outdated password hash could not be updated because the new hashing algorithm is not supported.'); } else { $this->password = $passwordHash; - Debug::debug('Notice: outdated password hash has been automatically updated to modern hashing.'); + Debug::notice('Notice: outdated password hash has been automatically updated to modern hashing.'); } } } diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index f76ba9f66..3cc7dde5e 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -75,6 +75,7 @@ ] ], 'debug' => [ + 'deprecation' => true, 'queries' => false, 'smtp' => false, 'twig' => false diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index d8d3b0280..7b4c69398 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -31,6 +31,12 @@ 'database' => ':memory:', ] ], + /** + * Don't log deprecations in tests + */ + 'debug' => [ + 'deprecation' => false, + ], /** * Don't display error detail in test. Return the non formatted errors */ diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php index 967eac0ef..1cab5eef7 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php @@ -9,6 +9,7 @@ use ReflectionClass; use UserFrosting\Sprinkle\Core\Util\BadClassNameException; +use UserFrosting\Sprinkle\Core\Facades\Config; use UserFrosting\Sprinkle\Core\Facades\Debug; /** @@ -204,7 +205,9 @@ protected function getMigrationDependencies($migration) if ($reflectionClass->hasProperty('dependencies') && $reflectionClass->getProperty('dependencies')->isStatic()) { return $migration::$dependencies; } elseif (property_exists($migration, 'dependencies')) { - Debug::debug("`$migration` uses a non static `dependencies` property. Please change the `dependencies` property to a static property."); + if (Config::get('debug.deprecation')) { + Debug::warning("`$migration` uses a non static `dependencies` property. Please change the `dependencies` property to a static property."); + } $instance = new $migration(); return $instance->dependencies; } else { diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index 28bd58b7e..5dfe081e3 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -13,6 +13,7 @@ use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRepositoryInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationDependencyAnalyser as Analyser; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRollbackDependencyAnalyser as RollbackAnalyser; +use UserFrosting\Sprinkle\Core\Facades\Config; use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Util\BadClassNameException; @@ -185,7 +186,9 @@ protected function runUp($migrationClass, $batch, $pretend) * @deprecated Since 4.2.0. Use a seeder instead */ if (method_exists($migration, 'seed')) { - Debug::debug("Migration `seed` method has been deprecated and will be removed in future versions. Please use a Seeder instead."); + if (Config::get('debug.deprecation')) { + Debug::warning("Migration `seed` method has been deprecated and will be removed in future versions. Please use a Seeder instead."); + } $this->runMigration($migration, 'seed'); $this->note("Seeded: {$migrationClass}"); } diff --git a/app/sprinkles/core/src/Model/UFModel.php b/app/sprinkles/core/src/Model/UFModel.php index 0d9feff2f..1e21f6339 100644 --- a/app/sprinkles/core/src/Model/UFModel.php +++ b/app/sprinkles/core/src/Model/UFModel.php @@ -20,7 +20,7 @@ abstract class UFModel extends Model { public function __construct(array $attributes = []) { - Debug::debug("UFModel has been deprecated and will be removed in future versions. Please move your model " . static::class . " to Database/Models/ and have it extend the base Database/Models/Model class."); + Debug::warning("UFModel has been deprecated and will be removed in future versions. Please move your model " . static::class . " to Database/Models/ and have it extend the base Database/Models/Model class."); parent::__construct($attributes); } diff --git a/app/system/Bakery/Migration.php b/app/system/Bakery/Migration.php index 760e5fbe9..0d50af7b9 100644 --- a/app/system/Bakery/Migration.php +++ b/app/system/Bakery/Migration.php @@ -10,6 +10,7 @@ use Illuminate\Database\Schema\Builder; use UserFrosting\Sprinkle\Core\Database\Migration as NewMigration; use Symfony\Component\Console\Style\SymfonyStyle; +use UserFrosting\Sprinkle\Core\Facades\Config; use UserFrosting\Sprinkle\Core\Facades\Debug; /** @@ -28,7 +29,9 @@ class Migration extends NewMigration */ public function __construct(Builder $schema = null, SymfonyStyle $io = null) { - Debug::debug("`UserFrosting\System\Bakery\Migration` has been deprecated and will be removed in future versions. Please have your `" . static::class . "` migration extend the base `UserFrosting\Sprinkle\Core\Database\Migration` class instead."); + if (Config::get('debug.deprecation')) { + Debug::warning("`UserFrosting\System\Bakery\Migration` has been deprecated and will be removed in future versions. Please have your `" . static::class . "` migration extend the base `UserFrosting\Sprinkle\Core\Database\Migration` class instead."); + } parent::__construct($schema); } diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php index d68832378..5d7310b34 100644 --- a/app/tests/TestCase.php +++ b/app/tests/TestCase.php @@ -75,7 +75,7 @@ protected function setUpTraits() $uses = array_flip(class_uses_recursive(static::class)); if (isset($uses[DatabaseTransactions::class])) { - Debug::debug("`UserFrosting\Tests\DatabaseTransactions` has been deprecated and will be removed in future versions. Please use `UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` class instead."); + Debug::warning("`UserFrosting\Tests\DatabaseTransactions` has been deprecated and will be removed in future versions. Please use `UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` class instead."); $this->beginDatabaseTransaction(); } } From ce8228919f74ccac56ed65194321092a91d50a31 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 23 Oct 2018 21:44:05 -0400 Subject: [PATCH 104/237] Added tests for the rest of method in `CoreController` --- .../core/src/Controller/CoreController.php | 2 +- .../Controllers/CoreControllerTest.php | 49 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/Controller/CoreController.php b/app/sprinkles/core/src/Controller/CoreController.php index 36c9ee37a..da71ea71f 100644 --- a/app/sprinkles/core/src/Controller/CoreController.php +++ b/app/sprinkles/core/src/Controller/CoreController.php @@ -99,7 +99,7 @@ public function getAsset(Request $request, Response $response, $args) /** @var \UserFrosting\Assets\AssetLoader $assetLoader */ $assetLoader = $this->ci->assetLoader; - if (!$assetLoader->loadAsset($args['url'])) { + if (!isset($args['url']) || !$assetLoader->loadAsset($args['url'])) { throw new NotFoundException; } diff --git a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php index 8064150d1..5063a6e18 100644 --- a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php +++ b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php @@ -33,4 +33,53 @@ public function testPageIndex(CoreController $controller) $this->assertSame($result->getStatusCode(), 200); $this->assertTrue(!!preg_match('/<\/html>/', (string) $result->getBody())); } + + /** + * @depends testControllerConstructor + * @param CoreController $controller + */ + public function testJsonAlerts(CoreController $controller) + { + $result = $controller->jsonAlerts($this->getRequest(), $this->getResponse(), []); + $this->assertSame($result->getStatusCode(), 200); + $this->assertJson((string) $result->getBody()); + } + + /** + * @depends testControllerConstructor + * @expectedException \UserFrosting\Support\Exception\NotFoundException + * @param CoreController $controller + */ + public function testGetAsset_ExceptionNoUrl(CoreController $controller) + { + $controller->getAsset($this->getRequest(), $this->getResponse(), []); + } + + /** + * @depends testControllerConstructor + * @expectedException \UserFrosting\Support\Exception\NotFoundException + * @param CoreController $controller + */ + public function testGetAsset_ExceptionBadUrl(CoreController $controller) + { + $url = "/" . rand(0, 99999); + $controller->getAsset($this->getRequest(), $this->getResponse(), ['url' => $url]); + } + + /** + * @depends testControllerConstructor + * @depends testGetAsset_ExceptionNoUrl + * @depends testGetAsset_ExceptionBadUrl + * @param CoreController $controller + */ + public function testGetAsset(CoreController $controller) + { + $result = $controller->getAsset($this->getRequest(), $this->getResponse(), ['url' => '']); + $this->assertSame($result->getStatusCode(), 200); + $this->assertSame('', (string) $result->getBody()); + + $result = $controller->getAsset($this->getRequest(), $this->getResponse(), ['url' => 'userfrosting/js/uf-alerts.js']); + $this->assertSame($result->getStatusCode(), 200); + $this->assertNotEmpty((string) $result->getBody()); + } } From b43d7dd33f26c8e8aac3f46672df7722c68771cb Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 24 Oct 2018 20:28:36 -0400 Subject: [PATCH 105/237] Fix for sessions in tests --- app/sprinkles/core/config/testing.php | 8 -------- .../{TestController.php => ControllerTestCase.php} | 11 ++++------- .../Integration/Controllers/CoreControllerTest.php | 9 +++------ phpunit.xml | 1 + 4 files changed, 8 insertions(+), 21 deletions(-) rename app/sprinkles/core/tests/{TestController.php => ControllerTestCase.php} (81%) diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index 7b4c69398..6b2ded25d 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -14,14 +14,6 @@ 'default' => 'array', ] ], - /** - * Disable CSRF in the testing env. - */ - 'csrf' => [ - 'blacklist' => [ - '^/' => ['GET'] - ] - ], /** * Use in memory db for testing */ diff --git a/app/sprinkles/core/tests/TestController.php b/app/sprinkles/core/tests/ControllerTestCase.php similarity index 81% rename from app/sprinkles/core/tests/TestController.php rename to app/sprinkles/core/tests/ControllerTestCase.php index 77fdb33f8..5357c6450 100644 --- a/app/sprinkles/core/tests/TestController.php +++ b/app/sprinkles/core/tests/ControllerTestCase.php @@ -12,28 +12,25 @@ use Slim\Http\Response; use UserFrosting\Sprinkle\Core\Tests\TestDatabase; use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; +use UserFrosting\Tests\TestCase; /** - * Helper trait to handle Controller Test + * Special TestCase for Controller Tests * * @see https://akrabat.com/testing-slim-framework-actions/ * @author Louis Charette */ -trait TestController +class ControllerTestCase extends TestCase { use TestDatabase; use RefreshDatabase; /** - * Force session to start to avoid PHPUnit headers already sent error - * @see https://stackoverflow.com/a/23400885/445757 + * Setup test database for controller tests */ public function setUp() { - @session_start(); parent::setUp(); - - // Setup test database $this->setupTestDatabase(); $this->refreshDatabase(); } diff --git a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php index 5063a6e18..6bb19ae46 100644 --- a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php +++ b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php @@ -3,16 +3,13 @@ namespace UserFrosting\Tests\Integration\Seeder; use UserFrosting\Sprinkle\Core\Controller\CoreController; -use UserFrosting\Sprinkle\Core\Tests\TestController; -use UserFrosting\Tests\TestCase; +use UserFrosting\Sprinkle\Core\Tests\ControllerTestCase; /** - * + * Tests CoreController */ -class CoreControllerTest extends TestCase +class CoreControllerTest extends ControllerTestCase { - use TestController; - /** * @return CoreController */ diff --git a/phpunit.xml b/phpunit.xml index 8945a7192..348cb4d2f 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -7,6 +7,7 @@ convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" + stderr="true" stopOnFailure="false"> From 9203a0a0f48fb461321971425cc7a1766a03ef0b Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 25 Oct 2018 20:38:38 -0400 Subject: [PATCH 106/237] Allow checkAccess to accept a `null` user, since `currentUser` can technically be `null`. --- .../src/Authorize/AuthorizationManager.php | 16 ++-- .../account/src/Log/UserActivityProcessor.php | 2 +- .../Integration/AuthorizationManagerTest.php | 81 +++++++++++++++++++ .../tests/Integration/AdminControllerTest.php | 33 ++++++++ app/sprinkles/core/config/default.php | 2 +- .../Controllers/CoreControllerTest.php | 2 +- 6 files changed, 128 insertions(+), 8 deletions(-) create mode 100644 app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php create mode 100644 app/sprinkles/admin/tests/Integration/AdminControllerTest.php diff --git a/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/app/sprinkles/account/src/Authorize/AuthorizationManager.php index 2b1ce5acb..b501708be 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationManager.php @@ -68,16 +68,23 @@ public function getCallbacks() * * Determine if this user has access to the given $slug under the given $params. * - * @param User $user + * @param User|null $user * @param string $slug The permission slug to check for access. * @param array $params An array of field names => values, specifying any additional data to provide the authorization module * when determining whether or not this user has access. * @return bool True if the user has access, false otherwise. */ - public function checkAccess(User $user, $slug, array $params = []) + public function checkAccess($user, $slug, array $params = []) { $debug = $this->ci->config['debug.auth']; + if (is_null($user) || !($user instanceof User)) { + if ($debug) { + $this->ci->authLogger->debug("No user defined. Access denied."); + } + return false; + } + if ($debug) { $trace = array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), 1); $this->ci->authLogger->debug("Authorization check requested at: ", $trace); @@ -86,17 +93,16 @@ public function checkAccess(User $user, $slug, array $params = []) if ($this->ci->authenticator->guest()) { if ($debug) { - $this->ci->authLogger->debug("User is not logged in. Access denied."); + $this->ci->authLogger->debug("User is not logged in. Access denied."); } return false; } // The master (root) account has access to everything. // Need to use loose comparison for now, because some DBs return `id` as a string. - if ($user->id == $this->ci->config['reserved_user_ids.master']) { if ($debug) { - $this->ci->authLogger->debug("User is the master (root) user. Access granted."); + $this->ci->authLogger->debug("User is the master (root) user. Access granted."); } return true; } diff --git a/app/sprinkles/account/src/Log/UserActivityProcessor.php b/app/sprinkles/account/src/Log/UserActivityProcessor.php index c6cdf3354..a73530349 100644 --- a/app/sprinkles/account/src/Log/UserActivityProcessor.php +++ b/app/sprinkles/account/src/Log/UserActivityProcessor.php @@ -34,7 +34,7 @@ public function __construct($userId) public function __invoke(array $record) { $additionalFields = [ - 'ip_address' => $_SERVER['REMOTE_ADDR'], + 'ip_address' => isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : null, 'user_id' => $this->userId, 'occurred_at' => $record['datetime'], 'description' => $record['message'] diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php new file mode 100644 index 000000000..925208958 --- /dev/null +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -0,0 +1,81 @@ +setupTestDatabase(); + $this->refreshDatabase(); + } + + /** + * @return AuthorizationManager + */ + public function testConstructor() + { + $manager = new AuthorizationManager($this->ci, []); + $this->assertInstanceOf(AuthorizationManager::class, $manager); + return $manager; + } + + /** + * @depends testConstructor + * @param AuthorizationManager $manager + */ + public function testAddCallback(AuthorizationManager $manager) + { + $this->assertEmpty($manager->getCallbacks()); + $this->assertInstanceOf(AuthorizationManager::class, $manager->addCallback('foo', function () {})); + $callbacks = $manager->getCallbacks(); + $this->assertNotEmpty($callbacks); + $this->assertEquals(['foo' => function () {}], $callbacks); + } + + /** + * @depends testConstructor + * @expectedException \ArgumentCountError + * @param AuthorizationManager $manager + */ + public function testCheckAccess_withOutUser(AuthorizationManager $manager) + { + $manager->checkAccess(); + } + + /** + * @depends testConstructor + * @param AuthorizationManager $manager + */ + public function testCheckAccess_withNullUser(AuthorizationManager $manager) + { + $this->assertFalse($manager->checkAccess(null, 'foo')); + } + + /** + * @depends testConstructor + * @param AuthorizationManager $manager + */ + public function testCheckAccess_withBadUserType(AuthorizationManager $manager) + { + $this->assertFalse($manager->checkAccess(123, 'foo')); + } +} diff --git a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php new file mode 100644 index 000000000..4bbda10c4 --- /dev/null +++ b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php @@ -0,0 +1,33 @@ +ci); + $this->assertInstanceOf(AdminController::class, $controller); + return $controller; + } + + /** + * @depends testControllerConstructor + * @expectedException \UserFrosting\Support\Exception\ForbiddenException + * @param AdminController $controller + */ + public function testPageDashboard_NullUser(AdminController $controller) + { + $controller->pageDashboard($this->getRequest(), $this->getResponse(), []); + } +} diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 3cc7dde5e..58704ca1c 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -157,7 +157,7 @@ 'public_relative' => dirname($_SERVER['SCRIPT_NAME']) // The location of `index.php` relative to the document root. Use for sites installed in subdirectories of your web server's document root. ], 'session' => [ - 'handler' => 'file', + 'handler' => 'file', //file or database // Config values for when using db-based sessions 'database' => [ 'table' => 'sessions' diff --git a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php index 6bb19ae46..a72b9bde5 100644 --- a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php +++ b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php @@ -1,6 +1,6 @@ Date: Sat, 27 Oct 2018 09:48:54 -0500 Subject: [PATCH 107/237] Added showAlertOnSuccess feature Added showAlertOnSuccess flag to enable displaying Alerts when the Ajax call succeeds. --- .../core/assets/userfrosting/js/uf-form.js | 121 ++++++++++-------- 1 file changed, 65 insertions(+), 56 deletions(-) diff --git a/app/sprinkles/core/assets/userfrosting/js/uf-form.js b/app/sprinkles/core/assets/userfrosting/js/uf-form.js index c5352e757..f9ca51371 100644 --- a/app/sprinkles/core/assets/userfrosting/js/uf-form.js +++ b/app/sprinkles/core/assets/userfrosting/js/uf-form.js @@ -31,56 +31,58 @@ * * @todo Implement proper fallback for when `set` function isn't supported by FormData. */ -;(function($, window, document, undefined) { - 'use strict'; +; +(function ($, window, document, undefined) { + 'use strict'; // Define plugin name and defaults. var pluginName = 'ufForm', defaults = { DEBUG: false, - site : site, // global site variables - submittingText : "", + site: site, // global site variables + submittingText: "", beforeSubmitCallback: null, - binaryCheckboxes : true, // submit checked/unchecked checkboxes as 0/1 values - keyupDelay : 0, + binaryCheckboxes: true, // submit checked/unchecked checkboxes as 0/1 values + keyupDelay: 0, + showAlertOnSuccess: false, // These are options that will be passed to jQuery Validate // See https://jqueryvalidation.org/validate/#-validate() validator: { - rules : {}, - messages : {} + rules: {}, + messages: {} }, // Deprecated validators: { - rules : {}, - messages : {} + rules: {}, + messages: {} } }; // Constructor - function Plugin (element, options) { + function Plugin(element, options) { this.element = element[0]; this.$element = $(this.element); var lateDefaults = { - submitButton : this.$element.find('button[type=submit]'), - msgTarget : this.$element.find('.js-form-alerts:first'), + submitButton: this.$element.find('button[type=submit]'), + msgTarget: this.$element.find('.js-form-alerts:first'), // These are options that will be passed to jQuery Validate // See https://jqueryvalidation.org/validate/#-validate() - validator : { + validator: { submitHandler: $.proxy(this.defaultSubmitHandler, this), - onkeyup : $.proxy(this._onKeyUp, this) + onkeyup: $.proxy(this._onKeyUp, this) }, - ajax : { + ajax: { // Override jQuery's strict JSON parsing - converters : { + converters: { 'text json': $.proxy(this._defaultResponseParser, this) }, // Response type - dataType : this._debugAjax ? 'html' : 'json', + dataType: this._debugAjax ? 'html' : 'json', // Disable the submit button before sending the request - beforeSend : $.proxy(this.disableSubmit, this), + beforeSend: $.proxy(this.disableSubmit, this), // enable the submit button once the request completes - complete : $.proxy(this.enableSubmit, this) + complete: $.proxy(this.enableSubmit, this) } }; @@ -115,7 +117,7 @@ /** * Set "loading" text for submit button, if it exists, and disable button */ - Plugin.prototype.disableSubmit = function() { + Plugin.prototype.disableSubmit = function () { var submitButton = this.settings.submitButton; // Do nothing, if the button is already disabled if (submitButton.prop('disabled')) { @@ -138,7 +140,7 @@ * * @return this */ - Plugin.prototype.enableSubmit = function() { + Plugin.prototype.enableSubmit = function () { var submitButton = this.settings.submitButton; // Do nothing, if the button is already enabled @@ -162,7 +164,7 @@ * @param {Element} form * @param {Event} event */ - Plugin.prototype.defaultSubmitHandler = function(form, event) { + Plugin.prototype.defaultSubmitHandler = function (form, event) { // Execute any "before submit" callback if (this.settings.beforeSubmitCallback) { this.settings.beforeSubmitCallback(); @@ -180,7 +182,7 @@ * @param {object} reqParams * @returns {Deferred} */ - Plugin.prototype.submitForm = function(reqParams) { + Plugin.prototype.submitForm = function (reqParams) { return $.ajax(reqParams).then( // Submission successful $.proxy(this._defaultSuccess, this), @@ -197,8 +199,19 @@ * @param {jqXHR} jqXHR * @return {jqXHR} */ - Plugin.prototype._defaultSuccess = function(data, textStatus, jqXHR) { + Plugin.prototype._defaultSuccess = function (data, textStatus, jqXHR) { this.$element.trigger('submitSuccess.ufForm', [data, textStatus, jqXHR]); + if (this.settings.showAlertOnSuccess) { + // showing UF alerts on success also. + // This will show the Alerts from the Alert stream when the page is not reloaded after the ufForm submit succeeds, + if (!this.settings.msgTarget.data('ufAlerts')) { + this.settings.msgTarget.ufAlerts(); + } else { + this.settings.msgTarget.ufAlerts('clear'); + } + + this.settings.msgTarget.ufAlerts('fetch').ufAlerts('render'); + } return jqXHR; }; @@ -210,7 +223,7 @@ * @param {string} errorThrown * @return {jqXHR} */ - Plugin.prototype._defaultError = function(jqXHR, textStatus, errorThrown) { + Plugin.prototype._defaultError = function (jqXHR, textStatus, errorThrown) { // Error messages if (this._debugAjax && jqXHR.responseText) { this.$element.trigger('submitError.ufForm', [jqXHR, textStatus, errorThrown]); @@ -242,7 +255,7 @@ * @param {string} result * @return {object} */ - Plugin.prototype._defaultResponseParser = function(result) { + Plugin.prototype._defaultResponseParser = function (result) { try { // First try to use native browser parsing if (typeof JSON === 'object' && typeof JSON.parse === 'function') { @@ -251,9 +264,9 @@ return $.parseJSON(result); } } catch (e) { - // statements to handle any exceptions - console.warn('Could not parse expected JSON response.'); - return {}; + // statements to handle any exceptions + console.warn('Could not parse expected JSON response.'); + return {}; } }; @@ -265,14 +278,13 @@ * @param {object} ajaxParams * @return {object} */ - Plugin.prototype.prepareRequestData = function(form, ajaxParams) { + Plugin.prototype.prepareRequestData = function (form, ajaxParams) { // Set ajax type and url from form method and action, if not otherwise set. var ajaxDefaults = { - type : this.$element.attr('method'), - url : this.$element.attr('action'), - contentType : (typeof this.$element.attr('enctype') === 'undefined') ? - 'application/x-www-form-urlencoded; charset=UTF-8' : - this.$element.attr('enctype') + type: this.$element.attr('method'), + url: this.$element.attr('action'), + contentType: (typeof this.$element.attr('enctype') === 'undefined') ? + 'application/x-www-form-urlencoded; charset=UTF-8' : this.$element.attr('enctype') }; ajaxParams = $.extend(true, {}, ajaxDefaults, ajaxParams); @@ -300,21 +312,20 @@ * @param {Element} form * @return {string} */ - Plugin.prototype._urlencodeData = function(form) { + Plugin.prototype._urlencodeData = function (form) { // Serialize and post to the backend script in ajax mode var serializedData; if (this.settings.binaryCheckboxes) { serializedData = $(form).find(':input').not(':checkbox').serialize(); // Get unchecked checkbox values, set them to 0 - $(form).find('input[type=checkbox]:enabled').each(function() { + $(form).find('input[type=checkbox]:enabled').each(function () { if ($(this).is(':checked')) { serializedData += '&' + encodeURIComponent(this.name) + '=1'; } else { serializedData += '&' + encodeURIComponent(this.name) + '=0'; } }); - } - else { + } else { serializedData = $(form).find(':input').serialize(); } @@ -327,7 +338,7 @@ * @param {Element} form * @return {FormData} */ - Plugin.prototype._multipartData = function(form) { + Plugin.prototype._multipartData = function (form) { // Use FormData to wrap form contents. // https://developer.mozilla.org/en/docs/Web/API/FormData var formData = new FormData(form); @@ -339,7 +350,7 @@ if (typeof formData.set !== 'function') { this.settings.msgTarget.ufAlerts('push', 'danger', "Your browser is missing a required feature. This form will still attempt to submit, but if it fails, you'll need to use Chrome for desktop or FireFox for desktop."); } else { - checkboxes.each(function() { + checkboxes.each(function () { if ($(this).is(':checked')) { // this replaces checkbox value with 1 (as we're using binaryCheckboxes). formData.set(this.name, 1); @@ -360,10 +371,10 @@ * @param {Element} form * @param {Event} event */ - Plugin.prototype._onKeyUp = function(element, event) { + Plugin.prototype._onKeyUp = function (element, event) { var validator = this.validator; // See http://stackoverflow.com/questions/41363409/jquery-validate-add-delay-to-keyup-validation - setTimeout(function() { + setTimeout(function () { // Avoid revalidate the field when pressing one of the following keys // Shift => 16 // Ctrl => 17 @@ -383,16 +394,16 @@ 38, 39, 40, 45, 144, 225 ]; - if ( event.which === 9 && validator.elementValue( element ) === '' || $.inArray( event.keyCode, excludedKeys ) !== -1 ) { + if (event.which === 9 && validator.elementValue(element) === '' || $.inArray(event.keyCode, excludedKeys) !== -1) { return; - } else if ( element.name in validator.submitted || element.name in validator.invalid ) { - validator.element( element ); + } else if (element.name in validator.submitted || element.name in validator.invalid) { + validator.element(element); } }, this.settings.keyupDelay); }; // Handles instantiation and access to non-private methods. - $.fn[pluginName] = function(methodOrOptions) { + $.fn[pluginName] = function (methodOrOptions) { // Grab plugin instance var instance = $(this).data(pluginName); // If undefined or object, initalise plugin. @@ -407,14 +418,12 @@ else if (typeof methodOrOptions === 'string' && typeof instance[methodOrOptions] === 'function') { // Ensure not a private function if (methodOrOptions.indexOf('_') !== 0) { - return instance[methodOrOptions]( Array.prototype.slice.call(arguments, 1)); - } - else { - console.warn( 'Method ' + methodOrOptions + ' is private!' ); + return instance[methodOrOptions](Array.prototype.slice.call(arguments, 1)); + } else { + console.warn('Method ' + methodOrOptions + ' is private!'); } - } - else { - console.warn( 'Method ' + methodOrOptions + ' does not exist.' ); + } else { + console.warn('Method ' + methodOrOptions + ' does not exist.'); } }; -})(jQuery, window, document); +})(jQuery, window, document); \ No newline at end of file From 3ff90873a89623b20f582e7d50b6de3c365839ed Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 27 Oct 2018 13:15:54 -0400 Subject: [PATCH 108/237] Disable test until PHP 7.1 --- .../account/tests/Integration/AuthorizationManagerTest.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index 925208958..2fdfed15a 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -55,11 +55,12 @@ public function testAddCallback(AuthorizationManager $manager) * @depends testConstructor * @expectedException \ArgumentCountError * @param AuthorizationManager $manager + * REQUIRES PHP 7.1 or better */ - public function testCheckAccess_withOutUser(AuthorizationManager $manager) + /*public function testCheckAccess_withOutUser(AuthorizationManager $manager) { $manager->checkAccess(); - } + }*/ /** * @depends testConstructor From e630e0ef48b959b1ff7b11168100853ba174d19c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 27 Oct 2018 14:20:27 -0400 Subject: [PATCH 109/237] Restore per user theme --- .../src/ServicesProvider/ServicesProvider.php | 29 ++++++++----------- .../src/ServicesProvider/ServicesProvider.php | 9 +----- app/system/Sprinkle/SprinkleManager.php | 20 ++++++++----- 3 files changed, 26 insertions(+), 32 deletions(-) diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index e3cf80309..d4f2df469 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -46,19 +46,8 @@ public function register(ContainerInterface $container) */ $container->extend('assets', function ($assets, $c) { - // Register paths for user theme, if a user is logged in - // We catch any authorization-related exceptions, so that error pages can be rendered. - try { - /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ - $authenticator = $c->authenticator; - $currentUser = $c->currentUser; - } catch (\Exception $e) { - return $assets; - } - - if ($authenticator->check()) { - // TODO $c->sprinkleManager->addResource('assets', $currentUser->theme); - } + // Force load the current user to add it's theme assets ressources + $currentUser = $c->currentUser; return $assets; }); @@ -147,14 +136,14 @@ public function register(ContainerInterface $container) return $view; } + // Register user theme template with Twig Loader if ($authenticator->check()) { - $theme = $currentUser->theme; - // TODO $themePath = $c->sprinkleManager->addResource('templates', $theme); + $themePath = $c->locator->findResource("templates://", true, false); if ($themePath) { $loader = $twig->getLoader(); $loader->prependPath($themePath); // Add namespaced path as well - $loader->addPath($themePath, $theme); + $loader->addPath($themePath, $currentUser->theme); } } @@ -346,8 +335,14 @@ public function register(ContainerInterface $container) */ $container['currentUser'] = function ($c) { $authenticator = $c->authenticator; + $currentUser = $authenticator->user(); + + // Add user theme sprinkles ressources + if ($authenticator->check() && $currentUser->theme) { + $c->sprinkleManager->addSprinkleResources($currentUser->theme); + } - return $authenticator->user(); + return $currentUser; }; /** diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index ded29128c..eace0303b 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -102,14 +102,7 @@ public function register(ContainerInterface $container) * @return \UserFrosting\Assets\AssetLoader */ $container['assetLoader'] = function ($c) { - $config = $c->config; - $locator = $c->locator; - - $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; - - $assets = new Assets($locator, 'assets', $baseUrl); - - return new AssetLoader($assets); + return new AssetLoader($c->assets); }; /** diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index d03d9699a..4ec3b34fa 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -53,20 +53,26 @@ public function __construct(ContainerInterface $ci) /** * Register resource streams for all base sprinkles. + * For each sprinkle, register its resources and then run its initializer */ public function addResources() { - /** - * @var \UserFrosting\UniformResourceLocator\ResourceLocator $locator - */ - $locator = $this->ci->locator; - - // For each sprinkle, register its resources and then run its initializer foreach ($this->sprinkles as $sprinkleName => $sprinkle) { - $locator->registerLocation($sprinkleName, $this->sprinklesPath . $sprinkleName); + $this->addSprinkleResources($sprinkleName); } } + /** + * Register a sprinkle as a locator location + * @param string $sprinkleName + */ + public function addSprinkleResources($sprinkleName) + { + /** @var \UserFrosting\UniformResourceLocator\ResourceLocator $locator */ + $locator = $this->ci->locator; + $locator->registerLocation($sprinkleName, $this->sprinklesPath . $sprinkleName); + } + /** * Takes the name of a Sprinkle, and creates an instance of the initializer object (if defined). * From 53d657e6156c292ba24b716363b25b8dbb4e8f20 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 27 Oct 2018 16:49:46 -0400 Subject: [PATCH 110/237] Added `withTestUser` Trait for integration testing requiring a functional user --- .../tests/Integration/AuthenticatorTest.php | 43 +++++++++++++++ .../Integration/AuthorizationManagerTest.php | 2 + app/sprinkles/account/tests/withTestUser.php | 51 +++++++++++++++++ .../tests/Integration/AdminControllerTest.php | 55 ++++++++++++++++++- 4 files changed, 148 insertions(+), 3 deletions(-) create mode 100644 app/sprinkles/account/tests/Integration/AuthenticatorTest.php create mode 100644 app/sprinkles/account/tests/withTestUser.php diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php new file mode 100644 index 000000000..59454e760 --- /dev/null +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -0,0 +1,43 @@ +setupTestDatabase(); + $this->refreshDatabase(); + } + + /** + * @return Authenticator + */ + public function testConstructor() + { + $authenticator = new Authenticator($this->ci->classMapper, $this->ci->session, $this->ci->config, $this->ci->cache); + $this->assertInstanceOf(Authenticator::class, $authenticator); + return $authenticator; + } diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index 2fdfed15a..68a988775 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -4,6 +4,7 @@ use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager; use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Tests\withTestUser; use UserFrosting\Sprinkle\Core\Tests\TestDatabase; use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; use UserFrosting\Tests\TestCase; @@ -15,6 +16,7 @@ class AuthorizationManagerTest extends TestCase { use TestDatabase; use RefreshDatabase; + use withTestUser; /** * Setup the test database. diff --git a/app/sprinkles/account/tests/withTestUser.php b/app/sprinkles/account/tests/withTestUser.php new file mode 100644 index 000000000..eee5c6d0f --- /dev/null +++ b/app/sprinkles/account/tests/withTestUser.php @@ -0,0 +1,51 @@ +ci->currentUser = $user; + $this->ci->authenticator->login($user); + } + + /** + * Logout + */ + protected function logoutCurrentUser() + { + $this->ci->authenticator->logout(); + } + + /** + * Create a test user with no settings/permissions for a controller test + * @param bool $isAdmin + * @return User + */ + protected function createTestUser($isAdmin = false) + { + if ($isAdmin) { + $user_id = $this->ci->config['reserved_user_ids.master']; + } else { + $user_id = rand(0, 1222); + } + + $fm = $this->ci->factory; + return $fm->create(User::class, ["id" => $user_id]); + } +} diff --git a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php index 4bbda10c4..ff662980a 100644 --- a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php +++ b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php @@ -11,12 +11,20 @@ */ class AdminControllerTest extends ControllerTestCase { + use withTestUser; + + public function tearDown() + { + // N.B.: This shouldn't be necessary with the NullSessionProvier ! + $this->logoutCurrentUser(); + } + /** * @return AdminController */ public function testControllerConstructor() { - $controller = new AdminController($this->ci); + $controller = $this->getController(); $this->assertInstanceOf(AdminController::class, $controller); return $controller; } @@ -24,10 +32,51 @@ public function testControllerConstructor() /** * @depends testControllerConstructor * @expectedException \UserFrosting\Support\Exception\ForbiddenException - * @param AdminController $controller */ - public function testPageDashboard_NullUser(AdminController $controller) + public function testPageDashboard_NullUser() + { + $controller = $this->getController(); + $controller->pageDashboard($this->getRequest(), $this->getResponse(), []); + } + + /** + * @depends testControllerConstructor + * @expectedException \UserFrosting\Support\Exception\ForbiddenException + */ + public function testPageDashboard_ForbiddenException() { + // Non admin user, won't have access + $testUser = $this->createTestUser(); + $this->setCurrentUser($testUser); + + // Get controller + $controller = $this->getController(); + $controller->pageDashboard($this->getRequest(), $this->getResponse(), []); } + + /** + * @depends testControllerConstructor + */ + public function testPageDashboard() + { + // Admin user, WILL have access + $testUser = $this->createTestUser(true); + $this->setCurrentUser($testUser); + + // Get controller + $controller = $this->getController(); + + $result = $controller->pageDashboard($this->getRequest(), $this->getResponse(), []); + $this->assertSame($result->getStatusCode(), 200); + $this->assertNotEmpty((string) $result->getBody()); + } + + /** + * @return AdminController + */ + private function getController() + { + return new AdminController($this->ci); + } } From 4b3369297f2d414c4ae9a0c01e0100290ce4d2d3 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 27 Oct 2018 17:18:05 -0400 Subject: [PATCH 111/237] Apply #757 to `AdminController` (with test!) --- .../admin/src/Controller/AdminController.php | 2 +- .../tests/Integration/AdminControllerTest.php | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/admin/src/Controller/AdminController.php b/app/sprinkles/admin/src/Controller/AdminController.php index 53ea83f3e..1af8b7e85 100644 --- a/app/sprinkles/admin/src/Controller/AdminController.php +++ b/app/sprinkles/admin/src/Controller/AdminController.php @@ -120,7 +120,7 @@ public function clearCache(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'CACHE.CLEARED'); - return $response->withStatus(200); + return $response->withJson([], 200); } /** diff --git a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php index ff662980a..b2e1f98bf 100644 --- a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php +++ b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php @@ -72,6 +72,44 @@ public function testPageDashboard() $this->assertNotEmpty((string) $result->getBody()); } + /** + * Clear-cache controller method + * @depends testControllerConstructor + */ + public function testClearCache() + { + // Admin user, WILL have access + $testUser = $this->createTestUser(true); + $this->setCurrentUser($testUser); + + // Get controller + $controller = $this->getController(); + + // First, store something in cache + /** @var \Illuminate\Cache\Repository $cache **/ + $cache = $this->ci->cache; + $value = rand(1, 100); + $cache->put('foo', $value, 20); + $this->assertSame($value, $cache->get('foo')); + + $result = $controller->clearCache($this->getRequest(), $this->getResponse(), []); + $this->assertSame($result->getStatusCode(), 200); + $this->assertJson((string) $result->getBody()); + $this->assertSame('[]', (string) $result->getBody()); + + // Cache should be gone + $this->assertNotSame($value, $cache->get('foo')); + + // We can also check AlertStream Integration + /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ + $ms = $this->ci->alerts; + $messages = $ms->getAndClearMessages(); + $expectedMessage = end($messages)["message"]; + + $actualMessage = $this->ci->translator->translate('CACHE.CLEARED'); + $this->assertSame($expectedMessage, $actualMessage); + } + /** * @return AdminController */ From 24d3fe66abe1abce3c1550cc5304598473471d66 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 27 Oct 2018 18:37:55 -0400 Subject: [PATCH 112/237] Added more tests to `AuthorizationManager` --- .../Integration/AuthorizationManagerTest.php | 72 ++++++++++++++++++- app/sprinkles/account/tests/withTestUser.php | 55 +++++++++++++- 2 files changed, 122 insertions(+), 5 deletions(-) diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index 68a988775..f3d580cce 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -3,7 +3,6 @@ namespace UserFrosting\Sprinkle\Account\Tests\Integration; use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager; -use UserFrosting\Sprinkle\Account\Database\Models\User; use UserFrosting\Sprinkle\Account\Tests\withTestUser; use UserFrosting\Sprinkle\Core\Tests\TestDatabase; use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; @@ -30,12 +29,18 @@ public function setUp() $this->refreshDatabase(); } + public function tearDown() + { + // N.B.: This shouldn't be necessary with the NullSessionProvier ! + $this->logoutCurrentUser(); + } + /** * @return AuthorizationManager */ public function testConstructor() { - $manager = new AuthorizationManager($this->ci, []); + $manager = $this->getManager(); $this->assertInstanceOf(AuthorizationManager::class, $manager); return $manager; } @@ -81,4 +86,67 @@ public function testCheckAccess_withBadUserType(AuthorizationManager $manager) { $this->assertFalse($manager->checkAccess(123, 'foo')); } + + /** + * Test the service. Will have the predefined callbacks + */ + public function testService() + { + $this->assertInstanceOf(AuthorizationManager::class, $this->ci->authorizer); + } + + /** + * @depends testService + */ + public function testCheckAccess_withGuestUser() + { + $user = $this->createTestUser(); + $manager = $this->ci->authorizer; + $this->assertFalse($manager->checkAccess($user, 'foo')); + } + + /** + * @depends testService + */ + public function testCheckAccess_withNormalUser() + { + $user = $this->createTestUser(false, true); + $manager = $this->ci->authorizer; + $this->assertFalse($manager->checkAccess($user, 'foo')); + $this->assertFalse($manager->checkAccess($this->ci->currentUser, 'foo')); + } + + /** + * @depends testService + */ + public function testCheckAccess_withMasterUser() + { + $user = $this->createTestUser(true, true); + $manager = $this->ci->authorizer; + $this->assertTrue($manager->checkAccess($user, 'foo')); + $this->assertTrue($manager->checkAccess($this->ci->currentUser, 'foo')); + } + + /** + * @depends testCheckAccess_withNormalUser + */ + public function testCheckAccess_withNormalUserWithPermission() + { + // Create a non admin user and give him the 'foo' permission + $user = $this->createTestUser(); + $this->giveUserTestPermission($user, 'foo'); + $this->setCurrentUser($user); + + $manager = $this->ci->authorizer; + $this->assertTrue($manager->checkAccess($user, 'foo')); + $this->assertTrue($manager->checkAccess($this->ci->currentUser, 'foo')); + } + + /** + * @return AuthorizationManager + */ + protected function getManager() + { + return new AuthorizationManager($this->ci, []); + } } diff --git a/app/sprinkles/account/tests/withTestUser.php b/app/sprinkles/account/tests/withTestUser.php index eee5c6d0f..6730f517b 100644 --- a/app/sprinkles/account/tests/withTestUser.php +++ b/app/sprinkles/account/tests/withTestUser.php @@ -8,6 +8,8 @@ namespace UserFrosting\Sprinkle\Account\Tests; use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Database\Models\Permission; +use UserFrosting\Sprinkle\Account\Database\Models\Role; /** * Helper trait to pose as user when running an integration test @@ -34,10 +36,11 @@ protected function logoutCurrentUser() /** * Create a test user with no settings/permissions for a controller test - * @param bool $isAdmin + * @param bool $isAdmin Does this user have root access? Will bypass all permissions + * @param bool $login Login this user, setting him as the currentUser * @return User */ - protected function createTestUser($isAdmin = false) + protected function createTestUser($isAdmin = false, $login = false) { if ($isAdmin) { $user_id = $this->ci->config['reserved_user_ids.master']; @@ -46,6 +49,52 @@ protected function createTestUser($isAdmin = false) } $fm = $this->ci->factory; - return $fm->create(User::class, ["id" => $user_id]); + $user = $fm->create(User::class, ["id" => $user_id]); + + if ($login) { + $this->setCurrentUser($user); + } + + return $user; + } + + /** + * Gives a user a new test permission + * @param User $user + * @param string $slug + * @param string $conditions + * @return Permission + */ + protected function giveUserTestPermission(User $user, $slug, $conditions = "always()") + { + /** @var \League\FactoryMuffin\FactoryMuffin $fm **/ + $fm = $this->ci->factory; + + $permission = $fm->create(Permission::class, [ + 'slug' => $slug, + 'conditions' => $conditions + ]); + + // Add the permission to the user + $this->giveUserPermission($user, $permission); + + return $permission; + } + + /** + * Add the test permission to a Role, then the role to the user + * @param User $user + * @param Permission $permission + * @return Role The intermidiate role + */ + protected function giveUserPermission(User $user, Permission $permission) + { + /** @var \League\FactoryMuffin\FactoryMuffin $fm **/ + $fm = $this->ci->factory; + + $role = $fm->create(Role::class); + $role->permissions()->attach($permission); + $user->roles()->attach($role); + return $role; } } From 47f7406de0e2ca2fb9ff537e6361080cd962fd5a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 27 Oct 2018 18:46:33 -0400 Subject: [PATCH 113/237] Bad commit staging was bad --- app/sprinkles/account/tests/Integration/AuthenticatorTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index 59454e760..9739558ba 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -41,3 +41,4 @@ public function testConstructor() $this->assertInstanceOf(Authenticator::class, $authenticator); return $authenticator; } +} From 95a9666d64983cef3b1f8ff1285a995b4d7302a7 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 28 Oct 2018 17:25:22 -0400 Subject: [PATCH 114/237] Implement `NullSessionHandler` for testing env --- app/sprinkles/account/tests/withTestUser.php | 6 +- app/sprinkles/core/config/default.php | 2 +- app/sprinkles/core/config/testing.php | 9 +++ .../src/ServicesProvider/ServicesProvider.php | 5 +- .../core/src/Session/NullSessionHandler.php | 61 +++++++++++++++++++ phpunit.xml | 2 +- 6 files changed, 79 insertions(+), 6 deletions(-) create mode 100644 app/sprinkles/core/src/Session/NullSessionHandler.php diff --git a/app/sprinkles/account/tests/withTestUser.php b/app/sprinkles/account/tests/withTestUser.php index 6730f517b..a39a35799 100644 --- a/app/sprinkles/account/tests/withTestUser.php +++ b/app/sprinkles/account/tests/withTestUser.php @@ -36,13 +36,13 @@ protected function logoutCurrentUser() /** * Create a test user with no settings/permissions for a controller test - * @param bool $isAdmin Does this user have root access? Will bypass all permissions + * @param bool $isMaster Does this user have root access? Will bypass all permissions * @param bool $login Login this user, setting him as the currentUser * @return User */ - protected function createTestUser($isAdmin = false, $login = false) + protected function createTestUser($isMaster = false, $login = false) { - if ($isAdmin) { + if ($isMaster) { $user_id = $this->ci->config['reserved_user_ids.master']; } else { $user_id = rand(0, 1222); diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 58704ca1c..2d2a50c41 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -157,7 +157,7 @@ 'public_relative' => dirname($_SERVER['SCRIPT_NAME']) // The location of `index.php` relative to the document root. Use for sites installed in subdirectories of your web server's document root. ], 'session' => [ - 'handler' => 'file', //file or database + 'handler' => 'file', //file, database or array // Config values for when using db-based sessions 'database' => [ 'table' => 'sessions' diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index 6b2ded25d..bc8efc058 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -35,6 +35,15 @@ 'settings' => [ 'displayErrorDetails' => false ], + /** + * Disable native sessions in tests + */ + 'session' => [ + 'handler' => 'array' + ], + /** + * Use testning filesystem for tests + */ 'filesystems' => [ 'disks' => [ 'testing' => [ diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index eace0303b..023a8c804 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -45,8 +45,9 @@ use UserFrosting\Sprinkle\Core\Database\Migrator\Migrator; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocator; use UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository; -use \UserFrosting\Sprinkle\Core\Filesystem\FilesystemManager; +use UserFrosting\Sprinkle\Core\Filesystem\FilesystemManager; use UserFrosting\Sprinkle\Core\Router; +use UserFrosting\Sprinkle\Core\Session\NullSessionHandler; use UserFrosting\Sprinkle\Core\Throttle\Throttler; use UserFrosting\Sprinkle\Core\Throttle\ThrottleRule; use UserFrosting\Sprinkle\Core\Twig\CoreExtension; @@ -623,6 +624,8 @@ public function register(ContainerInterface $container) $connection = $c->db->connection(); // Table must exist, otherwise an exception will be thrown $handler = new DatabaseSessionHandler($connection, $config['session.database.table'], $config['session.minutes']); + } elseif ($config['session.handler'] == 'array') { + $handler = new NullSessionHandler; } else { throw new \Exception("Bad session handler type '{$config['session.handler']}' specified in configuration file."); } diff --git a/app/sprinkles/core/src/Session/NullSessionHandler.php b/app/sprinkles/core/src/Session/NullSessionHandler.php new file mode 100644 index 000000000..7e4b8cf2e --- /dev/null +++ b/app/sprinkles/core/src/Session/NullSessionHandler.php @@ -0,0 +1,61 @@ + - \ No newline at end of file + From 4a3aa595bf9269e74f7fa87d051607bb467e9745 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 28 Oct 2018 20:39:02 -0400 Subject: [PATCH 115/237] Automatically logout test user after a test --- .../tests/Integration/AuthorizationManagerTest.php | 8 +------- app/sprinkles/account/tests/withTestUser.php | 9 +++++++-- .../admin/tests/Integration/AdminControllerTest.php | 13 +++---------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index f3d580cce..eefc32bc4 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -29,12 +29,6 @@ public function setUp() $this->refreshDatabase(); } - public function tearDown() - { - // N.B.: This shouldn't be necessary with the NullSessionProvier ! - $this->logoutCurrentUser(); - } - /** * @return AuthorizationManager */ @@ -135,7 +129,7 @@ public function testCheckAccess_withNormalUserWithPermission() // Create a non admin user and give him the 'foo' permission $user = $this->createTestUser(); $this->giveUserTestPermission($user, 'foo'); - $this->setCurrentUser($user); + $this->loginUser($user); $manager = $this->ci->authorizer; $this->assertTrue($manager->checkAccess($user, 'foo')); diff --git a/app/sprinkles/account/tests/withTestUser.php b/app/sprinkles/account/tests/withTestUser.php index a39a35799..4528c8cd7 100644 --- a/app/sprinkles/account/tests/withTestUser.php +++ b/app/sprinkles/account/tests/withTestUser.php @@ -20,10 +20,15 @@ trait withTestUser /** * @param User $user */ - protected function setCurrentUser(User $user) + protected function loginUser(User $user) { $this->ci->currentUser = $user; $this->ci->authenticator->login($user); + + // Log user out when we're done with testing to prevent session persistence + $this->beforeApplicationDestroyed(function () use ($user) { + $this->logoutCurrentUser($user); + }); } /** @@ -52,7 +57,7 @@ protected function createTestUser($isMaster = false, $login = false) $user = $fm->create(User::class, ["id" => $user_id]); if ($login) { - $this->setCurrentUser($user); + $this->loginUser($user); } return $user; diff --git a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php index b2e1f98bf..651a1d34b 100644 --- a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php +++ b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php @@ -13,12 +13,6 @@ class AdminControllerTest extends ControllerTestCase { use withTestUser; - public function tearDown() - { - // N.B.: This shouldn't be necessary with the NullSessionProvier ! - $this->logoutCurrentUser(); - } - /** * @return AdminController */ @@ -47,11 +41,10 @@ public function testPageDashboard_ForbiddenException() { // Non admin user, won't have access $testUser = $this->createTestUser(); - $this->setCurrentUser($testUser); + $this->loginUser($testUser); // Get controller $controller = $this->getController(); - $controller->pageDashboard($this->getRequest(), $this->getResponse(), []); } @@ -62,7 +55,7 @@ public function testPageDashboard() { // Admin user, WILL have access $testUser = $this->createTestUser(true); - $this->setCurrentUser($testUser); + $this->loginUser($testUser); // Get controller $controller = $this->getController(); @@ -80,7 +73,7 @@ public function testClearCache() { // Admin user, WILL have access $testUser = $this->createTestUser(true); - $this->setCurrentUser($testUser); + $this->loginUser($testUser); // Get controller $controller = $this->getController(); From ea9a8d5fb9983633eb4b23d9aabfc0d605c3ca32 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 28 Oct 2018 20:40:15 -0400 Subject: [PATCH 116/237] Properly tear down tests --- app/sprinkles/account/tests/Unit/RegistrationTest.php | 1 + .../core/tests/Integration/BakeryMigrateCommandTest.php | 1 + .../core/tests/Integration/BakeryMigrateRefreshCommandTest.php | 1 + .../core/tests/Integration/BakeryMigrateResetCommandTest.php | 1 + .../core/tests/Integration/BakeryMigrateRollbackCommandTest.php | 1 + .../core/tests/Integration/BakeryMigrateStatusCommandTest.php | 1 + app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php | 1 + app/sprinkles/core/tests/Integration/DatabaseTests.php | 2 ++ app/sprinkles/core/tests/Integration/MigrationLocatorTest.php | 1 + .../core/tests/Integration/MigrationRepositoryTest.php | 1 + app/sprinkles/core/tests/Integration/Seeder/SeederTests.php | 1 + app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php | 1 + app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php | 1 + app/sprinkles/core/tests/Unit/SprunjeTest.php | 1 + 14 files changed, 15 insertions(+) diff --git a/app/sprinkles/account/tests/Unit/RegistrationTest.php b/app/sprinkles/account/tests/Unit/RegistrationTest.php index cb40e59cc..f36c0ab4a 100644 --- a/app/sprinkles/account/tests/Unit/RegistrationTest.php +++ b/app/sprinkles/account/tests/Unit/RegistrationTest.php @@ -26,6 +26,7 @@ class RegistrationTest extends TestCase public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php index 735098da7..395fcffbf 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php @@ -17,6 +17,7 @@ class DatabaseMigrationMigrateCommandTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php index f496de7f5..f69597606 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php @@ -17,6 +17,7 @@ class BakeryMigrateRefreshCommandTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php index 7a37965d1..53afca13e 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php @@ -17,6 +17,7 @@ class BakeryMigrateResetCommandTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php index af0ee7f6d..d5e02f6dc 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php @@ -17,6 +17,7 @@ class BakeryMigrateRollbackCommandTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php index 05078c486..5affcbc7a 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php @@ -17,6 +17,7 @@ class BakeryMigrateStatusCommandTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php index b0d7deb66..4a50083ef 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php @@ -29,6 +29,7 @@ class DatabaseMigratorTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/DatabaseTests.php b/app/sprinkles/core/tests/Integration/DatabaseTests.php index 271f1f142..5c137aeab 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseTests.php +++ b/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -119,6 +119,8 @@ public function tearDown() $this->schema($this->schemaName)->drop('jobs'); Relation::morphMap([], false); + + parent::tearDown(); } /** diff --git a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php index 44406bb48..fc01f9cc4 100644 --- a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php @@ -19,6 +19,7 @@ class MigrationLocatorTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php index 66e1f7f79..6eb7683ad 100644 --- a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php @@ -16,6 +16,7 @@ class MigrationRepositoryTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php b/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php index 5062501b3..632a1a6bc 100644 --- a/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php +++ b/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php @@ -35,6 +35,7 @@ public function setUp() public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php index d335e1420..fa4a2b4de 100644 --- a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php +++ b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php @@ -22,6 +22,7 @@ class BelongsToManyThroughTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php b/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php index 8ae4c8d65..fd8d0deb8 100644 --- a/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php +++ b/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php @@ -19,6 +19,7 @@ class DatabaseSyncableTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } diff --git a/app/sprinkles/core/tests/Unit/SprunjeTest.php b/app/sprinkles/core/tests/Unit/SprunjeTest.php index bc4942cec..11c22244e 100644 --- a/app/sprinkles/core/tests/Unit/SprunjeTest.php +++ b/app/sprinkles/core/tests/Unit/SprunjeTest.php @@ -22,6 +22,7 @@ class SprunjeTest extends TestCase { public function tearDown() { + parent::tearDown(); m::close(); } From 6e4e9d5a42e8b36e459cef85a4ee849601796acf Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 31 Oct 2018 21:48:47 -0400 Subject: [PATCH 117/237] Add test coverage configuration --- app/system/Bakery/Command/Test.php | 7 +++++++ phpunit.xml | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/app/system/Bakery/Command/Test.php b/app/system/Bakery/Command/Test.php index c2dddf7f4..a7d6c84de 100644 --- a/app/system/Bakery/Command/Test.php +++ b/app/system/Bakery/Command/Test.php @@ -9,6 +9,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Input\InputOption; use UserFrosting\System\Bakery\BaseCommand; /** @@ -30,6 +31,7 @@ class Test extends BaseCommand protected function configure() { $this->setName("test") + ->addOption("coverage", "c", InputOption::VALUE_NONE, "Generate code coverage report in HTML format. Will be saved in _meta/coverage") ->setDescription("Run tests") ->setHelp("Run php unit tests"); } @@ -47,6 +49,11 @@ protected function execute(InputInterface $input, OutputInterface $output) $command .= " -v"; } + // Add coverage report + if ($input->getOption('coverage')) { + $command .= " --coverage-html _meta/coverage"; + } + // Execute $this->io->writeln("> $command"); passthru($command); diff --git a/phpunit.xml b/phpunit.xml index 2d6d671fb..942583c38 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -19,4 +19,15 @@ + + + app/ + public/index.php + + app/vendor/ + app/tests/ + app/sprinkles/*/tests/ + + + From dcc8e2a8c6d91136cbf3a33e0bad4ccf489c916c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 31 Oct 2018 22:08:02 -0400 Subject: [PATCH 118/237] Adding more test for Authenticator --- .../tests/Integration/AuthenticatorTest.php | 86 +++++++++++++++++++ app/tests/TestCase.php | 17 ++++ 2 files changed, 103 insertions(+) diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index 9739558ba..b1fd207fd 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -41,4 +41,90 @@ public function testConstructor() $this->assertInstanceOf(Authenticator::class, $authenticator); return $authenticator; } + + /** + * @depends testConstructor + * @covers Authenticator::login + * @covers Authenticator::logout + * @param Authenticator $authenticator + */ + public function testLogin(Authenticator $authenticator) + { + // Create a test user + $testUser = $this->createTestUser(); + + // Test session to avoid false positive + $key = $this->ci->config['session.keys.current_user_id']; + $this->assertNull($this->ci->session[$key]); + $this->assertNotSame($testUser->id, $this->ci->session[$key]); + + // Login the test user + $authenticator->login($testUser, false); + + // Test session to see if user was logged in + $this->assertNotNull($this->ci->session[$key]); + $this->assertSame($testUser->id, $this->ci->session[$key]); + + // Must logout to avoid test issue + $authenticator->logout(); + + // We'll test the logout system works too while we're at it (and depend on it) + $key = $this->ci->config['session.keys.current_user_id']; + $this->assertNull($this->ci->session[$key]); + $this->assertNotSame($testUser->id, $this->ci->session[$key]); + } + + /** + * @depends testConstructor + * @expectedException \UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountInvalidException + * @param Authenticator $authenticator + */ + public function testValidateUserAccountThrowAccountInvalidException(Authenticator $authenticator) + { + $this->invokeMethod($authenticator, 'validateUserAccount', [99999999]); + } + + /** + * @depends testConstructor + * @param Authenticator $authenticator + */ + public function testValidateUserAccountRetunNullOnFalseArgument(Authenticator $authenticator) + { + $user = $this->invokeMethod($authenticator, 'validateUserAccount', [false]); + $this->assertNull($user); + } + + /** + * @depends testConstructor + * @expectedException \UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountInvalidException + * @param Authenticator $authenticator + */ + public function testValidateUserAccountThrowExceptionArgumentNotInt(Authenticator $authenticator) + { + $this->invokeMethod($authenticator, 'validateUserAccount', ['stringIsNotInt']); + } + + /** + * @depends testConstructor + * @param Authenticator $authenticator + */ + public function testValidateUserAccount(Authenticator $authenticator) + { + $testUser = $this->createTestUser(); + $user = $this->invokeMethod($authenticator, 'validateUserAccount', [$testUser->id]); + $this->assertSame($testUser->id, $user->id); + } + + /** + * @depends testConstructor + * @expectedException \UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountDisabledException + * @param Authenticator $authenticator + */ + public function testValidateUserAccountWithAccountDisabledException(Authenticator $authenticator) + { + $testUser = $this->createTestUser(); + $testUser->flag_enabled = false; + $testUser->save(); + $this->invokeMethod($authenticator, 'validateUserAccount', [$testUser->id]); + } } diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php index 5d7310b34..13e1d0c69 100644 --- a/app/tests/TestCase.php +++ b/app/tests/TestCase.php @@ -165,6 +165,23 @@ public static function assertCollectionsSame($expected, $actual, $key = 'id', $m } } + /** + * Call protected/private method of a class. + * + * @param object &$object Instantiated object that we will run method on. + * @param string $methodName Method name to call + * @param array $parameters Array of parameters to pass into method. + * @return mixed Method return. + */ + public function invokeMethod(&$object, $methodName, array $parameters = array()) + { + $reflection = new \ReflectionClass(get_class($object)); + $method = $reflection->getMethod($methodName); + $method->setAccessible(true); + + return $method->invokeArgs($object, $parameters); + } + /** * Register a callback to be run before the application is destroyed. * From 5a115f87d7e83dc5aab9fd503747a9c5be36f3ea Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 2 Nov 2018 22:01:04 -0400 Subject: [PATCH 119/237] Improve AuthorizationManager test coverage... ...reducing risk of false positive --- .../src/Authorize/AuthorizationManager.php | 12 +- .../Integration/AuthorizationManagerTest.php | 110 ++++++++++++------ 2 files changed, 81 insertions(+), 41 deletions(-) diff --git a/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/app/sprinkles/account/src/Authorize/AuthorizationManager.php index b501708be..078ef544b 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationManager.php @@ -91,12 +91,14 @@ public function checkAccess($user, $slug, array $params = []) $this->ci->authLogger->debug("Checking authorization for user {$user->id} ('{$user->user_name}') on permission '$slug'..."); } - if ($this->ci->authenticator->guest()) { + // TODO : This doesn't make sense. The argument $user shouldn't be impacted by the user doing the request + // See : https://github.com/userfrosting/UserFrosting/issues/736#issuecomment-313525283 + /*if ($this->ci->authenticator->guest()) { if ($debug) { $this->ci->authLogger->debug("User is not logged in. Access denied."); } return false; - } + }*/ // The master (root) account has access to everything. // Need to use loose comparison for now, because some DBs return `id` as a string. @@ -112,7 +114,7 @@ public function checkAccess($user, $slug, array $params = []) if (empty($permissions) || !isset($permissions[$slug])) { if ($debug) { - $this->ci->authLogger->debug("No matching permissions found. Access denied."); + $this->ci->authLogger->debug("No matching permissions found. Access denied."); } return false; } @@ -130,14 +132,14 @@ public function checkAccess($user, $slug, array $params = []) $pass = $ace->evaluateCondition($permission->conditions, $params); if ($pass) { if ($debug) { - $this->ci->authLogger->debug("User passed conditions '{$permission->conditions}' . Access granted."); + $this->ci->authLogger->debug("User passed conditions '{$permission->conditions}'. Access granted."); } return true; } } if ($debug) { - $this->ci->authLogger->debug("User failed to pass any of the matched permissions. Access denied."); + $this->ci->authLogger->debug("User failed to pass any of the matched permissions. Access denied."); } return false; diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index eefc32bc4..492181e32 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -2,6 +2,7 @@ namespace UserFrosting\Sprinkle\Account\Tests\Integration; +use Mockery as m; use UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager; use UserFrosting\Sprinkle\Account\Tests\withTestUser; use UserFrosting\Sprinkle\Core\Tests\TestDatabase; @@ -29,6 +30,12 @@ public function setUp() $this->refreshDatabase(); } + public function tearDown() + { + parent::tearDown(); + m::close(); + } + /** * @return AuthorizationManager */ @@ -52,6 +59,14 @@ public function testAddCallback(AuthorizationManager $manager) $this->assertEquals(['foo' => function () {}], $callbacks); } + /** + * Test the service. Will have the predefined callbacks + */ + public function testService() + { + $this->assertInstanceOf(AuthorizationManager::class, $this->ci->authorizer); + } + /** * @depends testConstructor * @expectedException \ArgumentCountError @@ -65,60 +80,51 @@ public function testAddCallback(AuthorizationManager $manager) /** * @depends testConstructor - * @param AuthorizationManager $manager */ - public function testCheckAccess_withNullUser(AuthorizationManager $manager) + public function testCheckAccess_withNullUser() { - $this->assertFalse($manager->checkAccess(null, 'foo')); + $this->getMockAuthLogger()->shouldReceive('debug')->once()->with("No user defined. Access denied."); + $this->assertFalse($this->getManager()->checkAccess(null, 'foo')); } /** * @depends testConstructor - * @param AuthorizationManager $manager */ - public function testCheckAccess_withBadUserType(AuthorizationManager $manager) + public function testCheckAccess_withBadUserType() { - $this->assertFalse($manager->checkAccess(123, 'foo')); + $this->getMockAuthLogger()->shouldReceive('debug')->once()->with("No user defined. Access denied."); + $this->assertFalse($this->getManager()->checkAccess(123, 'foo')); } /** - * Test the service. Will have the predefined callbacks + * @depends testConstructor */ - public function testService() + public function testCheckAccess_withNormalUser() { - $this->assertInstanceOf(AuthorizationManager::class, $this->ci->authorizer); - } + $user = $this->createTestUser(false); - /** - * @depends testService - */ - public function testCheckAccess_withGuestUser() - { - $user = $this->createTestUser(); - $manager = $this->ci->authorizer; - $this->assertFalse($manager->checkAccess($user, 'foo')); - } + // Setup authLogger expectations + $authLogger = $this->getMockAuthLogger(); + $authLogger->shouldReceive('debug')->once()->with("No matching permissions found. Access denied."); + $authLogger->shouldReceive('debug')->times(2); - /** - * @depends testService - */ - public function testCheckAccess_withNormalUser() - { - $user = $this->createTestUser(false, true); - $manager = $this->ci->authorizer; - $this->assertFalse($manager->checkAccess($user, 'foo')); - $this->assertFalse($manager->checkAccess($this->ci->currentUser, 'foo')); + $this->assertFalse($this->getManager()->checkAccess($user, 'foo')); } /** * @depends testService + * @depends testCheckAccess_withNormalUser */ public function testCheckAccess_withMasterUser() { - $user = $this->createTestUser(true, true); - $manager = $this->ci->authorizer; - $this->assertTrue($manager->checkAccess($user, 'foo')); - $this->assertTrue($manager->checkAccess($this->ci->currentUser, 'foo')); + $user = $this->createTestUser(true); + + // Setup authLogger expectations + $authLogger = $this->getMockAuthLogger(); + $authLogger->shouldReceive('debug')->once()->with("User is the master (root) user. Access granted."); + $authLogger->shouldReceive('debug')->times(2); + + $this->assertTrue($this->getManager()->checkAccess($user, 'foo')); } /** @@ -129,11 +135,31 @@ public function testCheckAccess_withNormalUserWithPermission() // Create a non admin user and give him the 'foo' permission $user = $this->createTestUser(); $this->giveUserTestPermission($user, 'foo'); - $this->loginUser($user); - $manager = $this->ci->authorizer; - $this->assertTrue($manager->checkAccess($user, 'foo')); - $this->assertTrue($manager->checkAccess($this->ci->currentUser, 'foo')); + // Setup authLogger expectations + $authLogger = $this->getMockAuthLogger(); + $authLogger->shouldReceive('debug')->once()->with("Evaluating callback 'always'..."); + $authLogger->shouldReceive('debug')->once()->with("User passed conditions 'always()'. Access granted."); + $authLogger->shouldReceive('debug')->times(6); + + $this->assertTrue($this->ci->authorizer->checkAccess($user, 'foo')); + } + + /** + * @depends testCheckAccess_withNormalUserWithPermission + */ + public function testCheckAccess_withNormalUserWithFailedPermission() + { + // Create a non admin user and give him the 'foo' permission + $user = $this->createTestUser(); + $this->giveUserTestPermission($user, 'foo', 'is_master(self.id)'); + + // Setup authLogger expectations + $authLogger = $this->getMockAuthLogger(); + $authLogger->shouldReceive('debug')->once()->with("User failed to pass any of the matched permissions. Access denied."); + $authLogger->shouldReceive('debug')->times(7); + + $this->assertFalse($this->ci->authorizer->checkAccess($user, 'foo')); } /** @@ -143,4 +169,16 @@ protected function getManager() { return new AuthorizationManager($this->ci, []); } + + /** + * We'll test using the `debug.auth` on and a mock authLogger to not get our + * dirty test into the real log + * @return \Monolog\Logger + */ + protected function getMockAuthLogger() + { + $this->ci->config['debug.auth'] = true; + $this->ci->authLogger = m::mock('\Monolog\Logger'); + return $this->ci->authLogger; + } } From 5be1a3779979a2c9facfbb294bc41bf15d6d75de Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 10:22:07 -0400 Subject: [PATCH 120/237] Add one more test for guest user & currentUser behavior --- .../src/Authorize/AuthorizationManager.php | 9 ------ .../Integration/AuthorizationManagerTest.php | 31 +++++++++++++++++++ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/app/sprinkles/account/src/Authorize/AuthorizationManager.php index 078ef544b..8f6606f31 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationManager.php @@ -91,15 +91,6 @@ public function checkAccess($user, $slug, array $params = []) $this->ci->authLogger->debug("Checking authorization for user {$user->id} ('{$user->user_name}') on permission '$slug'..."); } - // TODO : This doesn't make sense. The argument $user shouldn't be impacted by the user doing the request - // See : https://github.com/userfrosting/UserFrosting/issues/736#issuecomment-313525283 - /*if ($this->ci->authenticator->guest()) { - if ($debug) { - $this->ci->authLogger->debug("User is not logged in. Access denied."); - } - return false; - }*/ - // The master (root) account has access to everything. // Need to use loose comparison for now, because some DBs return `id` as a string. if ($user->id == $this->ci->config['reserved_user_ids.master']) { diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index 492181e32..4ec120d2e 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -96,6 +96,19 @@ public function testCheckAccess_withBadUserType() $this->assertFalse($this->getManager()->checkAccess(123, 'foo')); } + /** + * By default, `checkAccess` is null. Test to make sure we don't break the + * "current user is guest" thing + * @depends testCheckAccess_withNullUser + */ + public function testCheckAccess_withNullCurrentUser() + { + $this->getMockAuthLogger()->shouldReceive('debug')->once()->with("No user defined. Access denied."); + $user = $this->ci->currentUser; + $this->assertNull($user); + $this->assertFalse($this->getManager()->checkAccess($user, 'foo')); + } + /** * @depends testConstructor */ @@ -111,6 +124,24 @@ public function testCheckAccess_withNormalUser() $this->assertFalse($this->getManager()->checkAccess($user, 'foo')); } + /** + * Once logged in, `currentUser` will not be null + * @depends testCheckAccess_withNormalUser + */ + public function testCheckAccess_withCurrentUser() + { + $user = $this->createTestUser(false, true); + $this->assertNotNull($this->ci->currentUser); + $this->assertSame($user, $this->ci->currentUser); + + // Setup authLogger expectations + $authLogger = $this->getMockAuthLogger(); + $authLogger->shouldReceive('debug')->once()->with("No matching permissions found. Access denied."); + $authLogger->shouldReceive('debug')->times(2); + + $this->assertFalse($this->getManager()->checkAccess($this->ci->currentUser, 'foo')); + } + /** * @depends testService * @depends testCheckAccess_withNormalUser From 20ca8ddf27d2630f5c7c3eca84ceb170069ecd0f Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 14:19:55 -0400 Subject: [PATCH 121/237] Added more Authenticator tests --- .../tests/Integration/AuthenticatorTest.php | 257 +++++++++++++++++- app/sprinkles/account/tests/withTestUser.php | 7 +- 2 files changed, 258 insertions(+), 6 deletions(-) diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index b1fd207fd..4b5ad66b1 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -3,8 +3,9 @@ namespace UserFrosting\Sprinkle\Account\Tests\Integration; use UserFrosting\Sprinkle\Account\Authenticate\Authenticator; -use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Account\Tests\withTestUser; +use UserFrosting\Sprinkle\Core\Facades\Debug; use UserFrosting\Sprinkle\Core\Tests\TestDatabase; use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; use UserFrosting\Tests\TestCase; @@ -37,15 +38,13 @@ public function setUp() */ public function testConstructor() { - $authenticator = new Authenticator($this->ci->classMapper, $this->ci->session, $this->ci->config, $this->ci->cache); + $authenticator = $this->getAuthenticator(); $this->assertInstanceOf(Authenticator::class, $authenticator); return $authenticator; } /** * @depends testConstructor - * @covers Authenticator::login - * @covers Authenticator::logout * @param Authenticator $authenticator */ public function testLogin(Authenticator $authenticator) @@ -127,4 +126,254 @@ public function testValidateUserAccountWithAccountDisabledException(Authenticato $testUser->save(); $this->invokeMethod($authenticator, 'validateUserAccount', [$testUser->id]); } + + /** + * @depends testConstructor + * @covers Authenticator::login + * @covers Authenticator::loginRememberedUser + * @param Authenticator $authenticator + */ + /*public function testLoginWithRememberMe(Authenticator $authenticator) + { + // Create a test user + $testUser = $this->createTestUser(); + + // Test session to avoid false positive + $key = $this->ci->config['session.keys.current_user_id']; + $this->assertNull($this->ci->session[$key]); + $this->assertNotSame($testUser->id, $this->ci->session[$key]); + + $authenticator->login($testUser, true); + + // Test session to see if user was logged in + $this->assertNotNull($this->ci->session[$key]); + $this->assertSame($testUser->id, $this->ci->session[$key]); + + // We'll manually delete the session, + //$this->ci->session[$key] == null; // $this->session->destroy(); + + // Go througt the loginRememberedUser process + $user = $authenticator->user(); //$this->invokeMethod($authenticator, 'loginRememberedUser'); + Debug::debug("USER ===> "); + Debug::debug($user); + $this->assertSame($testUser->id, $user->id); + $this->assertSame($testUser->id, $this->ci->session[$key]); + + // Must logout to avoid test issue + $authenticator->logout(); + }*/ + + /** + * @depends testConstructor + * @depends testLogin + * @param Authenticator $authenticator + */ + public function testAttempt_withUserName(Authenticator $authenticator) + { + // Create a test user + $testUser = $this->createTestUser(); + + // Faker doesn't hash the password. Let's do that now + $unhashed = $testUser->password; + $testUser->password = Password::hash($testUser->password); + $testUser->save(); + + // Attempt to log him in + $currentUser = $authenticator->attempt('user_name', $testUser->user_name, $unhashed, false); + $this->assertSame($testUser->id, $currentUser->id); + $this->assertFalse($authenticator->viaRemember()); + + // Must logout to avoid test issue + $authenticator->logout(); + } + + /** + * @depends testConstructor + * @depends testAttempt_withUserName + * @param Authenticator $authenticator + */ + public function testAttempt_withEmail(Authenticator $authenticator) + { + // Faker doesn't hash the password. Let's do that now + $password = 'FooBar'; + + // Create a test user + $testUser = $this->createTestUser(false, false, ['password' => Password::hash($password)]); + + // Attempt to log him in + $currentUser = $authenticator->attempt('email', $testUser->email, $password, false); + $this->assertSame($testUser->id, $currentUser->id); + $this->assertFalse($authenticator->viaRemember()); + + // Must logout to avoid test issue + $authenticator->logout(); + } + + /** + * @depends testConstructor + * @depends testAttempt_withUserName + * @expectedException \UserFrosting\Sprinkle\Account\Authenticate\Exception\InvalidCredentialsException + * @param Authenticator $authenticator + */ + public function testAttempt_withNoUser(Authenticator $authenticator) + { + $currentUser = $authenticator->attempt('user_name', 'fooBar', 'barFoo', false); + } + + /** + * @depends testConstructor + * @depends testAttempt_withUserName + * @expectedException \UserFrosting\Sprinkle\Account\Authenticate\Exception\InvalidCredentialsException + * @param Authenticator $authenticator + */ + public function testAttempt_withNoPassword(Authenticator $authenticator) + { + $testUser = $this->createTestUser(false, false, ['password' => '']); + $currentUser = $authenticator->attempt('email', $testUser->email, 'fooBar', false); + } + + /** + * @depends testConstructor + * @depends testAttempt_withUserName + * @expectedException \UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountDisabledException + * @param Authenticator $authenticator + */ + public function testAttempt_withFlagEnabledFalse(Authenticator $authenticator) + { + $password = 'FooBar'; + $testUser = $this->createTestUser(false, false, [ + 'password' => Password::hash($password), + 'flag_enabled' => 0 + ]); + + $currentUser = $authenticator->attempt('user_name', $testUser->user_name, $password, false); + } + + /** + * @depends testConstructor + * @depends testAttempt_withUserName + * @expectedException \UserFrosting\Sprinkle\Account\Authenticate\Exception\AccountNotVerifiedException + * @param Authenticator $authenticator + */ + public function testAttempt_withFlagVerifiedFalse(Authenticator $authenticator) + { + $password = 'FooBar'; + $testUser = $this->createTestUser(false, false, [ + 'password' => Password::hash($password), + 'flag_verified' => 0 + ]); + + $currentUser = $authenticator->attempt('user_name', $testUser->user_name, $password, false); + } + + /** + * @depends testConstructor + * @depends testAttempt_withUserName + * @param Authenticator $authenticator + */ + public function testAttempt_withFlagVerifiedFalseNoEmailVerification(Authenticator $authenticator) + { + // Force email verification to false + $this->ci->config['site.registration.require_email_verification'] = false; + + // Forcing config requires to recreate the authentificator + $authenticator = $this->getAuthenticator(); + + $password = 'FooBar'; + $testUser = $this->createTestUser(false, false, [ + 'password' => Password::hash($password), + 'flag_verified' => 0 + ]); + + $currentUser = $authenticator->attempt('user_name', $testUser->user_name, $password, false); + $this->assertSame($testUser->id, $currentUser->id); + $this->assertFalse($authenticator->viaRemember()); + + // Must logout to avoid test issue + $authenticator->logout(); + } + + /** + * @depends testConstructor + * @depends testAttempt_withUserName + * @expectedException \UserFrosting\Sprinkle\Account\Authenticate\Exception\InvalidCredentialsException + * @param Authenticator $authenticator + */ + public function testAttempt_withBadPassword(Authenticator $authenticator) + { + $password = 'FooBar'; + $testUser = $this->createTestUser(false, false, [ + 'password' => Password::hash($password) + ]); + + $currentUser = $authenticator->attempt('user_name', $testUser->user_name, 'BarFoo', false); + } + + /** + * @depends testConstructor + * @param Authenticator $authenticator + */ + public function testCheckWithNoUser(Authenticator $authenticator) + { + // We don't have a user by default + $this->assertFalse($authenticator->check()); + $this->assertTrue($authenticator->guest()); + } + + /** + * @depends testConstructor + */ + public function testCheckWithLoggedInUser() + { + $testUser = $this->createTestUser(false, true); + $authenticator = $this->getAuthenticator(); + + $this->assertTrue($authenticator->check()); + $this->assertFalse($authenticator->guest()); + $this->assertSame($testUser->id, $authenticator->user()->id); + } + + /** + * @depends testConstructor + * @param Authenticator $authenticator + */ + /*public function testLoginRememberedUser(Authenticator $authenticator) + { + //TODO + }*/ + + /** + * @depends testConstructor + * @param Authenticator $authenticator + */ + /*public function testLoginSessionUser(Authenticator $authenticator) + { + //TODO + }*/ + + /** + * @depends testConstructor + * @param Authenticator $authenticator + */ + /*public function testValidateRememberMeCookie(Authenticator $authenticator) + { + //TODO + }*/ + + /** + * @depends testConstructor + * @param Authenticator $authenticator + */ + /*public function testFlushSessionCache(Authenticator $authenticator) + { + //TODO + }*/ + + /** + * @return Authenticator + */ + protected function getAuthenticator() + { + return new Authenticator($this->ci->classMapper, $this->ci->session, $this->ci->config, $this->ci->cache); + } } diff --git a/app/sprinkles/account/tests/withTestUser.php b/app/sprinkles/account/tests/withTestUser.php index 4528c8cd7..9e37c9e03 100644 --- a/app/sprinkles/account/tests/withTestUser.php +++ b/app/sprinkles/account/tests/withTestUser.php @@ -43,9 +43,10 @@ protected function logoutCurrentUser() * Create a test user with no settings/permissions for a controller test * @param bool $isMaster Does this user have root access? Will bypass all permissions * @param bool $login Login this user, setting him as the currentUser + * @param array $params User account params * @return User */ - protected function createTestUser($isMaster = false, $login = false) + protected function createTestUser($isMaster = false, $login = false, array $params = []) { if ($isMaster) { $user_id = $this->ci->config['reserved_user_ids.master']; @@ -53,8 +54,10 @@ protected function createTestUser($isMaster = false, $login = false) $user_id = rand(0, 1222); } + $params = array_merge(["id" => $user_id], $params); + $fm = $this->ci->factory; - $user = $fm->create(User::class, ["id" => $user_id]); + $user = $fm->create(User::class, $params); if ($login) { $this->loginUser($user); From c8e7a89dfcd0df2ab0ac8c135bfea22a5d5e620a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 16:03:34 -0400 Subject: [PATCH 122/237] Fix bad storage in Authenticator --- .../src/Authenticate/Authenticator.php | 2 +- .../tests/Integration/AuthenticatorTest.php | 38 +------------------ 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index 7c3b3415f..36d116219 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -239,7 +239,7 @@ public function logout($complete = false) // This removes all of the user's persistent logins from the database if ($complete) { - $this->storage->cleanAllTriplets($currentUserId); + $this->rememberMeStorage->cleanAllTriplets($currentUserId); } // Clear the rememberMe cookie diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index 4b5ad66b1..6b72095bd 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -65,7 +65,7 @@ public function testLogin(Authenticator $authenticator) $this->assertSame($testUser->id, $this->ci->session[$key]); // Must logout to avoid test issue - $authenticator->logout(); + $authenticator->logout(true); // We'll test the logout system works too while we're at it (and depend on it) $key = $this->ci->config['session.keys.current_user_id']; @@ -333,42 +333,6 @@ public function testCheckWithLoggedInUser() $this->assertSame($testUser->id, $authenticator->user()->id); } - /** - * @depends testConstructor - * @param Authenticator $authenticator - */ - /*public function testLoginRememberedUser(Authenticator $authenticator) - { - //TODO - }*/ - - /** - * @depends testConstructor - * @param Authenticator $authenticator - */ - /*public function testLoginSessionUser(Authenticator $authenticator) - { - //TODO - }*/ - - /** - * @depends testConstructor - * @param Authenticator $authenticator - */ - /*public function testValidateRememberMeCookie(Authenticator $authenticator) - { - //TODO - }*/ - - /** - * @depends testConstructor - * @param Authenticator $authenticator - */ - /*public function testFlushSessionCache(Authenticator $authenticator) - { - //TODO - }*/ - /** * @return Authenticator */ From 1bd3f3b9e5f8afbc4ffeaf06a3f8eb6c9ec57fe5 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 16:57:21 -0400 Subject: [PATCH 123/237] Travis should now use the defined db for testing --- .travis.yml | 2 +- app/sprinkles/core/config/testing.php | 36 +++++++++++-------- app/sprinkles/core/tests/TestDatabase.php | 3 +- .../core/tests/Unit/TestDatabaseTraitTest.php | 4 +-- build/before_install.sh | 6 ++-- 5 files changed, 29 insertions(+), 22 deletions(-) diff --git a/.travis.yml b/.travis.yml index 01e29f4b8..953401886 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,7 +33,7 @@ before_script: script: # run unit tests - - composer test + - app/vendor/bin/phpunit after_failure: - cat app/log/userfrosting.log diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index bc8efc058..a3b0a9c99 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -15,7 +15,7 @@ ] ], /** - * Use in memory db for testing + * Define in memory db for testing */ 'db' => [ 'test_integration' => [ @@ -29,18 +29,6 @@ 'debug' => [ 'deprecation' => false, ], - /** - * Don't display error detail in test. Return the non formatted errors - */ - 'settings' => [ - 'displayErrorDetails' => false - ], - /** - * Disable native sessions in tests - */ - 'session' => [ - 'handler' => 'array' - ], /** * Use testning filesystem for tests */ @@ -55,6 +43,24 @@ 'driver' => 'localTest', 'root' => \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testingDriver' ], - ] - ] + ] + ], + /** + * Don't display error detail in test. Return the non formatted errors + */ + 'settings' => [ + 'displayErrorDetails' => false + ], + /** + * Disable native sessions in tests + */ + 'session' => [ + 'handler' => 'array' + ], + /** + * Database to use when using the TestDatabase Trait + */ + 'testing' => [ + 'dbConnection' => getenv('TEST_DB') ?: 'test_integration' + ] ]; diff --git a/app/sprinkles/core/tests/TestDatabase.php b/app/sprinkles/core/tests/TestDatabase.php index 4578a07ce..ae8b8dd14 100644 --- a/app/sprinkles/core/tests/TestDatabase.php +++ b/app/sprinkles/core/tests/TestDatabase.php @@ -19,6 +19,7 @@ trait TestDatabase */ public function setupTestDatabase() { - $this->ci->db->getDatabaseManager()->setDefaultConnection('test_integration'); + $connection = $this->ci->config['testing.dbConnection']; + $this->ci->db->getDatabaseManager()->setDefaultConnection($connection); } } diff --git a/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php b/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php index 83e7c7ed0..0ab411e8d 100644 --- a/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php +++ b/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php @@ -31,8 +31,8 @@ public function setUp() */ public function testTrait() { - // Use the test_integration for this test + // Use the testing db for this test $connection = $this->ci->db->getConnection(); - $this->assertEquals('test_integration', $connection->getName()); + $this->assertEquals($this->ci->config['testing.dbConnection'], $connection->getName()); } } diff --git a/build/before_install.sh b/build/before_install.sh index 37d752434..ab0dd5e40 100644 --- a/build/before_install.sh +++ b/build/before_install.sh @@ -16,7 +16,7 @@ if [ "$DB" == "mysql" ] ; then echo "Setting up mysql ..." mysql -u root -e "CREATE DATABASE userfrosting;" mysql -u root -e "GRANT ALL ON userfrosting.* TO 'travis'@'localhost';" - printf "UF_MODE=\"dev\"\nDB_DRIVER=\"mysql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"3306\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"travis\"\nDB_PASSWORD=\"\"\n" > app/.env + printf "UF_MODE=\"dev\"\nDB_DRIVER=\"mysql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"3306\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"travis\"\nDB_PASSWORD=\"\"\nTEST_DB=\"default\"\n" > app/.env fi # @@ -26,7 +26,7 @@ if [ "$DB" == "pgsql" ] ; then echo "Setting up pgsql ..." psql -c "CREATE DATABASE userfrosting;" -U postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE userfrosting TO postgres;" -U postgres - printf "UF_MODE=\"dev\"\nDB_DRIVER=\"pgsql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"5432\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"postgres\"\nDB_PASSWORD=\"\"\n" > app/.env + printf "UF_MODE=\"dev\"\nDB_DRIVER=\"pgsql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"5432\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"postgres\"\nDB_PASSWORD=\"\"\nTEST_DB=\"default\"\n" > app/.env fi # @@ -35,5 +35,5 @@ fi if [ "$DB" == "sqlite" ] ; then echo "Setting up sqlite ..." touch userfrosting.db - printf "UF_MODE=\"dev\"\nDB_DRIVER=\"sqlite\"\nDB_NAME=\"userfrosting.db\"\n" > app/.env + printf "UF_MODE=\"dev\"\nDB_DRIVER=\"sqlite\"\nDB_NAME=\"userfrosting.db\"\nTEST_DB=\"default\"\n" > app/.env fi From add216943e15ae0ed413edb026f63ed8b23724c0 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 17:08:42 -0400 Subject: [PATCH 124/237] Added info about the broken `testLoginWithRememberMe` test --- .../tests/Integration/AuthenticatorTest.php | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index 6b72095bd..ec804cab1 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -127,10 +127,21 @@ public function testValidateUserAccountWithAccountDisabledException(Authenticato $this->invokeMethod($authenticator, 'validateUserAccount', [$testUser->id]); } + /** + * The next test doesn't work with SQLite, as birke/rememberme doesn't look + * compatible with SQLite + * + * Exception : + * Doctrine\DBAL\Driver\PDOException: SQLSTATE[HY000]: General error: 1 no such function: NOW + * app/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:82 + * app/vendor/birke/rememberme/src/Storage/PDOStorage.php:28 + * app/vendor/birke/rememberme/src/Authenticator.php:107 + * app/sprinkles/account/src/Authenticate/Authenticator.php:332 + * app/tests/TestCase.php:182 + * app/sprinkles/account/tests/Integration/AuthenticatorTest.php:161 + */ /** * @depends testConstructor - * @covers Authenticator::login - * @covers Authenticator::loginRememberedUser * @param Authenticator $authenticator */ /*public function testLoginWithRememberMe(Authenticator $authenticator) @@ -150,14 +161,22 @@ public function testValidateUserAccountWithAccountDisabledException(Authenticato $this->assertSame($testUser->id, $this->ci->session[$key]); // We'll manually delete the session, - //$this->ci->session[$key] == null; // $this->session->destroy(); + $this->ci->session[$key] = null; + $this->assertNull($this->ci->session[$key]); + $this->assertNotSame($testUser->id, $this->ci->session[$key]); // Go througt the loginRememberedUser process - $user = $authenticator->user(); //$this->invokeMethod($authenticator, 'loginRememberedUser'); - Debug::debug("USER ===> "); - Debug::debug($user); + // First, we'll simulate a page refresh by creating a new authenticator + $authenticator = $this->getAuthenticator(); + + $user = $authenticator->user(); + //$user = $this->invokeMethod($authenticator, 'loginRememberedUser'); //<-- Use this to see the PDOException + + // If loginRememberedUser returns a PDOException, `user` will return a null user + $this->assertNotNull($user); $this->assertSame($testUser->id, $user->id); $this->assertSame($testUser->id, $this->ci->session[$key]); + $this->assertTrue($authenticator->viaRemember()); // Must logout to avoid test issue $authenticator->logout(); From 5e26f6ed006cbcdfb05d32d76654f6490c4fdada Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 17:11:12 -0400 Subject: [PATCH 125/237] Fix issue with `validateUserAccount` and pgsql --- app/sprinkles/account/src/Authenticate/Authenticator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index 36d116219..a9843211a 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -399,7 +399,7 @@ protected function validateRememberMeCookie() protected function validateUserAccount($userId) { if ($userId) { - $user = $this->classMapper->staticMethod('user', 'find', $userId); + $user = $this->classMapper->staticMethod('user', 'find', (int) $userId); // If the user doesn't exist any more, throw an exception. if (!$user) { From 9755acb8c4c7156ef85dc3c1c4d9e6dc8a6ab3a4 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 17:19:35 -0400 Subject: [PATCH 126/237] Temp fix for broken test in `testLogin` test related to SQLite --- app/sprinkles/account/tests/Integration/AuthenticatorTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index ec804cab1..c45ac1f53 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -65,7 +65,9 @@ public function testLogin(Authenticator $authenticator) $this->assertSame($testUser->id, $this->ci->session[$key]); // Must logout to avoid test issue - $authenticator->logout(true); + $authenticator->logout(); + // $authenticator->logout(true); //<-- Doesn't work with SQLite. Doctrine\DBAL\Driver\PDOException: SQLSTATE[HY000]: General error: 5 database is locked + // Is required to test the `cleanAllTriplets` thing // We'll test the logout system works too while we're at it (and depend on it) $key = $this->ci->config['session.keys.current_user_id']; From ec508e03fc1027d3317eb54721e94ca065b1a2d3 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 17:54:26 -0400 Subject: [PATCH 127/237] Introduce 'debug' as an option for UF_MODE (Close #653) --- CHANGELOG.md | 3 ++- app/sprinkles/account/config/debug.php | 12 ++++++++++++ app/sprinkles/core/config/{dev.php => debug.php} | 7 ++++--- app/sprinkles/core/src/Bakery/SetupEnvCommand.php | 1 + build/before_install.sh | 8 ++++---- 5 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 app/sprinkles/account/config/debug.php rename app/sprinkles/core/config/{dev.php => debug.php} (83%) diff --git a/CHANGELOG.md b/CHANGELOG.md index e88aa6d26..61819a4d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added tests for migrator and it's components - Added tests for `migrate` Bakery command and sub-commands - Added new `filesystem` service ([#869](https://github.com/userfrosting/UserFrosting/pull/869)) -- Added new `Seeder` and `seed` Bakery command +- Added new `Seeder` and `seed` Bakery command ([#653](https://github.com/userfrosting/UserFrosting/pull/653)) ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle @@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Rewrite `AssetLoader` to act as a wrapper for `Assets` - Improved `route:list` Bakery command - Rewritten the `locator` service so it's better suited for sprinkle system +- `dev` environment changed to `debug`. ### Fix - Sprinkle without a `template/` folder won't cause error anymore diff --git a/app/sprinkles/account/config/debug.php b/app/sprinkles/account/config/debug.php new file mode 100644 index 000000000..a93044fe2 --- /dev/null +++ b/app/sprinkles/account/config/debug.php @@ -0,0 +1,12 @@ + [ + 'auth' => true + ], + ]; diff --git a/app/sprinkles/core/config/dev.php b/app/sprinkles/core/config/debug.php similarity index 83% rename from app/sprinkles/core/config/dev.php rename to app/sprinkles/core/config/debug.php index 81f7549a0..0ea1faeb5 100644 --- a/app/sprinkles/core/config/dev.php +++ b/app/sprinkles/core/config/debug.php @@ -13,9 +13,10 @@ 'twig' => false ], 'debug' => [ - 'twig' => true, - 'auth' => true, - 'smtp' => true + 'deprecation' => true, + 'queries' => true, + 'smtp' => true, + 'twig' => true ], // Slim settings - see http://www.slimframework.com/docs/objects/application.html#slim-default-settings 'settings' => [ diff --git a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php index d07cbad16..7430248a0 100644 --- a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php @@ -82,6 +82,7 @@ protected function askForEnv(InputInterface $args) $newEnvMode = $this->io->choice("Environment Mode", [ 'default', 'production', + 'debug', 'Other...' ], 'default'); } diff --git a/build/before_install.sh b/build/before_install.sh index ab0dd5e40..57250a8a7 100644 --- a/build/before_install.sh +++ b/build/before_install.sh @@ -16,7 +16,7 @@ if [ "$DB" == "mysql" ] ; then echo "Setting up mysql ..." mysql -u root -e "CREATE DATABASE userfrosting;" mysql -u root -e "GRANT ALL ON userfrosting.* TO 'travis'@'localhost';" - printf "UF_MODE=\"dev\"\nDB_DRIVER=\"mysql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"3306\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"travis\"\nDB_PASSWORD=\"\"\nTEST_DB=\"default\"\n" > app/.env + printf "UF_MODE=\"debug\"\nDB_DRIVER=\"mysql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"3306\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"travis\"\nDB_PASSWORD=\"\"\nTEST_DB=\"default\"\n" > app/.env fi # @@ -26,14 +26,14 @@ if [ "$DB" == "pgsql" ] ; then echo "Setting up pgsql ..." psql -c "CREATE DATABASE userfrosting;" -U postgres psql -c "GRANT ALL PRIVILEGES ON DATABASE userfrosting TO postgres;" -U postgres - printf "UF_MODE=\"dev\"\nDB_DRIVER=\"pgsql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"5432\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"postgres\"\nDB_PASSWORD=\"\"\nTEST_DB=\"default\"\n" > app/.env + printf "UF_MODE=\"debug\"\nDB_DRIVER=\"pgsql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"5432\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"postgres\"\nDB_PASSWORD=\"\"\nTEST_DB=\"default\"\n" > app/.env fi - +s # # set up sqlite # if [ "$DB" == "sqlite" ] ; then echo "Setting up sqlite ..." touch userfrosting.db - printf "UF_MODE=\"dev\"\nDB_DRIVER=\"sqlite\"\nDB_NAME=\"userfrosting.db\"\nTEST_DB=\"default\"\n" > app/.env + printf "UF_MODE=\"debug\"\nDB_DRIVER=\"sqlite\"\nDB_NAME=\"userfrosting.db\"\nTEST_DB=\"default\"\n" > app/.env fi From e7ac1d07c7bf84269fcbad252a5a93dbe4094db7 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 18:16:50 -0400 Subject: [PATCH 128/237] redirect failing in UserController::pageInfo when user not found (resolve #888) (user Dilaz in #laravel was wrong) --- CHANGELOG.md | 5 +++-- .../account/src/Controller/AccountController.php | 10 ++++------ .../account/src/ServicesProvider/ServicesProvider.php | 2 +- app/sprinkles/admin/src/Controller/GroupController.php | 2 +- app/sprinkles/admin/src/Controller/RoleController.php | 2 +- app/sprinkles/admin/src/Controller/UserController.php | 2 +- 6 files changed, 11 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 61819a4d7..050e69af5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added tests for migrator and it's components - Added tests for `migrate` Bakery command and sub-commands - Added new `filesystem` service ([#869](https://github.com/userfrosting/UserFrosting/pull/869)) -- Added new `Seeder` and `seed` Bakery command ([#653](https://github.com/userfrosting/UserFrosting/pull/653)) +- Added new `Seeder` and `seed` Bakery command ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle @@ -34,11 +34,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Rewrite `AssetLoader` to act as a wrapper for `Assets` - Improved `route:list` Bakery command - Rewritten the `locator` service so it's better suited for sprinkle system -- `dev` environment changed to `debug`. +- `dev` environment changed to `debug` ([#653](https://github.com/userfrosting/UserFrosting/pull/653)) ### Fix - Sprinkle without a `template/` folder won't cause error anymore - Fixed routes not available in Tests [and Bakery] ([#854](https://github.com/userfrosting/UserFrosting/pull/854)) +- redirect failing in UserController::pageInfo when user not found ([#888](https://github.com/userfrosting/UserFrosting/pull/888)) ### Deprecated - Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration` diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 5db626be3..7f2e48d55 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -143,15 +143,14 @@ public function denyResetPassword(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); - // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel - return $response->withRedirect($loginPage, 400); + return $response->withRedirect($loginPage); } $passwordReset = $this->ci->repoPasswordReset->cancel($data['token']); if (!$passwordReset) { $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID'); - return $response->withRedirect($loginPage, 400); + return $response->withRedirect($loginPage); } $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_CANNED'); @@ -1262,15 +1261,14 @@ public function verify(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); - // 400 code + redirect is perfectly fine, according to user Dilaz in #laravel - return $response->withRedirect($loginPage, 400); + return $response->withRedirect($loginPage); } $verification = $this->ci->repoVerification->complete($data['token']); if (!$verification) { $ms->addMessageTranslated('danger', 'ACCOUNT.VERIFICATION.TOKEN_NOT_FOUND'); - return $response->withRedirect($loginPage, 400); + return $response->withRedirect($loginPage); } $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.COMPLETE'); diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index d4f2df469..e6346dfcd 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -373,7 +373,7 @@ public function register(ContainerInterface $container) return function (Request $request, Response $response, array $args) use ($c) { $redirect = $c->router->pathFor('dashboard'); - return $response->withRedirect($redirect, 302); + return $response->withRedirect($redirect); }; }; diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index f5a14f940..efb677fd0 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -546,7 +546,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the group no longer exists, forward to main group listing page if (!$group) { $redirectPage = $this->ci->router->pathFor('uri_groups'); - return $response->withRedirect($redirectPage, 404); + return $response->withRedirect($redirectPage); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index 316c26933..2ba2d04e0 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -652,7 +652,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the role no longer exists, forward to main role listing page if (!$role) { $redirectPage = $this->ci->router->pathFor('uri_roles'); - return $response->withRedirect($redirectPage, 404); + return $response->withRedirect($redirectPage); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index 9eebf5956..d24f0cfbd 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -909,7 +909,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the user no longer exists, forward to main user listing page if (!$user) { $usersPage = $this->ci->router->pathFor('uri_users'); - return $response->withRedirect($usersPage, 404); + return $response->withRedirect($usersPage); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ From 3496710aa0f25b01e139faa91c37237ed3de4950 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 3 Nov 2018 18:28:27 -0400 Subject: [PATCH 129/237] Updated develop changelog --- CHANGELOG.md | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 050e69af5..9b98f7e61 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added -- Use locale requested by browser when possible for guests ([#718](https://github.com/userfrosting/UserFrosting/pull/718)) -- Add locale drop down to registration page, with the currently applied locale selected ([#718](https://github.com/userfrosting/UserFrosting/pull/718)) +- Use locale requested by browser when possible for guests ([#718](https://github.com/userfrosting/UserFrosting/issues/718)) +- Add locale drop down to registration page, with the currently applied locale selected ([#718](https://github.com/userfrosting/UserFrosting/issues/718)) - Integrated improvements from [v4.0.25-Alpha](#v4025-alpha) - Added `database` option for `migrate` and `migrate:*` Bakery commands - New `isProduction` method for Bakery command to test if app is in production mode @@ -18,34 +18,40 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `RefreshDatabase` test Trait to use a fresh database for a test - Added `TestDatabase` test Trait to use the in memory database for a test - Implement `withRaw`, `withSum`, `withAvg`, `withMin`, `withMax` (see https://github.com/laravel/framework/pull/16815) -- Include Vagrant integration directly inside UF ([#829](https://github.com/userfrosting/UserFrosting/pull/829)) -- Added arguments to the `create-admin` and `setup` Bakery commands so it can be used in a non-interactive way ([#808](https://github.com/userfrosting/UserFrosting/pull/808)) +- Include Vagrant integration directly inside UF ([#829](https://github.com/userfrosting/UserFrosting/issues/829)) +- Added arguments to the `create-admin` and `setup` Bakery commands so it can be used in a non-interactive way ([#808](https://github.com/userfrosting/UserFrosting/issues/808)) - Added tests for migrator and it's components - Added tests for `migrate` Bakery command and sub-commands -- Added new `filesystem` service ([#869](https://github.com/userfrosting/UserFrosting/pull/869)) +- Added new `filesystem` service ([#869](https://github.com/userfrosting/UserFrosting/issues/869)) - Added new `Seeder` and `seed` Bakery command +- Added `withTestUser` trait for helper methods when running tests requiring a user +- Added `ControllerTestCase` special test case to help testing controllers +- Improved overall test coverage and added coverage config to `phpunit.xml` ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle -- Re-written the migrator. It is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider ([#795](https://github.com/userfrosting/UserFrosting/pull/795)) +- Re-written the migrator. It is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider ([#795](https://github.com/userfrosting/UserFrosting/issues/795)) - Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace -- Move User registration out of the `AccountController` ([#793](https://github.com/userfrosting/UserFrosting/pull/793)) +- Move User registration out of the `AccountController` ([#793](https://github.com/userfrosting/UserFrosting/issues/793)) - Temporarily undeprecate `AssetLoader` until the new asset system can be refactored (https://github.com/userfrosting/assets/issues/4) - Rewrite `AssetLoader` to act as a wrapper for `Assets` -- Improved `route:list` Bakery command -- Rewritten the `locator` service so it's better suited for sprinkle system -- `dev` environment changed to `debug` ([#653](https://github.com/userfrosting/UserFrosting/pull/653)) +- Improved `route:list` Bakery command from [v4.1.20](#v4.1.20) +- Rewritten the `locator` service so it's better suited for sprinkle system ([#853](https://github.com/userfrosting/UserFrosting/issues/853)) +- `dev` environment changed to `debug` ([#653](https://github.com/userfrosting/UserFrosting/issues/653)) +- Changed deprecations to `warning`, and suppressed them in tests ### Fix - Sprinkle without a `template/` folder won't cause error anymore -- Fixed routes not available in Tests [and Bakery] ([#854](https://github.com/userfrosting/UserFrosting/pull/854)) -- redirect failing in UserController::pageInfo when user not found ([#888](https://github.com/userfrosting/UserFrosting/pull/888)) +- Fixed routes not available in Tests [and Bakery] ([#854](https://github.com/userfrosting/UserFrosting/issues/854)) +- redirect failing in UserController::pageInfo when user not found ([#888](https://github.com/userfrosting/UserFrosting/issues/888)) +- Fix WhoopsRenderer integration, resolving a temp fix in [v4.1.21](#v4.1.21). +- Fix Travis not running tests with the env database ### Deprecated - Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration` - Migrations dependencies property should now be a static property - Deprecated migration `seed` method. Database seeding should now be done using the new Seeder -- Trait `\UserFrosting\Tests\DatabaseTransactions` has been deprecated. Tests should now use the `\UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` trait instead. ([#826](https://github.com/userfrosting/UserFrosting/pull/826)) +- Trait `\UserFrosting\Tests\DatabaseTransactions` has been deprecated. Tests should now use the `\UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` trait instead. ([#826](https://github.com/userfrosting/UserFrosting/issues/826)) ### Removed - The console IO instance is not available anymore in migrations From 32b3046328efa594f2d0e62eb66d15bff34b1055 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 5 Nov 2018 20:19:15 -0500 Subject: [PATCH 130/237] Implement UserInterface (Resolve #769) --- .../account/src/Account/Registration.php | 8 +- .../src/Authenticate/Authenticator.php | 18 +- .../Authorize/AccessConditionExpression.php | 8 +- .../src/Authorize/AuthorizationManager.php | 6 +- .../src/Controller/AccountController.php | 9 +- .../Models/Interfaces/UserInterface.php | 162 ++++++++++++++++++ .../account/src/Database/Models/User.php | 3 +- .../src/Repository/TokenRepository.php | 18 +- .../src/ServicesProvider/ServicesProvider.php | 2 +- .../account/tests/Unit/FactoriesTest.php | 2 +- .../account/tests/Unit/RegistrationTest.php | 4 +- app/sprinkles/account/tests/withTestUser.php | 17 +- .../src/Controller/ActivityController.php | 4 +- .../admin/src/Controller/AdminController.php | 6 +- .../admin/src/Controller/GroupController.php | 22 +-- .../src/Controller/PermissionController.php | 10 +- .../admin/src/Controller/RoleController.php | 28 +-- .../admin/src/Controller/UserController.php | 34 ++-- .../tests/Integration/AdminControllerTest.php | 11 +- 19 files changed, 267 insertions(+), 105 deletions(-) create mode 100644 app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php diff --git a/app/sprinkles/account/src/Account/Registration.php b/app/sprinkles/account/src/Account/Registration.php index f88a3ce35..acf183da0 100644 --- a/app/sprinkles/account/src/Account/Registration.php +++ b/app/sprinkles/account/src/Account/Registration.php @@ -13,7 +13,7 @@ use UserFrosting\Sprinkle\Core\Mail\EmailRecipient; use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage; use UserFrosting\Support\Exception\HttpException; -use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; /** * Handles user registration tasks. @@ -80,7 +80,7 @@ public function __construct(ContainerInterface $ci, $userdata = []) /** * Register a new user * - * @return \UserFrosting\Sprinkle\Account\Database\Models\User The created user + * @return UserInterface The created user */ public function register() { @@ -223,9 +223,9 @@ protected function setDefaults() /** * Send verification email for specified user * - * @param User $user The user to send the email for + * @param UserInterface $user The user to send the email for */ - protected function sendVerificationEmail(User $user) + protected function sendVerificationEmail(UserInterface $user) { // Try to generate a new verification request $verification = $this->ci->repoVerification->create($user, $this->ci->config['verification.timeout']); diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index a9843211a..d3e15a539 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -19,7 +19,7 @@ use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthCompromisedException; use UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException; use UserFrosting\Sprinkle\Account\Authenticate\Exception\InvalidCredentialsException; -use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Core\Util\ClassMapper; use UserFrosting\Support\Repository\Repository as Config; @@ -68,7 +68,7 @@ class Authenticator protected $rememberMe; /** - * @var User + * @var UserInterface */ protected $user; @@ -133,7 +133,7 @@ public function __construct(ClassMapper $classMapper, Session $session, Config $ * @param string $identityValue * @param string $password * @param bool $rememberMe - * @return User + * @return UserInterface */ public function attempt($identityColumn, $identityValue, $password, $rememberMe = false) { @@ -193,12 +193,12 @@ public function guest() * Process an account login request. * * This method logs in the specified user, allowing the client to assume the user's identity for the duration of the session. - * @param User $user The user to log in. + * @param UserInterface $user The user to log in. * @param bool $rememberMe Set to true to make this a "persistent session", i.e. one that will re-login even after the session expires. * @todo Figure out a way to update the currentUser service to reflect the logged-in user *immediately* in the service provider. * As it stands, the currentUser service will still reflect a "guest user" for the remainder of the request. */ - public function login($user, $rememberMe = false) + public function login(UserInterface $user, $rememberMe = false) { $oldId = session_id(); $this->session->regenerateId(true); @@ -272,7 +272,7 @@ public function logout($complete = false) * Try to get the currently authenticated user, returning a guest user if none was found. * * Tries to re-establish a session for "remember-me" users who have been logged out due to an expired session. - * @return User|null + * @return UserInterface|null * @throws AuthExpiredException * @throws AuthCompromisedException * @throws AccountInvalidException @@ -323,7 +323,7 @@ public function viaRemember() * Attempt to log in the client from their rememberMe token (in their cookie). * * @throws AuthCompromisedException The client attempted to log in with an invalid rememberMe token. - * @return User|bool If successful, the User object of the remembered user. Otherwise, return false. + * @return UserInterface|bool If successful, the User object of the remembered user. Otherwise, return false. */ protected function loginRememberedUser() { @@ -350,7 +350,7 @@ protected function loginRememberedUser() * Attempt to log in the client from the session. * * @throws AuthExpiredException The client attempted to use an expired rememberMe token. - * @return User|null If successful, the User object of the user in session. Otherwise, return null. + * @return UserInterface|null If successful, the User object of the user in session. Otherwise, return null. */ protected function loginSessionUser() { @@ -392,7 +392,7 @@ protected function validateRememberMeCookie() * * Checks that the account is valid and enabled, throwing an exception if not. * @param int $userId - * @return User|null + * @return UserInterface|null * @throws AccountInvalidException * @throws AccountDisabledException */ diff --git a/app/sprinkles/account/src/Authorize/AccessConditionExpression.php b/app/sprinkles/account/src/Authorize/AccessConditionExpression.php index ec9ea2e34..6378d271c 100644 --- a/app/sprinkles/account/src/Authorize/AccessConditionExpression.php +++ b/app/sprinkles/account/src/Authorize/AccessConditionExpression.php @@ -13,7 +13,7 @@ use PhpParser\Parser as Parser; use PhpParser\PrettyPrinter\Standard as StandardPrettyPrinter; use PhpParser\Error as PhpParserException; -use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; /** * AccessConditionExpression class @@ -26,7 +26,7 @@ class AccessConditionExpression { /** - * @var User A user object, which for convenience can be referenced as 'self' in access conditions. + * @var UserInterface A user object, which for convenience can be referenced as 'self' in access conditions. */ protected $user; @@ -64,11 +64,11 @@ class AccessConditionExpression * Create a new AccessConditionExpression object. * * @param ParserNodeFunctionEvaluator $nodeVisitor - * @param User $user A user object, which for convenience can be referenced as 'self' in access conditions. + * @param UserInterface $user A user object, which for convenience can be referenced as 'self' in access conditions. * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. * @param bool $debug Set to true if you want debugging information printed to the auth log. */ - public function __construct(ParserNodeFunctionEvaluator $nodeVisitor, User $user, Logger $logger, $debug = false) + public function __construct(ParserNodeFunctionEvaluator $nodeVisitor, UserInterface $user, Logger $logger, $debug = false) { $this->nodeVisitor = $nodeVisitor; $this->user = $user; diff --git a/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/app/sprinkles/account/src/Authorize/AuthorizationManager.php index 8f6606f31..65bea8305 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationManager.php @@ -8,7 +8,7 @@ namespace UserFrosting\Sprinkle\Account\Authorize; use Interop\Container\ContainerInterface; -use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; /** * AuthorizationManager class. @@ -68,7 +68,7 @@ public function getCallbacks() * * Determine if this user has access to the given $slug under the given $params. * - * @param User|null $user + * @param UserInterface|null $user * @param string $slug The permission slug to check for access. * @param array $params An array of field names => values, specifying any additional data to provide the authorization module * when determining whether or not this user has access. @@ -78,7 +78,7 @@ public function checkAccess($user, $slug, array $params = []) { $debug = $this->ci->config['debug.auth']; - if (is_null($user) || !($user instanceof User)) { + if (is_null($user) || !($user instanceof UserInterface)) { if ($debug) { $this->ci->authLogger->debug("No user defined. Access denied."); } diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 7f2e48d55..4c6b95fdc 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -322,7 +322,7 @@ public function login(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ @@ -471,6 +471,7 @@ public function pageRegister(Request $request, Response $response, $args) { /** @var \UserFrosting\Support\Repository\Repository $config */ $config = $this->ci->config; + /** @var \UserFrosting\I18n\LocalePathBuilder */ $localePathBuilder = $this->ci->localePathBuilder; @@ -623,7 +624,7 @@ public function pageSettings(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -723,7 +724,7 @@ public function profile(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access control for entire resource - check that the current user has permission to modify themselves @@ -1109,7 +1110,7 @@ public function settings(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access control for entire resource - check that the current user has permission to modify themselves diff --git a/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php b/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php new file mode 100644 index 000000000..8d71fbc16 --- /dev/null +++ b/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php @@ -0,0 +1,162 @@ +full_name` + * + * @return string + */ + public function getFullNameAttribute(); + + /** + * Retrieve the cached permissions dictionary for this user. + * + * @return array + */ + public function getCachedPermissions(); + + /** + * Retrieve the cached permissions dictionary for this user. + * + * @return User + */ + public function reloadCachedPermissions(); + + /** + * Get the amount of time, in seconds, that has elapsed since the last activity of a certain time for this user. + * + * @param string $type The type of activity to search for. + * @return int + */ + public function getSecondsSinceLastActivity($type); + + /** + * Return this user's group. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function group(); + + /** + * Returns whether or not this user is the master user. + * + * @return bool + */ + public function isMaster(); + + /** + * Get the most recent activity for this user, based on the user's last_activity_id. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsTo + */ + public function lastActivity(); + + /** + * Find the most recent activity for this user of a particular type. + * + * @param string $type + * @return \Illuminate\Database\Eloquent\Builder + */ + public function lastActivityOfType($type = null); + + /** + * Get the most recent time for a specified activity type for this user. + * + * @param string $type + * @return string|null The last activity time, as a SQL formatted time (YYYY-MM-DD HH:MM:SS), or null if an activity of this type doesn't exist. + */ + public function lastActivityTime($type); + + /** + * Performs tasks to be done after this user has been successfully authenticated. + * + * By default, adds a new sign-in activity and updates any legacy hash. + * @param mixed[] $params Optional array of parameters used for this event handler. + * @todo Transition to Laravel Event dispatcher to handle this + */ + public function onLogin($params = []); + + /** + * Performs tasks to be done after this user has been logged out. + * + * By default, adds a new sign-out activity. + * @param mixed[] $params Optional array of parameters used for this event handler. + * @todo Transition to Laravel Event dispatcher to handle this + */ + public function onLogout($params = []); + + /** + * Get all password reset requests for this user. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function passwordResets(); + + /** + * Get all of the permissions this user has, via its roles. + * + * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough + */ + public function permissions(); + + /** + * Get all roles to which this user belongs. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function roles(); + + /** + * Query scope to get all users who have a specific role. + * + * @param Builder $query + * @param int $roleId + * @return Builder + */ + public function scopeForRole($query, $roleId); + + /** + * Joins the user's most recent activity directly, so we can do things like sort, search, paginate, etc. + * + * @param Builder $query + * @return Builder + */ + public function scopeJoinLastActivity($query); +} diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index 138b242b3..95b6c13d2 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -10,6 +10,7 @@ use Carbon\Carbon; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletes; +use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; use UserFrosting\Sprinkle\Account\Facades\Password; use UserFrosting\Sprinkle\Core\Database\Models\Model; use UserFrosting\Sprinkle\Core\Facades\Debug; @@ -36,7 +37,7 @@ * @property string password * @property timestamp deleted_at */ -class User extends Model +class User extends Model implements UserInterface { use SoftDeletes; diff --git a/app/sprinkles/account/src/Repository/TokenRepository.php b/app/sprinkles/account/src/Repository/TokenRepository.php index 35a886ddc..82dc12494 100644 --- a/app/sprinkles/account/src/Repository/TokenRepository.php +++ b/app/sprinkles/account/src/Repository/TokenRepository.php @@ -8,7 +8,7 @@ namespace UserFrosting\Sprinkle\Account\Repository; use Carbon\Carbon; -use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; use UserFrosting\Sprinkle\Core\Database\Models\Model; use UserFrosting\Sprinkle\Core\Util\ClassMapper; @@ -119,11 +119,11 @@ public function complete($token, $userParams = []) /** * Create a new token for a specified user. * - * @param User $user The user object to associate with this token. + * @param UserInterface $user The user object to associate with this token. * @param int $timeout The time, in seconds, after which this token should expire. * @return Model The model (PasswordReset, Verification, etc) object that stores the token. */ - public function create(User $user, $timeout) + public function create(UserInterface $user, $timeout) { // Remove any previous tokens for this user $this->removeExisting($user); @@ -155,11 +155,11 @@ public function create(User $user, $timeout) /** * Determine if a specified user has an incomplete and unexpired token. * - * @param User $user The user object to look up. + * @param UserInterface $user The user object to look up. * @param int $token Optionally, try to match a specific token. * @return Model|false */ - public function exists(User $user, $token = null) + public function exists(UserInterface $user, $token = null) { $model = $this->classMapper ->staticMethod($this->modelIdentifier, 'where', 'user_id', $user->id) @@ -178,10 +178,10 @@ public function exists(User $user, $token = null) /** * Delete all existing tokens from the database for a particular user. * - * @param User $user + * @param UserInterface $user * @return int */ - protected function removeExisting(User $user) + protected function removeExisting(UserInterface $user) { return $this->classMapper ->staticMethod($this->modelIdentifier, 'where', 'user_id', $user->id) @@ -222,9 +222,9 @@ protected function generateRandomToken($gen = null) * Modify the user during the token completion process. * * This method is called during complete(), and is a way for concrete implementations to modify the user. - * @param User $user the user object to modify. + * @param UserInterface $user the user object to modify. * @param mixed[] $args * @return mixed[] $args the list of parameters that were supplied to the call to `complete()` */ - abstract protected function updateUser($user, $args); + abstract protected function updateUser(UserInterface $user, $args); } diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index e6346dfcd..94946fad8 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -331,7 +331,7 @@ public function register(ContainerInterface $container) /** * Loads the User object for the currently logged-in user. * - * @return \UserFrosting\Sprinkle\Account\Database\Models\User + * @return \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface */ $container['currentUser'] = function ($c) { $authenticator = $c->authenticator; diff --git a/app/sprinkles/account/tests/Unit/FactoriesTest.php b/app/sprinkles/account/tests/Unit/FactoriesTest.php index 19b8fd284..7be1843e8 100644 --- a/app/sprinkles/account/tests/Unit/FactoriesTest.php +++ b/app/sprinkles/account/tests/Unit/FactoriesTest.php @@ -41,6 +41,6 @@ public function testUserFactory() $fm = $this->ci->factory; $user = $fm->create('UserFrosting\Sprinkle\Account\Database\Models\User'); - $this->assertInstanceOf('UserFrosting\Sprinkle\Account\Database\Models\User', $user); + $this->assertInstanceOf('UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface', $user); } } diff --git a/app/sprinkles/account/tests/Unit/RegistrationTest.php b/app/sprinkles/account/tests/Unit/RegistrationTest.php index f36c0ab4a..06cc18f38 100644 --- a/app/sprinkles/account/tests/Unit/RegistrationTest.php +++ b/app/sprinkles/account/tests/Unit/RegistrationTest.php @@ -12,7 +12,7 @@ use UserFrosting\Sprinkle\Core\Tests\TestDatabase; use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; use UserFrosting\Sprinkle\Account\Account\Registration; -use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; use UserFrosting\Support\Exception\HttpException; /** @@ -71,7 +71,7 @@ public function testNormalRegistration() $user = $registration->register(); // Registration should return a valid user - $this->assertInstanceOf(User::class, $user); + $this->assertInstanceOf(UserInterface::class, $user); $this->assertEquals('FooBar', $user->user_name); // We try to register the same user again. Should throw an error diff --git a/app/sprinkles/account/tests/withTestUser.php b/app/sprinkles/account/tests/withTestUser.php index 9e37c9e03..ab0730aac 100644 --- a/app/sprinkles/account/tests/withTestUser.php +++ b/app/sprinkles/account/tests/withTestUser.php @@ -8,6 +8,7 @@ namespace UserFrosting\Sprinkle\Account\Tests; use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; use UserFrosting\Sprinkle\Account\Database\Models\Permission; use UserFrosting\Sprinkle\Account\Database\Models\Role; @@ -18,9 +19,9 @@ trait withTestUser { /** - * @param User $user + * @param UserInterface $user */ - protected function loginUser(User $user) + protected function loginUser(UserInterface $user) { $this->ci->currentUser = $user; $this->ci->authenticator->login($user); @@ -68,12 +69,12 @@ protected function createTestUser($isMaster = false, $login = false, array $para /** * Gives a user a new test permission - * @param User $user + * @param UserInterface $user * @param string $slug * @param string $conditions * @return Permission */ - protected function giveUserTestPermission(User $user, $slug, $conditions = "always()") + protected function giveUserTestPermission(UserInterface $user, $slug, $conditions = "always()") { /** @var \League\FactoryMuffin\FactoryMuffin $fm **/ $fm = $this->ci->factory; @@ -91,11 +92,11 @@ protected function giveUserTestPermission(User $user, $slug, $conditions = "alwa /** * Add the test permission to a Role, then the role to the user - * @param User $user - * @param Permission $permission - * @return Role The intermidiate role + * @param UserInterface $user + * @param Permission $permission + * @return Role The intermidiate role */ - protected function giveUserPermission(User $user, Permission $permission) + protected function giveUserPermission(UserInterface $user, Permission $permission) { /** @var \League\FactoryMuffin\FactoryMuffin $fm **/ $fm = $this->ci->factory; diff --git a/app/sprinkles/admin/src/Controller/ActivityController.php b/app/sprinkles/admin/src/Controller/ActivityController.php index 822b1f7fc..5e4d573d1 100644 --- a/app/sprinkles/admin/src/Controller/ActivityController.php +++ b/app/sprinkles/admin/src/Controller/ActivityController.php @@ -37,7 +37,7 @@ public function getList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -73,7 +73,7 @@ public function pageList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page diff --git a/app/sprinkles/admin/src/Controller/AdminController.php b/app/sprinkles/admin/src/Controller/AdminController.php index 1af8b7e85..08b00e8c2 100644 --- a/app/sprinkles/admin/src/Controller/AdminController.php +++ b/app/sprinkles/admin/src/Controller/AdminController.php @@ -34,7 +34,7 @@ public function pageDashboard(Request $request, Response $response, $args) //** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -104,7 +104,7 @@ public function clearCache(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -138,7 +138,7 @@ public function getModalConfirmClearCache(Request $request, Response $response, /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index efb677fd0..21fddbda7 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -51,7 +51,7 @@ public function create(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -151,7 +151,7 @@ public function delete(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -224,7 +224,7 @@ public function getInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -272,7 +272,7 @@ public function getList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -315,7 +315,7 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -364,7 +364,7 @@ public function getModalCreate(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; /** @var \UserFrosting\I18n\MessageTranslator $translator */ @@ -438,7 +438,7 @@ public function getModalEdit(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; /** @var \UserFrosting\I18n\MessageTranslator $translator */ @@ -501,7 +501,7 @@ public function getUsers(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -552,7 +552,7 @@ public function pageInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -622,7 +622,7 @@ public function pageList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -693,7 +693,7 @@ public function updateInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit submitted fields for this group diff --git a/app/sprinkles/admin/src/Controller/PermissionController.php b/app/sprinkles/admin/src/Controller/PermissionController.php index cfeb5f02a..0b9490463 100644 --- a/app/sprinkles/admin/src/Controller/PermissionController.php +++ b/app/sprinkles/admin/src/Controller/PermissionController.php @@ -37,7 +37,7 @@ public function getInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -85,7 +85,7 @@ public function getList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -123,7 +123,7 @@ public function getUsers(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -165,7 +165,7 @@ public function pageInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -208,7 +208,7 @@ public function pageList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index 2ba2d04e0..6f10ebfc5 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -51,7 +51,7 @@ public function create(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -151,7 +151,7 @@ public function delete(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -223,7 +223,7 @@ public function getInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -271,7 +271,7 @@ public function getList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -314,7 +314,7 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -373,7 +373,7 @@ public function getModalCreate(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; /** @var \UserFrosting\I18n\MessageTranslator $translator */ @@ -445,7 +445,7 @@ public function getModalEdit(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; /** @var \UserFrosting\I18n\MessageTranslator $translator */ @@ -512,7 +512,7 @@ public function getModalEditPermissions(Request $request, Response $response, $a /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit "permissions" field for this role @@ -556,7 +556,7 @@ public function getPermissions(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -610,7 +610,7 @@ public function getUsers(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -658,7 +658,7 @@ public function pageInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -728,7 +728,7 @@ public function pageList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -799,7 +799,7 @@ public function updateInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit submitted fields for this role @@ -892,7 +892,7 @@ public function updateField(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit the specified field for this user diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index d24f0cfbd..e7f6b73c6 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -55,7 +55,7 @@ public function create(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -196,7 +196,7 @@ public function createPasswordReset(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit "password" for this user @@ -268,7 +268,7 @@ public function delete(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -342,7 +342,7 @@ public function getActivities(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -397,7 +397,7 @@ public function getInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -433,7 +433,7 @@ public function getList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -479,7 +479,7 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -530,7 +530,7 @@ public function getModalCreate(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; /** @var \UserFrosting\I18n\MessageTranslator $translator */ @@ -635,7 +635,7 @@ public function getModalEdit(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit basic fields "name", "email", "locale" for this user @@ -720,7 +720,7 @@ public function getModalEditPassword(Request $request, Response $response, $args /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit "password" field for this user @@ -771,7 +771,7 @@ public function getModalEditRoles(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit "roles" field for this user @@ -814,7 +814,7 @@ public function getPermissions(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -867,7 +867,7 @@ public function getRoles(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -915,7 +915,7 @@ public function pageInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -1042,7 +1042,7 @@ public function pageList(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled page @@ -1118,7 +1118,7 @@ public function updateInfo(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit submitted fields for this user @@ -1211,7 +1211,7 @@ public function updateField(Request $request, Response $response, $args) /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ $authorizer = $this->ci->authorizer; - /** @var \UserFrosting\Sprinkle\Account\Database\Models\User $currentUser */ + /** @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface $currentUser */ $currentUser = $this->ci->currentUser; // Access-controlled resource - check that currentUser has permission to edit the specified field for this user diff --git a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php index 651a1d34b..4106ea975 100644 --- a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php +++ b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php @@ -27,7 +27,7 @@ public function testControllerConstructor() * @depends testControllerConstructor * @expectedException \UserFrosting\Support\Exception\ForbiddenException */ - public function testPageDashboard_NullUser() + public function testPageDashboard_GuestUser() { $controller = $this->getController(); $controller->pageDashboard($this->getRequest(), $this->getResponse(), []); @@ -40,8 +40,7 @@ public function testPageDashboard_NullUser() public function testPageDashboard_ForbiddenException() { // Non admin user, won't have access - $testUser = $this->createTestUser(); - $this->loginUser($testUser); + $testUser = $this->createTestUser(false, true); // Get controller $controller = $this->getController(); @@ -54,8 +53,7 @@ public function testPageDashboard_ForbiddenException() public function testPageDashboard() { // Admin user, WILL have access - $testUser = $this->createTestUser(true); - $this->loginUser($testUser); + $testUser = $this->createTestUser(true, true); // Get controller $controller = $this->getController(); @@ -72,8 +70,7 @@ public function testPageDashboard() public function testClearCache() { // Admin user, WILL have access - $testUser = $this->createTestUser(true); - $this->loginUser($testUser); + $testUser = $this->createTestUser(true, true); // Get controller $controller = $this->getController(); From 390a3a05644ab06205c945427471bb651e88288c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 5 Nov 2018 20:50:02 -0500 Subject: [PATCH 131/237] Add warning in Bakery when using soon to be unsupported PHP version --- app/defines.php | 1 + app/sprinkles/core/src/Bakery/DebugCommand.php | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/app/defines.php b/app/defines.php index f7f22a03e..cb0724681 100755 --- a/app/defines.php +++ b/app/defines.php @@ -6,6 +6,7 @@ define('UserFrosting\VERSION', '4.2.0-alpha.1'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); +define('UserFrosting\PHP_RECOMMENDED_VERSION', '7.1'); define('UserFrosting\DEBUG_CONFIG', false); // Directories and Paths diff --git a/app/sprinkles/core/src/Bakery/DebugCommand.php b/app/sprinkles/core/src/Bakery/DebugCommand.php index a8ac3c8a4..9608019a6 100644 --- a/app/sprinkles/core/src/Bakery/DebugCommand.php +++ b/app/sprinkles/core/src/Bakery/DebugCommand.php @@ -69,6 +69,11 @@ protected function checkPhpVersion() $this->io->error("UserFrosting requires php version ".\UserFrosting\PHP_MIN_VERSION." or above. You'll need to update you PHP version before you can continue."); exit(1); } + + // Check for deprecated versions + if (version_compare(phpversion(), \UserFrosting\PHP_RECOMMENDED_VERSION, '<')) { + $this->io->warning("While your PHP version is still supported by UserFrosting, we recommends version ".\UserFrosting\PHP_RECOMMENDED_VERSION." or above as ".phpversion()." will soon be unsupported. See http://php.net/supported-versions.php for more info."); + } } /** From 32e646521e6a3e90685a5661580cbcb751bb15b6 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 5 Nov 2018 21:48:09 -0500 Subject: [PATCH 132/237] POST, PUT, and DELETE methods should always return valid JSON (#757) --- .../src/Controller/AccountController.php | 52 +++++++++---------- .../admin/src/Controller/GroupController.php | 10 ++-- .../admin/src/Controller/RoleController.php | 12 ++--- .../admin/src/Controller/UserController.php | 14 ++--- 4 files changed, 44 insertions(+), 44 deletions(-) diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 4c6b95fdc..c4abfadbd 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -84,7 +84,7 @@ public function checkUsername(Request $request, Response $response, $args) // Throttle requests if ($delay > 0) { - return $response->withStatus(429); + return $response->withJson([], 429); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -203,7 +203,7 @@ public function forgotPassword(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); - return $response->withStatus(400); + return $response->withJson([], 400); } // Throttle requests @@ -218,7 +218,7 @@ public function forgotPassword(Request $request, Response $response, $args) if ($delay > 0) { $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); - return $response->withStatus(429); + return $response->withJson([], 429); } // All checks passed! log events/activities, update user, and send email @@ -255,7 +255,7 @@ public function forgotPassword(Request $request, Response $response, $args) // TODO: create delay to prevent timing-based attacks $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', ['email' => $data['email']]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -331,7 +331,7 @@ public function login(Request $request, Response $response, $args) // Return 200 success if user is already logged in if ($authenticator->check()) { $ms->addMessageTranslated('warning', 'LOGIN.ALREADY_COMPLETE'); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @var \UserFrosting\Support\Repository\Repository $config */ @@ -351,7 +351,7 @@ public function login(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); - return $response->withStatus(400); + return $response->withJson([], 400); } // Determine whether we are trying to log in with an email address or a username @@ -373,7 +373,7 @@ public function login(Request $request, Response $response, $args) $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', [ 'delay' => $delay ]); - return $response->withStatus(429); + return $response->withJson([], 429); } // Log throttleable event @@ -383,7 +383,7 @@ public function login(Request $request, Response $response, $args) // Note that we do this after logging throttle event, so this error counts towards throttling limit. if ($isEmail && !$config['site.login.enable_email']) { $ms->addMessageTranslated('danger', 'USER_OR_PASS_INVALID'); - return $response->withStatus(403); + return $response->withJson([], 403); } // Try to authenticate the user. Authenticator will throw an exception on failure. @@ -731,7 +731,7 @@ public function profile(Request $request, Response $response, $args) // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); - return $response->withStatus(403); + return $response->withJson([], 403); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -767,7 +767,7 @@ public function profile(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } // Looks good, let's update with new values! @@ -782,7 +782,7 @@ public function profile(Request $request, Response $response, $args) ]); $ms->addMessageTranslated('success', 'PROFILE.UPDATED'); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -832,13 +832,13 @@ public function register(Request $request, Response $response, $args) // Security measure: do not allow registering new users until the master account has been created. if (!$classMapper->staticMethod('user', 'find', $config['reserved_user_ids.master'])) { $ms->addMessageTranslated('danger', 'ACCOUNT.MASTER_NOT_EXISTS'); - return $response->withStatus(403); + return $response->withJson([], 403); } // Check if registration is currently enabled if (!$config['site.registration.enabled']) { $ms->addMessageTranslated('danger', 'REGISTRATION.DISABLED'); - return $response->withStatus(403); + return $response->withJson([], 403); } /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ @@ -847,7 +847,7 @@ public function register(Request $request, Response $response, $args) // Prevent the user from registering if he/she is already logged in if ($authenticator->check()) { $ms->addMessageTranslated('danger', 'REGISTRATION.LOGOUT'); - return $response->withStatus(403); + return $response->withJson([], 403); } // Load the request schema @@ -872,7 +872,7 @@ public function register(Request $request, Response $response, $args) // Throttle requests if ($delay > 0) { - return $response->withStatus(429); + return $response->withJson([], 429); } // Check captcha, if required @@ -885,7 +885,7 @@ public function register(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } // Remove captcha, password confirmation from object data after validation @@ -911,7 +911,7 @@ public function register(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'REGISTRATION.COMPLETE_TYPE1'); } - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -957,7 +957,7 @@ public function resendVerification(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); - return $response->withStatus(400); + return $response->withJson([], 400); } // Throttle requests @@ -972,7 +972,7 @@ public function resendVerification(Request $request, Response $response, $args) if ($delay > 0) { $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); - return $response->withStatus(429); + return $response->withJson([], 429); } // All checks passed! log events/activities, create user, and send verification email (if required) @@ -1006,7 +1006,7 @@ public function resendVerification(Request $request, Response $response, $args) }); $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.NEW_LINK_SENT', ['email' => $data['email']]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -1052,7 +1052,7 @@ public function setPassword(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); - return $response->withStatus(400); + return $response->withJson([], 400); } $forgotPasswordPage = $this->ci->router->pathFor('forgot-password'); @@ -1064,7 +1064,7 @@ public function setPassword(Request $request, Response $response, $args) if (!$passwordReset) { $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID', ['url' => $forgotPasswordPage]); - return $response->withStatus(400); + return $response->withJson([], 400); } $ms->addMessageTranslated('success', 'PASSWORD.UPDATED'); @@ -1082,7 +1082,7 @@ public function setPassword(Request $request, Response $response, $args) $authenticator->login($user); $ms->addMessageTranslated('success', 'WELCOME', $user->export()); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -1117,7 +1117,7 @@ public function settings(Request $request, Response $response, $args) // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); - return $response->withStatus(403); + return $response->withJson([], 403); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -1162,7 +1162,7 @@ public function settings(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } // Hash new password, if specified @@ -1185,7 +1185,7 @@ public function settings(Request $request, Response $response, $args) ]); $ms->addMessageTranslated('success', 'ACCOUNT.SETTINGS.UPDATED'); - return $response->withStatus(200); + return $response->withJson([], 200); } /** diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index 21fddbda7..01482a498 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -93,7 +93,7 @@ public function create(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } /** @var \UserFrosting\Support\Repository\Repository $config */ @@ -117,7 +117,7 @@ public function create(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'GROUP.CREATION_SUCCESSFUL', $data); }); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -204,7 +204,7 @@ public function delete(Request $request, Response $response, $args) 'name' => $groupName ]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -727,7 +727,7 @@ public function updateInfo(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } // Begin transaction - DB will be rolled back if an exception occurs @@ -752,7 +752,7 @@ public function updateInfo(Request $request, Response $response, $args) 'name' => $group->name ]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index 6f10ebfc5..fe9c6994a 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -93,7 +93,7 @@ public function create(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } /** @var \UserFrosting\Support\Repository\Repository $config */ @@ -117,7 +117,7 @@ public function create(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'ROLE.CREATION_SUCCESSFUL', $data); }); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -203,7 +203,7 @@ public function delete(Request $request, Response $response, $args) 'name' => $roleName ]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -833,7 +833,7 @@ public function updateInfo(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } // Begin transaction - DB will be rolled back if an exception occurs @@ -858,7 +858,7 @@ public function updateInfo(Request $request, Response $response, $args) 'name' => $role->name ]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -973,7 +973,7 @@ public function updateField(Request $request, Response $response, $args) ]); } - return $response->withStatus(200); + return $response->withJson([], 200); } /** diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index e7f6b73c6..fd1e32757 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -97,7 +97,7 @@ public function create(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } /** @var \UserFrosting\Support\Repository\Repository $config */ @@ -164,7 +164,7 @@ public function create(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'USER.CREATED', $data); }); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -236,7 +236,7 @@ public function createPasswordReset(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', [ 'email' => $user->email ]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -310,7 +310,7 @@ public function delete(Request $request, Response $response, $args) 'user_name' => $userName ]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -1151,7 +1151,7 @@ public function updateInfo(Request $request, Response $response, $args) } if ($error) { - return $response->withStatus(400); + return $response->withJson([], 400); } // Begin transaction - DB will be rolled back if an exception occurs @@ -1175,7 +1175,7 @@ public function updateInfo(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'DETAILS_UPDATED', [ 'user_name' => $user->user_name ]); - return $response->withStatus(200); + return $response->withJson([], 200); } /** @@ -1331,7 +1331,7 @@ public function updateField(Request $request, Response $response, $args) ]); } - return $response->withStatus(200); + return $response->withJson([], 200); } /** From 9e0d766b796db7706e9b96a80bb8062a02d48f08 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 5 Nov 2018 22:20:30 -0500 Subject: [PATCH 133/237] Disable CSRF during development (for REST API testing) #840 --- app/sprinkles/core/config/default.php | 1 + app/sprinkles/core/src/Core.php | 28 +-------- .../core/src/Middleware/CsrfMiddleware.php | 59 +++++++++++++++++++ 3 files changed, 62 insertions(+), 26 deletions(-) create mode 100644 app/sprinkles/core/src/Middleware/CsrfMiddleware.php diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 2d2a50c41..9c842220e 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -48,6 +48,7 @@ ], // CSRF middleware settings (see https://github.com/slimphp/Slim-Csrf) 'csrf' => [ + 'enabled' => getenv('CSRF_ENABLED') ?: true, 'name' => 'csrf', 'storage_limit' => 200, 'strength' => 16, diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index ab5d79cdf..2ef292df4 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -9,6 +9,7 @@ use RocketTheme\Toolbox\Event\Event; use UserFrosting\Sprinkle\Core\Database\Models\Model; +use UserFrosting\Sprinkle\Core\Middleware\CsrfMiddleware; use UserFrosting\Sprinkle\Core\Util\EnvironmentInfo; use UserFrosting\Sprinkle\Core\Util\ShutdownHandler; use UserFrosting\System\Sprinkle\Sprinkle; @@ -109,31 +110,6 @@ public function onSprinklesRegisterServices() */ public function onAddGlobalMiddleware(Event $event) { - $request = $this->ci->request; - $path = $request->getUri()->getPath(); - $method = ($request->getMethod()) ?: 'GET'; - - // Normalize path to always have a leading slash - $path = '/' . ltrim($path, '/'); - - // Normalize method to uppercase. - $method = strtoupper($method); - - $csrfBlacklist = $this->ci->config['csrf.blacklist']; - $isBlacklisted = false; - - // Go through the blacklist and determine if the path and method match any of the blacklist entries. - foreach ($csrfBlacklist as $pattern => $methods) { - $methods = array_map('strtoupper', (array) $methods); - if (in_array($method, $methods) && $pattern != '' && preg_match('~' . $pattern . '~', $path)) { - $isBlacklisted = true; - break; - } - } - - if (!$path || !$isBlacklisted) { - $app = $event->getApp(); - $app->add($this->ci->csrf); - } + CsrfMiddleware::register($event->getApp(), $this->ci->request, $this->ci->csrf); } } diff --git a/app/sprinkles/core/src/Middleware/CsrfMiddleware.php b/app/sprinkles/core/src/Middleware/CsrfMiddleware.php new file mode 100644 index 000000000..155e43232 --- /dev/null +++ b/app/sprinkles/core/src/Middleware/CsrfMiddleware.php @@ -0,0 +1,59 @@ +getUri()->getPath(); + $method = ($request->getMethod()) ?: 'GET'; + + // Normalize path to always have a leading slash + $path = '/' . ltrim($path, '/'); + + // Normalize method to uppercase. + $method = strtoupper($method); + + $csrfBlacklist = Config::get('csrf.blacklist'); + $isBlacklisted = false; + + // Go through the blacklist and determine if the path and method match any of the blacklist entries. + foreach ($csrfBlacklist as $pattern => $methods) { + $methods = array_map('strtoupper', (array) $methods); + if (in_array($method, $methods) && $pattern != '' && preg_match('~' . $pattern . '~', $path)) { + $isBlacklisted = true; + break; + } + } + + if (!$path || !$isBlacklisted) { + $app->add($guard); + } + } +} From dc1f2e99a4da9efbaa47798eb40269698a98c534 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 6 Nov 2018 22:09:51 -0500 Subject: [PATCH 134/237] Added comments to the config files to help understand each options --- app/sprinkles/account/config/debug.php | 3 +- app/sprinkles/account/config/default.php | 78 ++++++-- app/sprinkles/account/config/production.php | 11 +- .../src/ServicesProvider/ServicesProvider.php | 5 +- app/sprinkles/core/config/debug.php | 12 +- app/sprinkles/core/config/default.php | 182 ++++++++++++++---- app/sprinkles/core/config/production.php | 22 ++- app/sprinkles/core/config/testing.php | 1 - 8 files changed, 244 insertions(+), 70 deletions(-) diff --git a/app/sprinkles/account/config/debug.php b/app/sprinkles/account/config/debug.php index a93044fe2..42711b25a 100644 --- a/app/sprinkles/account/config/debug.php +++ b/app/sprinkles/account/config/debug.php @@ -1,8 +1,7 @@ [ 'auth' => false ], - // configuration for the 'password reset' feature - 'password_reset' => [ + + /** + * ---------------------------------------------------------------------- + * Configuration for the 'password reset' feature + * ---------------------------------------------------------------------- + */ + 'password_reset' => [ 'algorithm' => 'sha512', 'timeouts' => [ 'create' => 86400, 'reset' => 10800 ] ], - // See https://github.com/gbirke/rememberme for an explanation of these settings + + /** + * ---------------------------------------------------------------------- + * RememberMe Package Settings + * ---------------------------------------------------------------------- + * See https://github.com/gbirke/rememberme for an explanation of these settings + */ 'remember_me' => [ 'cookie' => [ 'name' => 'rememberme' @@ -34,44 +51,79 @@ 'expiresColumn' => 'expires_at' ] ], + + /** + * ---------------------------------------------------------------------- + * Reserved user IDs + * ---------------------------------------------------------------------- + * Master (root) user will be the one with this user id. Same goes for + * guest users + */ 'reserved_user_ids' => [ 'guest' => -1, 'master' => 1 ], + + /** + * ---------------------------------------------------------------------- + * Account Session config + * ---------------------------------------------------------------------- + * The keys used in the session to store info about authenticated users + */ 'session' => [ - // The keys used in the session to store info about authenticated users 'keys' => [ 'current_user_id' => 'account.current_user_id', // the key to use for storing the authenticated user's id - 'captcha' => 'account.captcha' // Key used to store a captcha hash during captcha verification + 'captcha' => 'account.captcha' // Key used to store a captcha hash during captcha verification ] ], - // "Site" settings that are automatically passed to Twig + + /** + * ---------------------------------------------------------------------- + * Account Site Settings + * ---------------------------------------------------------------------- + * "Site" settings that are automatically passed to Twig. Use theses + * settings to control the login and registration process + */ 'site' => [ 'login' => [ - 'enable_email' => true + 'enable_email' => true // Set to false to allow login by username only ], 'registration' => [ 'enabled' => true, //if this set to false, you probably want to also set require_email_verification to false as well to disable the link on the signup page 'captcha' => true, 'require_email_verification' => true, + // Default roles and other settings for newly registered users 'user_defaults' => [ 'locale' => 'en_US', 'group' => 'terran', - // Default roles for newly registered users 'roles' => [ 'user' => true ] ] ] ], + + /** + * ---------------------------------------------------------------------- + * Throttles Configuration + * ---------------------------------------------------------------------- + * No throttling is enforced by default. Everything is setup in + * production mode. See http://security.stackexchange.com/a/59550/74909 + * for the inspiration for our throttling system + */ 'throttles' => [ 'check_username_request' => null, 'password_reset_request' => null, - 'registration_attempt' => null, - 'sign_in_attempt' => null, - 'verification_request' => null + 'registration_attempt' => null, + 'sign_in_attempt' => null, + 'verification_request' => null ], - // configuration for the 'email verification' feature + + /** + * ---------------------------------------------------------------------- + * Configuration for the 'email verification' feature + * ---------------------------------------------------------------------- + */ 'verification' => [ 'algorithm' => 'sha512', 'timeout' => 10800 diff --git a/app/sprinkles/account/config/production.php b/app/sprinkles/account/config/production.php index b7c3288ed..0935f0fc1 100644 --- a/app/sprinkles/account/config/production.php +++ b/app/sprinkles/account/config/production.php @@ -1,12 +1,19 @@ [ 'check_username_request' => [ 'method' => 'ip', diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index 94946fad8..97b98a208 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -103,11 +103,8 @@ public function register(ContainerInterface $container) return $pathBuilder; } + // Add user locale if ($authenticator->check()) { - // Add paths to locale files for user theme - // TODO $themePath = $c->sprinkleManager->addResource('locale', $currentUser->theme); - - // Add user locale $pathBuilder->addLocales($currentUser->locale); } diff --git a/app/sprinkles/core/config/debug.php b/app/sprinkles/core/config/debug.php index 0ea1faeb5..ce1706689 100644 --- a/app/sprinkles/core/config/debug.php +++ b/app/sprinkles/core/config/debug.php @@ -1,8 +1,7 @@ false ], 'debug' => [ - 'deprecation' => true, - 'queries' => true, - 'smtp' => true, - 'twig' => true + 'deprecation' => true, + 'queries' => true, + 'smtp' => true, + 'twig' => true ], - // Slim settings - see http://www.slimframework.com/docs/objects/application.html#slim-default-settings 'settings' => [ 'displayErrorDetails' => true ], diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 9c842220e..5c42067ec 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -9,16 +9,39 @@ */ return [ - 'address_book' => [ + /** + * ---------------------------------------------------------------------- + * Address Book + * ---------------------------------------------------------------------- + * Admin is the one sending email from the system. You can set the sender + * email adress and name using this config. + */ + 'address_book' => [ 'admin' => [ 'email' => getenv('SMTP_USER') ?: null, 'name' => 'Site Administrator' ] ], + + /** + * ---------------------------------------------------------------------- + * Alert Service Config + * ---------------------------------------------------------------------- + * Alerts can be stored in the session, or cache system. Switch to the + * cache system if you experience issue with persistent alerts. + */ 'alert' => [ - 'storage' => 'session', // Set to one of `cache` or `session` - 'key' => 'site.alerts', // the key to use to store flash messages + 'storage' => 'session', // Supported storage : `session`, `cache` + 'key' => 'site.alerts', // the key to use to store flash messages ], + + /** + * ---------------------------------------------------------------------- + * Assets Service Config + * ---------------------------------------------------------------------- + * `use_raw` defines if raw or compiled assets are served. Set to false + * in production mode, so compiled assets can be served + */ 'assets' => [ 'compiled' => [ 'path' => 'assets', @@ -30,31 +53,50 @@ ], 'use_raw' => true ], + + /** + * ---------------------------------------------------------------------- + * Cache Service Config + * ---------------------------------------------------------------------- + * Redis & Memcached driver configuration + * See Laravel for more info : https://laravel.com/docs/5.4/cache + * + * Edit prefix to something unique when multiple instance of memcached / + * redis are used on the same server. + */ 'cache' => [ - 'driver' => 'file', // Set to one of `file`, `memcached`, `redis` - 'prefix' => 'userfrosting', // Edit prefix to something unique when multiple instance of memcached/redis are used on the same server + 'driver' => 'file', // Supported drivers : `file`, `memcached`, `redis` + 'prefix' => 'userfrosting', 'memcached' => [ - 'host' => '127.0.0.1', - 'port' => 11211, + 'host' => '127.0.0.1', + 'port' => 11211, 'weight' => 100 ], 'redis' => [ - 'host' => '127.0.0.1', + 'host' => '127.0.0.1', 'password' => null, - 'port' => 6379, + 'port' => 6379, 'database' => 0 ], + // Cache twig file to disk 'twig' => false ], - // CSRF middleware settings (see https://github.com/slimphp/Slim-Csrf) + + /** + * ---------------------------------------------------------------------- + * CSRF middleware settings + * ---------------------------------------------------------------------- + * See https://github.com/slimphp/Slim-Csrf + * Note : CSRF Middleware should only be disabled for dev or debug purposes. + */ 'csrf' => [ 'enabled' => getenv('CSRF_ENABLED') ?: true, 'name' => 'csrf', 'storage_limit' => 200, 'strength' => 16, 'persistent_token' => true, - // A list of url paths to ignore CSRF checks on - 'blacklist' => [ + 'blacklist' => [ + // A list of url paths to ignore CSRF checks on // URL paths will be matched against each regular expression in this list. // Each regular expression should map to an array of methods. // Regular expressions will be delimited with ~ in preg_match, so if you @@ -62,7 +104,18 @@ // Also, remember to use ^ when you only want to match the beginning of a URL path! ] ], - 'db' => [ + + /** + * ---------------------------------------------------------------------- + * Database Config + * ---------------------------------------------------------------------- + * Settings for the default database connections. Actual config values + * should be store in environment variables + * + * Multiple connections can also be used. + * See Laravel docs : https://laravel.com/docs/5.4/database + */ + 'db' => [ 'default' => [ 'driver' => getenv('DB_DRIVER') ?: 'mysql', 'host' => getenv('DB_HOST') ?: null, @@ -75,18 +128,24 @@ 'prefix' => '' ] ], + + /** + * ---------------------------------------------------------------------- + * Debug Configuration + * ---------------------------------------------------------------------- + * Turn any of those on to help debug your app + */ 'debug' => [ - 'deprecation' => true, - 'queries' => false, - 'smtp' => false, - 'twig' => false + 'deprecation' => true, + 'queries' => false, + 'smtp' => false, + 'twig' => false ], /** * ---------------------------------------------------------------------- * Filesystem Configuration * ---------------------------------------------------------------------- - * * You may configure as many filesystem "disks" as you wish, and you * may even configure multiple disks of the same driver. You may also * select the default filesystem disk that should be used by UserFrosting. @@ -134,8 +193,14 @@ ], ], + /** + * ---------------------------------------------------------------------- + * Mail Service Config + * ---------------------------------------------------------------------- + * See https://learn.userfrosting.com/mail/the-mailer-service + */ 'mail' => [ - 'mailer' => 'smtp', // Set to one of 'smtp', 'mail', 'qmail', 'sendmail' + 'mailer' => 'smtp', // Set to one of 'smtp', 'mail', 'qmail', 'sendmail' 'host' => getenv('SMTP_HOST') ?: null, 'port' => 587, 'auth' => true, @@ -144,21 +209,41 @@ 'password' => getenv('SMTP_PASSWORD') ?: null, 'smtp_debug' => 4, 'message_options' => [ - 'CharSet' => 'UTF-8', - 'isHtml' => true, - 'Timeout' => 15 + 'CharSet' => 'UTF-8', + 'isHtml' => true, + 'Timeout' => 15 ] ], + + /** + * ---------------------------------------------------------------------- + * Migration Service Config + * ---------------------------------------------------------------------- + * `repository_table` is the table with the list of ran migrations + */ 'migrations' => [ 'repository_table' => 'migrations' ], - // Filesystem paths + + /** + * ---------------------------------------------------------------------- + * Filesystem paths + * ---------------------------------------------------------------------- + */ 'path' => [ 'document_root' => str_replace(DIRECTORY_SEPARATOR, \UserFrosting\DS, $_SERVER['DOCUMENT_ROOT']), - 'public_relative' => dirname($_SERVER['SCRIPT_NAME']) // The location of `index.php` relative to the document root. Use for sites installed in subdirectories of your web server's document root. + 'public_relative' => dirname($_SERVER['SCRIPT_NAME']) // The location of `index.php` relative to the document root. Use for sites installed in subdirectories of your web server's document root. ], + + /** + * ---------------------------------------------------------------------- + * Session Config + * ---------------------------------------------------------------------- + * Custom PHP Sessions Handler config. Sessions can be store in file or + * database. Array handler can be used for testing + */ 'session' => [ - 'handler' => 'file', //file, database or array + 'handler' => 'file', // Supported Handler : `file`, `database` or `array` // Config values for when using db-based sessions 'database' => [ 'table' => 'sessions' @@ -168,26 +253,41 @@ 'cache_limiter' => false, // Decouples the session keys used to store certain session info 'keys' => [ - 'csrf' => 'site.csrf', // the key (prefix) used to store an ArrayObject of CSRF tokens. + 'csrf' => 'site.csrf', // the key (prefix) used to store an ArrayObject of CSRF tokens. ] ], - // Slim settings - see http://www.slimframework.com/docs/objects/application.html#slim-default-settings + + /** + * ---------------------------------------------------------------------- + * Slim settings + * ---------------------------------------------------------------------- + * See http://www.slimframework.com/docs/objects/application.html#slim-default-settings + * Set `displayErrorDetails` to true to display full error details + */ 'settings' => [ 'displayErrorDetails' => true ], - // "Site" settings that are automatically passed to Twig + + /** + * ---------------------------------------------------------------------- + * Site Settings + * ---------------------------------------------------------------------- + * "Site" settings that are automatically passed to Twig + */ 'site' => [ + // AdminLTE Settings 'AdminLTE' => [ 'skin' => 'blue' ], + // Google Analytics Settings 'analytics' => [ 'google' => [ 'code' => '', 'enabled' => false ] ], - 'author' => 'Author', - 'csrf' => null, // Do not set this variable. The core Twig extension will override it with values from the CSRF service. + 'author' => 'Author', // Site author + 'csrf' => null, // Do not set this variable. The core Twig extension will override it with values from the CSRF service. 'debug' => [ 'ajax' => false, 'info' => true @@ -216,7 +316,7 @@ // translation as a base and load the Spanish (es_ES) translation on top. 'default' => 'en_US' ], - 'title' => 'UserFrosting', + 'title' => 'UserFrosting', // Site display name // Global ufTable settings 'uf_table' => [ 'use_loading_transition' => true @@ -225,17 +325,23 @@ 'uri' => [ // 'base' settings are no longer used to generate the uri frequently used in Twig (site.uri.public). This is due to Slim doing a better job of figuring this out on its own. This key has been kept to ensure backwards compatibility. 'base' => [ - 'host' => isset($_SERVER['SERVER_NAME']) ? trim($_SERVER['SERVER_NAME'], '/') : 'localhost', - 'scheme' => empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https', - 'port' => isset($_SERVER['SERVER_PORT']) ? (int) $_SERVER['SERVER_PORT'] : null, - 'path' => isset($_SERVER['SCRIPT_NAME']) ? trim(dirname($_SERVER['SCRIPT_NAME']), '/\\') : '' + 'host' => isset($_SERVER['SERVER_NAME']) ? trim($_SERVER['SERVER_NAME'], '/') : 'localhost', + 'scheme' => empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] === 'off' ? 'http' : 'https', + 'port' => isset($_SERVER['SERVER_PORT']) ? (int) $_SERVER['SERVER_PORT'] : null, + 'path' => isset($_SERVER['SCRIPT_NAME']) ? trim(dirname($_SERVER['SCRIPT_NAME']), '/\\') : '' ], - 'author' => 'https://www.userfrosting.com', - 'publisher' => '' + 'author' => 'https://www.userfrosting.com', + 'publisher' => '' ] ], + + /** + * ---------------------------------------------------------------------- + * PHP global settings + * ---------------------------------------------------------------------- + */ 'php' => [ - 'timezone' => 'America/New_York', + 'timezone' => 'America/New_York', 'error_reporting' => E_ALL, // Development - report all errors and suggestions 'display_errors' => 'true', 'log_errors' => 'false', diff --git a/app/sprinkles/core/config/production.php b/app/sprinkles/core/config/production.php index d0154d4dd..93cc5611d 100644 --- a/app/sprinkles/core/config/production.php +++ b/app/sprinkles/core/config/production.php @@ -2,26 +2,39 @@ /** * Default production config file for UserFrosting. You may override/extend this in your site's configuration file to customize deploy settings. - * */ return [ + /** + * Use compiled assets + */ 'assets' => [ 'use_raw' => false ], + /** + * Enable Twig cache + */ 'cache' => [ 'twig' => true ], + /** + * Turn off debug logs + */ 'debug' => [ 'twig' => false, 'auth' => false, 'smtp' => false ], - // Slim settings - see http://www.slimframework.com/docs/objects/application.html#slim-default-settings + /** + * Use router cache, disable full error details + */ 'settings' => [ - 'routerCacheFile' => \UserFrosting\ROOT_DIR . '/' . \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\CACHE_DIR_NAME . '/' . 'routes.cache', + 'routerCacheFile' => \UserFrosting\ROOT_DIR . '/' . \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\CACHE_DIR_NAME . '/' . 'routes.cache', 'displayErrorDetails' => false ], + /** + * Enable analytics, disable more debugging + */ 'site' => [ 'analytics' => [ 'google' => [ @@ -33,6 +46,9 @@ 'info' => false ] ], + /** + * Send errors to log + */ 'php' => [ 'display_errors' => 'false', 'log_errors' => 'true' diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index a3b0a9c99..9606cf2ab 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -2,7 +2,6 @@ /** * Default testing config file for UserFrosting. You may override/extend this in your site's configuration file to customize deploy settings. - * */ return [ From 79f6f1e594e6b6f80419437e797ae71e159dc672 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 7 Nov 2018 21:33:57 -0500 Subject: [PATCH 135/237] Add MigrationInterface and verbose unfulfillable migration message --- app/sprinkles/core/src/Database/Migration.php | 16 +--- .../core/src/Database/MigrationInterface.php | 26 ++++++ .../Migrator/MigrationDependencyAnalyser.php | 12 ++- .../MigrationRollbackDependencyAnalyser.php | 4 +- .../core/src/Database/Migrator/Migrator.php | 90 +++++++++++-------- .../MigrationDependencyAnalyserTest.php | 2 +- app/system/Bakery/Migration.php | 2 +- 7 files changed, 91 insertions(+), 61 deletions(-) create mode 100644 app/sprinkles/core/src/Database/MigrationInterface.php diff --git a/app/sprinkles/core/src/Database/Migration.php b/app/sprinkles/core/src/Database/Migration.php index 8afed782b..0f9f3cba1 100644 --- a/app/sprinkles/core/src/Database/Migration.php +++ b/app/sprinkles/core/src/Database/Migration.php @@ -14,7 +14,7 @@ * * @author Louis Charette */ -abstract class Migration +abstract class Migration implements MigrationInterface { /** * @var \Illuminate\Database\Schema\Builder $schema @@ -38,18 +38,4 @@ public function __construct(Builder $schema = null) { $this->schema = $schema; } - - /** - * Method to apply changes to the database - */ - public function up() - { - } - - /** - * Method to revert changes applied by the `up` method - */ - public function down() - { - } } diff --git a/app/sprinkles/core/src/Database/MigrationInterface.php b/app/sprinkles/core/src/Database/MigrationInterface.php new file mode 100644 index 000000000..4af0ec53f --- /dev/null +++ b/app/sprinkles/core/src/Database/MigrationInterface.php @@ -0,0 +1,26 @@ +pending->contains($dependency) || !$this->validateClassDependencies($dependency)) { - return $this->markAsUnfulfillable($migrationName); + return $this->markAsUnfulfillable($migrationName, $dependency); } } @@ -176,11 +176,16 @@ protected function markAsFulfillable($migration) * Mark a dependency as unfulfillable. Removes it from the pending list and add it to the unfulfillable list * * @param string $migration The migration classname + * @param string|array $dependency The problematic dependecy * @return bool False, it's not fullfillable */ - protected function markAsUnfulfillable($migration) + protected function markAsUnfulfillable($migration, $dependency) { - $this->unfulfillable->push($migration); + if (is_array($dependency)) { + $dependency = implode(", ", $dependency); + } + + $this->unfulfillable->put($migration, $dependency); return false; } @@ -201,6 +206,7 @@ protected function getMigrationDependencies($migration) // If the `dependencies` property exist and is static, use this one. // Otherwise, get a class instance and the non static property + // We can remove this one the non static property is removed $reflectionClass = new ReflectionClass($migration); if ($reflectionClass->hasProperty('dependencies') && $reflectionClass->getProperty('dependencies')->isStatic()) { return $migration::$dependencies; diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php index d263ae4ed..ce1c1fd2a 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php @@ -65,8 +65,8 @@ protected function validateClassDependencies($migrationName) // If this migration has a dependencies for one of the migration to // rollback (installed), we can't perform the rollback - if (array_intersect($this->installed->toArray(), $dependencies)) { - return $this->markAsUnfulfillable($migrationName); + if ($missing = array_intersect($this->installed->toArray(), $dependencies)) { + return $this->markAsUnfulfillable($migrationName, $missing); } // If no dependencies returned false, it's fulfillable diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index 5dfe081e3..e63a6cd53 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -9,6 +9,7 @@ use Illuminate\Support\Arr; use Illuminate\Database\Capsule\Manager as Capsule; +use UserFrosting\Sprinkle\Core\Database\MigrationInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocatorInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRepositoryInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationDependencyAnalyser as Analyser; @@ -99,8 +100,11 @@ public function run(array $options = []) // Any migration without a fulfilled dependency will cause this script to throw an exception if ($unfulfillable = $analyser->getUnfulfillable()) { - $unfulfillableList = implode(", ", $unfulfillable); - throw new \Exception("Unfulfillable migrations found :: $unfulfillableList"); + $messages = ["Unfulfillable migrations found :: "]; + foreach ($unfulfillable as $migration => $dependency) { + $messages[] = "=> $migration (Missing dependency : $dependency)"; + } + throw new \Exception(implode("\n", $messages)); } // Run pending migration up @@ -114,7 +118,7 @@ public function run(array $options = []) * @param array $ran The list of already ran migrations returned by the migration repository * @return array The list of pending migrations, ie the available migrations not ran yet */ - public function pendingMigrations($available, $ran) + public function pendingMigrations(array $available, array $ran) { return collect($available)->reject(function ($migration) use ($ran) { return collect($ran)->contains($migration); @@ -141,8 +145,8 @@ protected function runPending(array $migrations, array $options = []) // We now have an ordered array of migrations, we will spin through them and run the // migrations "up" so the changes are made to the databases. We'll then log // that the migration was run so we don't repeat it next time we execute. - foreach ($migrations as $migrationClass) { - $this->runUp($migrationClass, $batch, $pretend); + foreach ($migrations as $migrationClassName) { + $this->runUp($migrationClassName, $batch, $pretend); if ($step) { $batch++; @@ -155,16 +159,16 @@ protected function runPending(array $migrations, array $options = []) /** * Run "up" a migration class * - * @param string $migrationClass The migration class name + * @param string $migrationClassName The migration class name * @param int $batch The current bacth number * @param bool $pretend If this operation should be pretended / faked */ - protected function runUp($migrationClass, $batch, $pretend) + protected function runUp($migrationClassName, $batch, $pretend) { // First we will resolve a "real" instance of the migration class from // the class name. Once we have the instances we can run the actual // command such as "up" or "down", or we can just simulate the action. - $migration = $this->resolve($migrationClass); + $migration = $this->resolve($migrationClassName); // Move into pretend mode if requested if ($pretend) { @@ -177,9 +181,9 @@ protected function runUp($migrationClass, $batch, $pretend) // Once we have run a migrations class, we will log that it was run in this // repository so that we don't try to run it next time we do a migration // in the application. A migration repository keeps the migrate order. - $this->repository->log($migrationClass, $batch); + $this->repository->log($migrationClassName, $batch); - $this->note("Migrated: {$migrationClass}"); + $this->note("Migrated: {$migrationClassName}"); /** * If the migration has a `seed` method, run it @@ -190,7 +194,7 @@ protected function runUp($migrationClass, $batch, $pretend) Debug::warning("Migration `seed` method has been deprecated and will be removed in future versions. Please use a Seeder instead."); } $this->runMigration($migration, 'seed'); - $this->note("Seeded: {$migrationClass}"); + $this->note("Seeded: {$migrationClassName}"); } } @@ -219,25 +223,25 @@ public function rollback(array $options = []) /** * Rollback a specific migration * - * @param string $migration The Migration to rollback + * @param string $migrationClassName The Migration to rollback * @param array $options * @return array The list of rolledback migration classes */ - public function rollbackMigration($migration, array $options = []) + public function rollbackMigration($migrationClassName, array $options = []) { $this->notes = []; // Get the migration detail from the repository - $migrationObject = $this->repository->getMigration($migration); + $migration = $this->repository->getMigration($migrationClassName); // Make sure the migration was found. If not, return same empty array // as the main rollback method - if (!$migrationObject) { + if (!$migration) { return []; } // Rollback the migration - return $this->rollbackMigrations([$migrationObject->migration], $options); + return $this->rollbackMigrations([$migration->migration], $options); } /** @@ -308,7 +312,7 @@ protected function rollbackMigrations(array $migrations, array $options) * @param array $migrations The migrations classes to rollback * @throws \Exception If rollback can't be performed */ - protected function checkRollbackDependencies($migrations) + protected function checkRollbackDependencies(array $migrations) { // Get ran migrations $ranMigrations = $this->repository->getMigrationsList(); @@ -318,8 +322,11 @@ protected function checkRollbackDependencies($migrations) // Any rollback that creates an unfulfilled dependency will cause this script to throw an exception if ($unfulfillable = $analyser->getUnfulfillable()) { - $unfulfillableList = implode(", ", $unfulfillable); - throw new \Exception("Some migrations can't be rolled back since the following migrations depends on it :: $unfulfillableList"); + $messages = ["Some migrations can't be rolled back since the other migrations depends on it :: "]; + foreach ($unfulfillable as $migration => $dependency) { + $messages[] = "=> $dependency is a dependency of $migration"; + } + throw new \Exception(implode("\n", $messages)); } } @@ -351,14 +358,14 @@ public function reset($pretend = false) /** * Run "down" a migration instance. * - * @param string $migrationClass The migration class name + * @param string $migrationClassName The migration class name * @param bool $pretend Is the operation should be pretended */ - protected function runDown($migrationClass, $pretend) + protected function runDown($migrationClassName, $pretend) { // We resolve an instance of the migration. Once we get an instance we can either run a // pretend execution of the migration or we can run the real migration. - $instance = $this->resolve($migrationClass); + $instance = $this->resolve($migrationClassName); if ($pretend) { return $this->pretendToRun($instance, 'down'); @@ -369,21 +376,22 @@ protected function runDown($migrationClass, $pretend) // Once we have successfully run the migration "down" we will remove it from // the migration repository so it will be considered to have not been run // by the application then will be able to fire by any later operation. - $this->repository->delete($migrationClass); + $this->repository->delete($migrationClassName); - $this->note("Rolled back: {$migrationClass}"); + $this->note("Rolled back: {$migrationClassName}"); } /** * Run a migration inside a transaction if the database supports it. * Note : As of Laravel 5.4, only PostgresGrammar supports it * - * @param object $migration The migration instance + * @param MigrationInterface $migration The migration instance * @param string $method The method used [up, down] */ - protected function runMigration($migration, $method) + protected function runMigration(MigrationInterface $migration, $method) { $callback = function () use ($migration, $method) { + // We keep this for seed... if (method_exists($migration, $method)) { $migration->{$method}(); } @@ -399,10 +407,10 @@ protected function runMigration($migration, $method) /** * Pretend to run the migrations. * - * @param object $migration The migration instance + * @param MigrationInterface $migration The migration instance * @param string $method The method used [up, down] */ - protected function pretendToRun($migration, $method) + protected function pretendToRun(MigrationInterface $migration, $method) { $name = get_class($migration); $this->note("\n$name"); @@ -415,35 +423,39 @@ protected function pretendToRun($migration, $method) /** * Get all of the queries that would be run for a migration. * - * @param object $migration The migration instance + * @param MigrationInterface $migration The migration instance * @param string $method The method used [up, down] * @return array The queries executed by the processed schema */ - protected function getQueries($migration, $method) + protected function getQueries(MigrationInterface $migration, $method) { // Get the connection instance $connection = $this->getConnection(); return $connection->pretend(function () use ($migration, $method) { - if (method_exists($migration, $method)) { - $migration->{$method}(); - } + $migration->{$method}(); }); } /** * Resolve a migration instance from it's class name. * - * @param string $migrationClass The class name - * @return object The migration class instance + * @param string $migrationClassName The class name + * @return MigrationInterface The migration class instance */ - public function resolve($migrationClass) + public function resolve($migrationClassName) { - if (!class_exists($migrationClass)) { - throw new BadClassNameException("Unable to find the migration class '$migrationClass'."); + if (!class_exists($migrationClassName)) { + throw new BadClassNameException("Unable to find the migration class '$migrationClassName'."); + } + + $migration = new $migrationClassName($this->getSchemaBuilder()); + + if (!$migration instanceof MigrationInterface) { + throw new \Exception('Migration must be an instance of `'.MigrationInterface::class.'`'); } - return new $migrationClass($this->getSchemaBuilder()); + return $migration; } /** diff --git a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php index 03f8bf7af..173071a08 100644 --- a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php @@ -75,7 +75,7 @@ public function testAnalyserWithUnfulfillable() ], $analyser->getFulfillable()); $this->assertEquals([ - '\\UserFrosting\\Tests\\Integration\\Migrations\\UnfulfillableTable' + '\\UserFrosting\\Tests\\Integration\\Migrations\\UnfulfillableTable' => '\UserFrosting\Tests\Integration\Migrations\NonExistingMigration' ], $analyser->getUnfulfillable()); } } diff --git a/app/system/Bakery/Migration.php b/app/system/Bakery/Migration.php index 0d50af7b9..6023d3672 100644 --- a/app/system/Bakery/Migration.php +++ b/app/system/Bakery/Migration.php @@ -19,7 +19,7 @@ * @deprecated since 4.2.0 Use `UserFrosting\Sprinkle\Core\Database\Migration` instead * @author Alex Weissman (https://alexanderweissman.com) */ -class Migration extends NewMigration +abstract class Migration extends NewMigration { /** * Constructor From 3d4520be24c04f7ad30fb43e659d06c817d971f5 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 7 Nov 2018 22:03:45 -0500 Subject: [PATCH 136/237] Decoupled Slim CSRF code from service provider for easier substitution of the CSRF provider later (Ref #706) --- app/sprinkles/core/src/Core.php | 4 +- .../core/src/Csrf/CsrfProviderInterface.php | 39 +++++++++ .../core/src/Csrf/SlimCsrfProvider.php | 86 +++++++++++++++++++ .../core/src/Middleware/CsrfMiddleware.php | 59 ------------- .../src/ServicesProvider/ServicesProvider.php | 24 +----- 5 files changed, 129 insertions(+), 83 deletions(-) create mode 100644 app/sprinkles/core/src/Csrf/CsrfProviderInterface.php create mode 100644 app/sprinkles/core/src/Csrf/SlimCsrfProvider.php delete mode 100644 app/sprinkles/core/src/Middleware/CsrfMiddleware.php diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index 2ef292df4..488b66998 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -8,8 +8,8 @@ namespace UserFrosting\Sprinkle\Core; use RocketTheme\Toolbox\Event\Event; +use UserFrosting\Sprinkle\Core\Csrf\SlimCsrfProvider; use UserFrosting\Sprinkle\Core\Database\Models\Model; -use UserFrosting\Sprinkle\Core\Middleware\CsrfMiddleware; use UserFrosting\Sprinkle\Core\Util\EnvironmentInfo; use UserFrosting\Sprinkle\Core\Util\ShutdownHandler; use UserFrosting\System\Sprinkle\Sprinkle; @@ -110,6 +110,6 @@ public function onSprinklesRegisterServices() */ public function onAddGlobalMiddleware(Event $event) { - CsrfMiddleware::register($event->getApp(), $this->ci->request, $this->ci->csrf); + SlimCsrfProvider::registerMiddleware($event->getApp(), $this->ci->request, $this->ci->csrf); } } diff --git a/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php b/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php new file mode 100644 index 000000000..332f0f645 --- /dev/null +++ b/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php @@ -0,0 +1,39 @@ +config['session.keys.csrf']; + + // Workaround so that we can pass storage into CSRF guard. + // If we tried to directly pass the indexed portion of `session` (for example, $ci->session['site.csrf']), + // we would get an 'Indirect modification of overloaded element of UserFrosting\Session\Session' error. + // If we tried to assign an array and use that, PHP would only modify the local variable, and not the session. + // Since ArrayObject is an object, PHP will modify the object itself, allowing it to persist in the session. + if (!$ci->session->has($csrfKey)) { + $ci->session[$csrfKey] = new \ArrayObject(); + } + $csrfStorage = $ci->session[$csrfKey]; + + $onFailure = function ($request, $response, $next) { + $e = new BadRequestException("The CSRF code was invalid or not provided."); + $e->addUserMessage('CSRF_MISSING'); + throw $e; + + return $next($request, $response); + }; + + return new Guard($ci->config['csrf.name'], $csrfStorage, $onFailure, $ci->config['csrf.storage_limit'], $ci->config['csrf.strength'], $ci->config['csrf.persistent_token']); + } + + /** + * @inheritDoc + */ + public static function registerMiddleware(App $app, Request $request, $guard) + { + // Global on/off switch + if (!Config::get('csrf.enabled')) { + return; + } + + $path = $request->getUri()->getPath(); + $method = ($request->getMethod()) ?: 'GET'; + + // Normalize path to always have a leading slash + $path = '/' . ltrim($path, '/'); + + // Normalize method to uppercase. + $method = strtoupper($method); + + $csrfBlacklist = Config::get('csrf.blacklist'); + $isBlacklisted = false; + + // Go through the blacklist and determine if the path and method match any of the blacklist entries. + foreach ($csrfBlacklist as $pattern => $methods) { + $methods = array_map('strtoupper', (array) $methods); + if (in_array($method, $methods) && $pattern != '' && preg_match('~' . $pattern . '~', $path)) { + $isBlacklisted = true; + break; + } + } + + if (!$path || !$isBlacklisted) { + $app->add($guard); + } + } +} diff --git a/app/sprinkles/core/src/Middleware/CsrfMiddleware.php b/app/sprinkles/core/src/Middleware/CsrfMiddleware.php deleted file mode 100644 index 155e43232..000000000 --- a/app/sprinkles/core/src/Middleware/CsrfMiddleware.php +++ /dev/null @@ -1,59 +0,0 @@ -getUri()->getPath(); - $method = ($request->getMethod()) ?: 'GET'; - - // Normalize path to always have a leading slash - $path = '/' . ltrim($path, '/'); - - // Normalize method to uppercase. - $method = strtoupper($method); - - $csrfBlacklist = Config::get('csrf.blacklist'); - $isBlacklisted = false; - - // Go through the blacklist and determine if the path and method match any of the blacklist entries. - foreach ($csrfBlacklist as $pattern => $methods) { - $methods = array_map('strtoupper', (array) $methods); - if (in_array($method, $methods) && $pattern != '' && preg_match('~' . $pattern . '~', $path)) { - $isBlacklisted = true; - break; - } - } - - if (!$path || !$isBlacklisted) { - $app->add($guard); - } - } -} diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 023a8c804..1b2564b9e 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -22,7 +22,6 @@ use Monolog\Formatter\LineFormatter; use Monolog\Handler\StreamHandler; use Monolog\Logger; -use Slim\Csrf\Guard; use Slim\Views\Twig; use Slim\Views\TwigExtension; use UserFrosting\Assets\AssetLoader; @@ -33,6 +32,7 @@ use UserFrosting\I18n\LocalePathBuilder; use UserFrosting\Assets\Assets; use UserFrosting\Assets\AssetBundles\GulpBundleAssetsCompiledBundles as CompiledAssetBundles; +use UserFrosting\Sprinkle\Core\Csrf\SlimCsrfProvider; use UserFrosting\Sprinkle\Core\Util\RawAssetBundles; use UserFrosting\I18n\MessageTranslator; use UserFrosting\Session\Session; @@ -262,27 +262,7 @@ public function register(ContainerInterface $container) * @return \Slim\Csrf\Guard */ $container['csrf'] = function ($c) { - $csrfKey = $c->config['session.keys.csrf']; - - // Workaround so that we can pass storage into CSRF guard. - // If we tried to directly pass the indexed portion of `session` (for example, $c->session['site.csrf']), - // we would get an 'Indirect modification of overloaded element of UserFrosting\Session\Session' error. - // If we tried to assign an array and use that, PHP would only modify the local variable, and not the session. - // Since ArrayObject is an object, PHP will modify the object itself, allowing it to persist in the session. - if (!$c->session->has($csrfKey)) { - $c->session[$csrfKey] = new \ArrayObject(); - } - $csrfStorage = $c->session[$csrfKey]; - - $onFailure = function ($request, $response, $next) { - $e = new BadRequestException("The CSRF code was invalid or not provided."); - $e->addUserMessage('CSRF_MISSING'); - throw $e; - - return $next($request, $response); - }; - - return new Guard($c->config['csrf.name'], $csrfStorage, $onFailure, $c->config['csrf.storage_limit'], $c->config['csrf.strength'], $c->config['csrf.persistent_token']); + return SlimCsrfProvider::setupService($c); }; /** From 6ad8e4e22186d0d6c11f50a2a8a6b5215b4c5e77 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 10 Nov 2018 20:55:27 -0500 Subject: [PATCH 137/237] Adds PHP-CS-Fixer config --- .github/CONTRIBUTING.md | 15 +++++- .php_cs | 114 ++++++++++++++++++++++++++++++++++++++++ STYLE-GUIDE.md | 12 +++-- composer.json | 1 + 4 files changed, 137 insertions(+), 5 deletions(-) create mode 100755 .php_cs diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d78dfb5a2..46a180c97 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -123,7 +123,18 @@ To build the API documentation, install [ApiGen](http://www.apigen.org/) globall from inside your dev directory. +## Automatically fixing coding style with PHP-CS-Fixer + +[PHP-CS-Fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) can be used to automatically fix PHP code styling. UserFrosting provides a project specific configuration file ([`.php_cs`](.php_cs)) with a set of rules reflecting our [style guidelines](../STYLE-GUIDE.md). This tool should be used before submitting any code change to assure the style guidelines are met. Every sprinkles will also be parsed by the fixer. + +PHP-CS-Fixer is automatically loaded by Composer and can be used from the UserFrosting root directory : + +``` +app/vendor/bin/php-cs-fixer fix +``` + ## Useful tools -If you are using Atom, be sure to checkout theses useful packages : - - [Docblockr](https://atom.io/packages/docblockr) (Used to generate [documentation block](https://github.com/userfrosting/UserFrosting/blob/master/STYLE-GUIDE.md#documentation)) +If you are using **Atom**, be sure to checkout theses useful packages : + - [Docblockr](https://atom.io/packages/docblockr) : Used to generate [documentation block](https://github.com/userfrosting/UserFrosting/blob/master/STYLE-GUIDE.md#documentation). + - [php-ide-serenata](https://atom.io/packages/php-ide-serenata) : Integrates [Serenata](https://gitlab.com/Serenata/Serenata) as PHP IDE, providing autocompletion, code navigation, refactoring, signature help, linting and annotations. diff --git a/.php_cs b/.php_cs new file mode 100755 index 000000000..317f09e0e --- /dev/null +++ b/.php_cs @@ -0,0 +1,114 @@ + true, + 'array_syntax' => ['syntax' => 'short'], + 'binary_operator_spaces' => ['align_double_arrow' => true, 'align_equals' => false], + 'blank_line_after_namespace' => true, + 'blank_line_after_opening_tag' => true, + 'blank_line_before_return' => true, + 'braces' => true, + 'cast_spaces' => true, + 'class_definition' => true, + 'declare_equal_normalize' => true, + 'elseif' => true, + 'encoding' => true, + 'full_opening_tag' => true, + 'function_declaration' => true, + 'function_typehint_space' => true, + 'hash_to_slash_comment' => true, + 'heredoc_to_nowdoc' => true, + 'include' => true, + 'indentation_type' => true, + 'line_ending' => true, + 'lowercase_cast' => true, + 'lowercase_constants' => true, + 'lowercase_keywords' => true, + 'method_argument_space' => true, + 'method_separation' => true, + 'multiline_whitespace_before_semicolons' => true, + 'native_function_casing' => true, + 'new_with_braces' => true, + 'no_blank_lines_after_class_opening' => true, + 'no_blank_lines_after_phpdoc' => true, + 'no_break_comment' => true, + 'no_closing_tag' => true, + 'no_empty_phpdoc' => true, + 'no_empty_statement' => true, + 'no_extra_blank_lines' => true, + 'no_leading_import_slash' => true, + 'no_leading_namespace_whitespace' => true, + 'no_mixed_echo_print' => ['use' => 'echo'], + 'no_multiline_whitespace_around_double_arrow' => true, + 'no_short_bool_cast' => true, + 'no_singleline_whitespace_before_semicolons' => true, + 'no_spaces_after_function_name' => true, + 'no_spaces_around_offset' => true, + 'no_spaces_inside_parenthesis' => true, + 'no_trailing_comma_in_list_call' => true, + 'no_trailing_comma_in_singleline_array' => true, + 'no_trailing_whitespace' => true, + 'no_trailing_whitespace_in_comment' => true, + 'no_unneeded_control_parentheses' => true, + 'no_unreachable_default_argument_value' => true, + 'no_unused_imports' => true, + 'no_useless_return' => true, + 'no_whitespace_before_comma_in_array' => true, + 'no_whitespace_in_blank_line' => true, + 'normalize_index_brace' => true, + 'object_operator_without_whitespace' => true, + 'phpdoc_align' => true, + 'phpdoc_indent' => true, + 'phpdoc_inline_tag' => true, + 'phpdoc_no_empty_return' => true, + 'phpdoc_no_access' => true, + 'phpdoc_no_alias_tag' => ['type' => 'var'], + 'phpdoc_no_package' => true, + 'phpdoc_order' => true, + 'phpdoc_scalar' => true, + 'phpdoc_single_line_var_spacing' => true, + 'phpdoc_to_comment' => true, + 'phpdoc_trim' => true, + 'phpdoc_types' => true, + 'psr4' => true, + 'short_scalar_cast' => true, + 'simplified_null_return' => true, + 'single_blank_line_at_eof' => true, + 'single_blank_line_before_namespace' => true, + 'single_class_element_per_statement' => true, + 'single_import_per_statement' => true, + 'single_line_after_imports' => true, + 'single_quote' => true, + 'space_after_semicolon' => true, + 'standardize_not_equals' => true, + 'switch_case_semicolon_to_colon' => true, + 'switch_case_space' => true, + 'ternary_operator_spaces' => true, + 'trim_array_spaces' => true, + 'unary_operator_spaces' => true, + 'visibility_required' => true, + 'whitespace_after_comma_in_array' => true, + + 'header_comment' => [ + 'header' => $header, + 'separate' => 'bottom', + 'comment_type' => 'PHPDoc', + ] +]; + +$finder = PhpCsFixer\Finder::create() + ->exclude([ + 'vendor', + ]) + ->in([__DIR__ . '/app', __DIR__ . '/public']); + +return PhpCsFixer\Config::create() + ->setRules($rules) + ->setFinder($finder) + ->setUsingCache(true) + ->setRiskyAllowed(true); diff --git a/STYLE-GUIDE.md b/STYLE-GUIDE.md index 94c10b211..73dcc77fc 100644 --- a/STYLE-GUIDE.md +++ b/STYLE-GUIDE.md @@ -19,7 +19,7 @@ In addition: * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ ``` - + ### Classes - All classes MUST be prefaced with a documentation block containing a description and the author(s) of that class. You SHOULD add other descriptive properties as well. @@ -32,7 +32,7 @@ In addition: - Front controller (Slim) routes should be alphabetized, first by route type and then by route URL. If you have route groups, those should come first and be alphabetized as well. ### Variables - + - All class member variables and local variables MUST be declared in `camelCase`. ### Arrays @@ -40,5 +40,11 @@ In addition: - Array keys MUST be defined using `snake_case`. This is so they can be referenced in Twig and other templating languages. - Array keys MUST NOT contain `.`. This is because `.` is a reserved operator in Laravel and Twig's [dot syntax](https://medium.com/@assertchris/dot-notation-3fd3e42edc61). - Multidimensional arrays SHOULD be referenced using dot syntax whenever possible. So, instead of doing `$myArray['person1']['email']`, you should use `$myArray['person1.email']` if your array structure supports it. - + +### Tools + +[php-cs-fixer](https://github.com/FriendsOfPHP/PHP-CS-Fixer) can be used to automatically fix styling. See [Contributing](.github/CONTRIBUTING.md) for more info. + ### Twig Templates + +[TODO] \ No newline at end of file diff --git a/composer.json b/composer.json index 687ab555a..a321693a3 100755 --- a/composer.json +++ b/composer.json @@ -22,6 +22,7 @@ "wikimedia/composer-merge-plugin": "^1.4.0" }, "require-dev": { + "friendsofphp/php-cs-fixer": "^2.13", "phpunit/phpunit": "^5.7", "mockery/mockery": "1.0.0-alpha1", "league/factory-muffin": "^3.0", From ae8f72b36e5f54866dfd44590fd4cce9e890cf47 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 11 Nov 2018 10:12:53 -0500 Subject: [PATCH 138/237] Applied new PHP-CS-Fixer rules --- .php_cs | 1 - CHANGELOG.md | 1 + app/defines.php | 6 + app/sprinkles/account/config/debug.php | 23 +- app/sprinkles/account/config/default.php | 241 +++++----- app/sprinkles/account/config/production.php | 144 +++--- .../account/factories/Permissions.php | 9 +- app/sprinkles/account/factories/Roles.php | 7 +- app/sprinkles/account/factories/Users.php | 17 +- app/sprinkles/account/locale/ar/messages.php | 239 +++++----- app/sprinkles/account/locale/ar/validate.php | 13 +- .../account/locale/de_DE/messages.php | 246 +++++----- .../account/locale/de_DE/validate.php | 12 +- .../account/locale/en_US/messages.php | 246 +++++----- .../account/locale/en_US/validate.php | 12 +- .../account/locale/es_ES/messages.php | 251 ++++++----- .../account/locale/es_ES/validate.php | 12 +- app/sprinkles/account/locale/fa/messages.php | 234 +++++----- app/sprinkles/account/locale/fa/validate.php | 12 +- .../account/locale/fr_FR/messages.php | 236 +++++----- .../account/locale/fr_FR/validate.php | 10 +- .../account/locale/it_IT/messages.php | 247 +++++----- .../account/locale/it_IT/validate.php | 12 +- .../account/locale/pt_PT/messages.php | 218 ++++----- .../account/locale/pt_PT/validate.php | 10 +- .../account/locale/ru_RU/messages.php | 246 +++++----- .../account/locale/ru_RU/validate.php | 12 +- .../account/locale/th_TH/messages.php | 216 ++++----- .../account/locale/th_TH/validate.php | 10 +- app/sprinkles/account/locale/tr/messages.php | 246 +++++----- app/sprinkles/account/locale/tr/validate.php | 12 +- .../account/locale/zh_CN/messages.php | 234 +++++----- .../account/locale/zh_CN/validate.php | 12 +- app/sprinkles/account/routes/routes.php | 1 - app/sprinkles/account/src/Account.php | 1 + .../account/src/Account/Registration.php | 25 +- .../account/src/Authenticate/AuthGuard.php | 1 + .../src/Authenticate/Authenticator.php | 32 +- .../Exception/AccountDisabledException.php | 1 + .../Exception/AccountInvalidException.php | 1 + .../Exception/AccountNotVerifiedException.php | 1 + .../Exception/AuthCompromisedException.php | 1 + .../Exception/AuthExpiredException.php | 1 + .../Exception/InvalidCredentialsException.php | 1 + .../account/src/Authenticate/Hasher.php | 23 +- .../Authorize/AccessConditionExpression.php | 31 +- .../src/Authorize/AuthorizationException.php | 1 + .../src/Authorize/AuthorizationManager.php | 32 +- .../Authorize/ParserNodeFunctionEvaluator.php | 40 +- .../account/src/Bakery/CreateAdminUser.php | 51 ++- .../src/Controller/AccountController.php | 165 ++++--- .../Exception/SpammyRequestException.php | 1 + .../Migrations/v400/ActivitiesTable.php | 1 + .../Database/Migrations/v400/GroupsTable.php | 19 +- .../Migrations/v400/PasswordResetsTable.php | 3 +- .../Migrations/v400/PermissionRolesTable.php | 1 + .../Migrations/v400/PermissionsTable.php | 137 +++--- .../Migrations/v400/PersistencesTable.php | 1 + .../Migrations/v400/RoleUsersTable.php | 1 + .../Database/Migrations/v400/RolesTable.php | 13 +- .../Database/Migrations/v400/UsersTable.php | 11 +- .../Migrations/v400/VerificationsTable.php | 1 + .../account/src/Database/Models/Activity.php | 21 +- .../account/src/Database/Models/Group.php | 12 +- .../Models/Interfaces/UserInterface.php | 17 +- .../src/Database/Models/PasswordReset.php | 16 +- .../src/Database/Models/Permission.php | 20 +- .../account/src/Database/Models/Role.php | 14 +- .../account/src/Database/Models/User.php | 33 +- .../src/Database/Models/Verification.php | 16 +- .../AuthCompromisedExceptionHandler.php | 1 + .../Handler/AuthExpiredExceptionHandler.php | 1 + .../Handler/ForbiddenExceptionHandler.php | 3 +- .../account/src/Facades/Password.php | 1 + .../src/Log/UserActivityDatabaseHandler.php | 1 + .../account/src/Log/UserActivityProcessor.php | 3 +- .../Repository/PasswordResetRepository.php | 1 + .../src/Repository/TokenRepository.php | 30 +- .../src/Repository/VerificationRepository.php | 1 + .../src/ServicesProvider/ServicesProvider.php | 72 +-- .../account/src/Twig/AccountExtension.php | 6 +- .../account/src/Util/HashFailedException.php | 1 + app/sprinkles/account/src/Util/Util.php | 7 +- .../tests/Integration/AuthenticatorTest.php | 14 +- .../Integration/AuthorizationManagerTest.php | 36 +- .../account/tests/Unit/FactoriesTest.php | 1 + .../account/tests/Unit/HasherTest.php | 7 +- .../account/tests/Unit/RegistrationTest.php | 1 + app/sprinkles/account/tests/withTestUser.php | 22 +- app/sprinkles/admin/locale/ar/messages.php | 202 ++++----- app/sprinkles/admin/locale/de_DE/messages.php | 252 +++++------ app/sprinkles/admin/locale/en_US/messages.php | 254 +++++------ app/sprinkles/admin/locale/es_ES/messages.php | 258 +++++------ app/sprinkles/admin/locale/fa/messages.php | 248 +++++----- app/sprinkles/admin/locale/fr_FR/messages.php | 229 +++++----- app/sprinkles/admin/locale/it_IT/messages.php | 250 +++++------ app/sprinkles/admin/locale/pt_PT/messages.php | 210 ++++----- app/sprinkles/admin/locale/ru_RU/messages.php | 254 +++++------ app/sprinkles/admin/locale/th_TH/messages.php | 200 ++++----- app/sprinkles/admin/locale/tr/messages.php | 254 +++++------ app/sprinkles/admin/locale/zh_CN/messages.php | 252 +++++------ app/sprinkles/admin/src/Admin.php | 1 + .../src/Controller/ActivityController.php | 13 +- .../admin/src/Controller/AdminController.php | 32 +- .../admin/src/Controller/GroupController.php | 118 ++--- .../src/Controller/PermissionController.php | 35 +- .../admin/src/Controller/RoleController.php | 140 +++--- .../admin/src/Controller/UserController.php | 188 ++++---- .../src/ServicesProvider/ServicesProvider.php | 8 +- .../admin/src/Sprunje/ActivitySprunje.php | 11 +- .../admin/src/Sprunje/GroupSprunje.php | 1 + .../admin/src/Sprunje/PermissionSprunje.php | 15 +- .../src/Sprunje/PermissionUserSprunje.php | 3 +- .../admin/src/Sprunje/RoleSprunje.php | 6 +- .../src/Sprunje/UserPermissionSprunje.php | 3 +- .../admin/src/Sprunje/UserSprunje.php | 37 +- .../tests/Integration/AdminControllerTest.php | 11 +- .../admin/tests/Integration/SprunjeTests.php | 6 + app/sprinkles/core/config/debug.php | 55 +-- app/sprinkles/core/config/default.php | 101 +++-- app/sprinkles/core/config/production.php | 105 ++--- app/sprinkles/core/config/testing.php | 127 +++--- app/sprinkles/core/defines.php | 6 + app/sprinkles/core/extra/adjectives.php | 6 + app/sprinkles/core/extra/nouns.php | 6 + app/sprinkles/core/locale/ar/errors.php | 52 +-- app/sprinkles/core/locale/ar/messages.php | 156 +++---- app/sprinkles/core/locale/ar/validate.php | 24 +- app/sprinkles/core/locale/de_DE/errors.php | 52 +-- app/sprinkles/core/locale/de_DE/messages.php | 162 +++---- app/sprinkles/core/locale/de_DE/validate.php | 32 +- app/sprinkles/core/locale/en_US/errors.php | 53 +-- app/sprinkles/core/locale/en_US/messages.php | 162 +++---- app/sprinkles/core/locale/en_US/validate.php | 38 +- app/sprinkles/core/locale/es_ES/errors.php | 56 +-- app/sprinkles/core/locale/es_ES/messages.php | 154 +++---- app/sprinkles/core/locale/es_ES/validate.php | 42 +- app/sprinkles/core/locale/fa/errors.php | 54 +-- app/sprinkles/core/locale/fa/messages.php | 144 +++--- app/sprinkles/core/locale/fa/validate.php | 32 +- app/sprinkles/core/locale/fr_FR/errors.php | 52 +-- app/sprinkles/core/locale/fr_FR/messages.php | 144 +++--- app/sprinkles/core/locale/fr_FR/validate.php | 38 +- app/sprinkles/core/locale/it_IT/errors.php | 52 +-- app/sprinkles/core/locale/it_IT/messages.php | 164 +++---- app/sprinkles/core/locale/it_IT/validate.php | 32 +- app/sprinkles/core/locale/pt_PT/errors.php | 52 +-- app/sprinkles/core/locale/pt_PT/messages.php | 138 +++--- app/sprinkles/core/locale/pt_PT/validate.php | 24 +- app/sprinkles/core/locale/ru_RU/errors.php | 54 +-- app/sprinkles/core/locale/ru_RU/messages.php | 162 +++---- app/sprinkles/core/locale/ru_RU/validate.php | 38 +- app/sprinkles/core/locale/th_TH/errors.php | 52 +-- app/sprinkles/core/locale/th_TH/messages.php | 138 +++--- app/sprinkles/core/locale/th_TH/validate.php | 24 +- app/sprinkles/core/locale/valitron/ar.php | 48 +- app/sprinkles/core/locale/valitron/de.php | 58 +-- app/sprinkles/core/locale/valitron/el.php | 60 +-- app/sprinkles/core/locale/valitron/en.php | 60 +-- app/sprinkles/core/locale/valitron/es.php | 60 +-- app/sprinkles/core/locale/valitron/fr.php | 52 ++- app/sprinkles/core/locale/valitron/id.php | 58 +-- app/sprinkles/core/locale/valitron/it.php | 54 ++- app/sprinkles/core/locale/valitron/ja.php | 68 +-- app/sprinkles/core/locale/valitron/lv.php | 54 ++- app/sprinkles/core/locale/valitron/pt-br.php | 48 +- app/sprinkles/core/locale/valitron/ro.php | 61 +-- app/sprinkles/core/locale/valitron/ru.php | 64 +-- app/sprinkles/core/locale/valitron/th.php | 60 +-- app/sprinkles/core/locale/valitron/zh-cn.php | 48 +- app/sprinkles/core/locale/valitron/zh-tw.php | 48 +- app/sprinkles/core/locale/zh_CN/errors.php | 50 +-- app/sprinkles/core/locale/zh_CN/messages.php | 142 +++--- app/sprinkles/core/locale/zh_CN/validate.php | 30 +- app/sprinkles/core/routes/routes.php | 1 - app/sprinkles/core/src/Alert/AlertStream.php | 37 +- .../core/src/Alert/CacheAlertStream.php | 9 +- .../core/src/Alert/SessionAlertStream.php | 7 +- app/sprinkles/core/src/Bakery/BakeCommand.php | 7 +- .../core/src/Bakery/ClearCacheCommand.php | 18 +- .../core/src/Bakery/DebugCommand.php | 50 ++- .../core/src/Bakery/MigrateCommand.php | 15 +- .../core/src/Bakery/MigrateRefreshCommand.php | 15 +- .../core/src/Bakery/MigrateResetCommand.php | 16 +- .../src/Bakery/MigrateRollbackCommand.php | 12 +- .../core/src/Bakery/MigrateStatusCommand.php | 24 +- .../core/src/Bakery/RouteListCommand.php | 15 +- app/sprinkles/core/src/Bakery/SeedCommand.php | 3 +- .../core/src/Bakery/SeedListCommand.php | 3 +- .../core/src/Bakery/SetupCommand.php | 7 +- .../core/src/Bakery/SetupDbCommand.php | 134 +++--- .../core/src/Bakery/SetupEnvCommand.php | 15 +- .../core/src/Bakery/SetupSmtpCommand.php | 32 +- .../core/src/Controller/CoreController.php | 39 +- .../core/src/Controller/SimpleController.php | 1 + app/sprinkles/core/src/Core.php | 5 +- .../core/src/Csrf/CsrfProviderInterface.php | 9 +- .../core/src/Csrf/SlimCsrfProvider.php | 7 +- app/sprinkles/core/src/Database/Builder.php | 31 +- .../src/Database/DatabaseInvalidException.php | 1 + .../core/src/Database/EloquentBuilder.php | 13 +- app/sprinkles/core/src/Database/Migration.php | 1 + .../core/src/Database/MigrationInterface.php | 1 + .../Migrations/v400/SessionsTable.php | 1 + .../Migrations/v400/ThrottlesTable.php | 1 + .../Migrator/DatabaseMigrationRepository.php | 26 +- .../Migrator/MigrationDependencyAnalyser.php | 18 +- .../Database/Migrator/MigrationLocator.php | 9 +- .../Migrator/MigrationLocatorInterface.php | 1 + .../Migrator/MigrationRepositoryInterface.php | 13 +- .../MigrationRollbackDependencyAnalyser.php | 7 +- .../core/src/Database/Migrator/Migrator.php | 55 ++- .../Models/Concerns/HasRelationships.php | 92 ++-- .../core/src/Database/Models/Model.php | 18 +- .../core/src/Database/Models/Throttle.php | 9 +- .../Relations/BelongsToManyConstrained.php | 33 +- .../Relations/BelongsToManyThrough.php | 31 +- .../Relations/BelongsToManyUnique.php | 1 + .../Database/Relations/Concerns/Syncable.php | 11 +- .../Database/Relations/Concerns/Unique.php | 59 +-- .../Database/Relations/HasManySyncable.php | 1 + .../Database/Relations/MorphManySyncable.php | 1 + .../Database/Relations/MorphToManyUnique.php | 1 + .../core/src/Database/Seeder/BaseSeed.php | 2 +- .../src/Database/Seeder/SeedInterface.php | 1 + .../core/src/Database/Seeder/Seeder.php | 22 +- .../src/Error/ExceptionHandlerManager.php | 19 +- .../src/Error/Handler/ExceptionHandler.php | 12 +- .../Handler/ExceptionHandlerInterface.php | 1 + .../Error/Handler/HttpExceptionHandler.php | 4 +- .../Handler/NotFoundExceptionHandler.php | 2 +- .../Handler/PhpMailerExceptionHandler.php | 3 +- .../core/src/Error/Renderer/ErrorRenderer.php | 10 +- .../Error/Renderer/ErrorRendererInterface.php | 9 +- .../core/src/Error/Renderer/HtmlRenderer.php | 17 +- .../core/src/Error/Renderer/JsonRenderer.php | 14 +- .../src/Error/Renderer/PlainTextRenderer.php | 3 +- .../src/Error/Renderer/WhoopsRenderer.php | 175 ++++---- .../core/src/Error/Renderer/XmlRenderer.php | 13 +- app/sprinkles/core/src/Facades/Config.php | 1 + app/sprinkles/core/src/Facades/Debug.php | 1 + app/sprinkles/core/src/Facades/Storage.php | 1 + app/sprinkles/core/src/Facades/Translator.php | 1 + .../core/src/Filesystem/FilesystemManager.php | 13 +- .../Http/Concerns/DeterminesContentType.php | 7 +- .../core/src/Log/DatabaseHandler.php | 9 +- app/sprinkles/core/src/Log/MixedFormatter.php | 4 +- .../core/src/Mail/EmailRecipient.php | 26 +- app/sprinkles/core/src/Mail/MailMessage.php | 16 +- app/sprinkles/core/src/Mail/Mailer.php | 41 +- .../core/src/Mail/StaticMailMessage.php | 5 +- .../core/src/Mail/TwigMailMessage.php | 7 +- app/sprinkles/core/src/Model/UFModel.php | 3 +- app/sprinkles/core/src/Router.php | 17 +- .../src/ServicesProvider/ServicesProvider.php | 23 +- .../core/src/Session/NullSessionHandler.php | 8 +- app/sprinkles/core/src/Sprunje/Sprunje.php | 59 +-- .../core/src/Throttle/ThrottleRule.php | 13 +- app/sprinkles/core/src/Throttle/Throttler.php | 20 +- .../core/src/Throttle/ThrottlerException.php | 1 + app/sprinkles/core/src/Twig/CacheHelper.php | 4 +- app/sprinkles/core/src/Twig/CoreExtension.php | 14 +- .../core/src/Util/BadClassNameException.php | 1 + app/sprinkles/core/src/Util/Captcha.php | 21 +- .../core/src/Util/CheckEnvironment.php | 116 ++--- app/sprinkles/core/src/Util/ClassMapper.php | 10 +- .../core/src/Util/EnvironmentInfo.php | 5 +- .../core/src/Util/RawAssetBundles.php | 119 +++-- .../core/src/Util/ShutdownHandler.php | 30 +- app/sprinkles/core/src/Util/Util.php | 25 +- .../core/tests/ControllerTestCase.php | 6 +- .../core/tests/DatabaseTransactions.php | 1 + .../Integration/BakeryMigrateCommandTest.php | 3 +- .../BakeryMigrateRefreshCommandTest.php | 1 + .../BakeryMigrateResetCommandTest.php | 1 + .../BakeryMigrateRollbackCommandTest.php | 1 + .../BakeryMigrateStatusCommandTest.php | 5 +- .../Integration/CheckEnvironmentTest.php | 6 + .../Controllers/CoreControllerTest.php | 12 +- .../DatabaseMigratorIntegrationTest.php | 2 +- .../DatabaseMigratorServiceTest.php | 3 +- .../Integration/DatabaseMigratorTest.php | 3 +- .../core/tests/Integration/DatabaseTests.php | 425 +++++++++--------- .../Error/Handler/ExceptionHandlerTest.php | 7 + .../Error/Renderer/WhoopsRendererTest.php | 18 +- .../MigrationDependencyAnalyserTest.php | 1 + .../Integration/MigrationLocatorTest.php | 1 + .../Integration/MigrationRepositoryTest.php | 1 + .../Migrations/DeprecatedClassTable.php | 6 + .../Migrations/UnfulfillableTable.php | 6 + .../one/CreatePasswordResetsTable.php | 6 + .../Migrations/one/CreateUsersTable.php | 8 +- .../Migrations/two/CreateFlightsTable.php | 6 + .../tests/Integration/Seeder/SeederTests.php | 40 +- .../tests/Integration/Seeder/Seeds/Seed1.php | 8 +- .../tests/Integration/Seeder/Seeds/Seed2.php | 8 +- .../Integration/Seeder/Seeds/Test/Seed.php | 8 +- app/sprinkles/core/tests/RefreshDatabase.php | 4 +- app/sprinkles/core/tests/TestDatabase.php | 1 + .../tests/Unit/BelongsToManyThroughTest.php | 5 +- .../core/tests/Unit/DatabaseSyncableTest.php | 10 +- .../core/tests/Unit/FilesystemTest.php | 13 +- app/sprinkles/core/tests/Unit/RouterTest.php | 6 + app/sprinkles/core/tests/Unit/SprunjeTest.php | 1 + .../core/tests/Unit/TestDatabaseTraitTest.php | 1 + app/system/Bakery/Bakery.php | 15 +- app/system/Bakery/BaseCommand.php | 8 +- app/system/Bakery/Command/BuildAssets.php | 57 +-- app/system/Bakery/Command/Test.php | 15 +- app/system/Bakery/ConfirmableTrait.php | 10 +- app/system/Bakery/DatabaseTest.php | 7 +- app/system/Bakery/Migration.php | 5 +- app/system/Facade.php | 17 +- app/system/ServicesProvider.php | 1 + app/system/SlimAppEvent.php | 1 + app/system/Sprinkle/Sprinkle.php | 1 + app/system/Sprinkle/SprinkleManager.php | 13 +- app/system/UserFrosting.php | 24 +- app/tests/DatabaseTransactions.php | 1 + app/tests/TestCase.php | 26 +- app/tests/Unit/ExampleTest.php | 6 + 321 files changed, 7531 insertions(+), 6954 deletions(-) diff --git a/.php_cs b/.php_cs index 317f09e0e..57610a595 100755 --- a/.php_cs +++ b/.php_cs @@ -72,7 +72,6 @@ $rules = [ 'phpdoc_order' => true, 'phpdoc_scalar' => true, 'phpdoc_single_line_var_spacing' => true, - 'phpdoc_to_comment' => true, 'phpdoc_trim' => true, 'phpdoc_types' => true, 'psr4' => true, diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b98f7e61..5edcffbd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `withTestUser` trait for helper methods when running tests requiring a user - Added `ControllerTestCase` special test case to help testing controllers - Improved overall test coverage and added coverage config to `phpunit.xml` +- Added code style config (`.php_cs`) and instructions for PHP-CS-Fixer in Readme ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle diff --git a/app/defines.php b/app/defines.php index cb0724681..5b4b14025 100755 --- a/app/defines.php +++ b/app/defines.php @@ -1,4 +1,10 @@ [ - 'auth' => true - ], - ]; +/* + * Debug development config file for UserFrosting. Sets every debug options on to help debug what's going wrong + */ +return [ + 'debug' => [ + 'auth' => true + ], +]; diff --git a/app/sprinkles/account/config/default.php b/app/sprinkles/account/config/default.php index b26179b44..71c689696 100644 --- a/app/sprinkles/account/config/default.php +++ b/app/sprinkles/account/config/default.php @@ -1,131 +1,136 @@ [ + 'auth' => false + ], - return [ - /** - * ---------------------------------------------------------------------- - * AuthorizationManager Debug - * ---------------------------------------------------------------------- - * Turn this on to send AuthorizationManager::checkAccess process details - * to log. This can help debugging your permissions and roles - */ - 'debug' => [ - 'auth' => false - ], + /* + * ---------------------------------------------------------------------- + * Configuration for the 'password reset' feature + * ---------------------------------------------------------------------- + */ + 'password_reset' => [ + 'algorithm' => 'sha512', + 'timeouts' => [ + 'create' => 86400, + 'reset' => 10800 + ] + ], - /** - * ---------------------------------------------------------------------- - * Configuration for the 'password reset' feature - * ---------------------------------------------------------------------- - */ - 'password_reset' => [ - 'algorithm' => 'sha512', - 'timeouts' => [ - 'create' => 86400, - 'reset' => 10800 - ] + /* + * ---------------------------------------------------------------------- + * RememberMe Package Settings + * ---------------------------------------------------------------------- + * See https://github.com/gbirke/rememberme for an explanation of these settings + */ + 'remember_me' => [ + 'cookie' => [ + 'name' => 'rememberme' ], - - /** - * ---------------------------------------------------------------------- - * RememberMe Package Settings - * ---------------------------------------------------------------------- - * See https://github.com/gbirke/rememberme for an explanation of these settings - */ - 'remember_me' => [ - 'cookie' => [ - 'name' => 'rememberme' - ], - 'expire_time' => 604800, - 'session' => [ - 'path' => '/' - ], - 'table' => [ - 'tableName' => 'persistences', - 'credentialColumn' => 'user_id', - 'tokenColumn' => 'token', - 'persistentTokenColumn' => 'persistent_token', - 'expiresColumn' => 'expires_at' - ] + 'expire_time' => 604800, + 'session' => [ + 'path' => '/' ], + 'table' => [ + 'tableName' => 'persistences', + 'credentialColumn' => 'user_id', + 'tokenColumn' => 'token', + 'persistentTokenColumn' => 'persistent_token', + 'expiresColumn' => 'expires_at' + ] + ], - /** - * ---------------------------------------------------------------------- - * Reserved user IDs - * ---------------------------------------------------------------------- - * Master (root) user will be the one with this user id. Same goes for - * guest users - */ - 'reserved_user_ids' => [ - 'guest' => -1, - 'master' => 1 - ], + /* + * ---------------------------------------------------------------------- + * Reserved user IDs + * ---------------------------------------------------------------------- + * Master (root) user will be the one with this user id. Same goes for + * guest users + */ + 'reserved_user_ids' => [ + 'guest' => -1, + 'master' => 1 + ], - /** - * ---------------------------------------------------------------------- - * Account Session config - * ---------------------------------------------------------------------- - * The keys used in the session to store info about authenticated users - */ - 'session' => [ - 'keys' => [ - 'current_user_id' => 'account.current_user_id', // the key to use for storing the authenticated user's id - 'captcha' => 'account.captcha' // Key used to store a captcha hash during captcha verification - ] - ], + /* + * ---------------------------------------------------------------------- + * Account Session config + * ---------------------------------------------------------------------- + * The keys used in the session to store info about authenticated users + */ + 'session' => [ + 'keys' => [ + 'current_user_id' => 'account.current_user_id', // the key to use for storing the authenticated user's id + 'captcha' => 'account.captcha' // Key used to store a captcha hash during captcha verification + ] + ], - /** - * ---------------------------------------------------------------------- - * Account Site Settings - * ---------------------------------------------------------------------- - * "Site" settings that are automatically passed to Twig. Use theses - * settings to control the login and registration process - */ - 'site' => [ - 'login' => [ - 'enable_email' => true // Set to false to allow login by username only - ], - 'registration' => [ - 'enabled' => true, //if this set to false, you probably want to also set require_email_verification to false as well to disable the link on the signup page - 'captcha' => true, - 'require_email_verification' => true, - // Default roles and other settings for newly registered users - 'user_defaults' => [ - 'locale' => 'en_US', - 'group' => 'terran', - 'roles' => [ - 'user' => true - ] + /* + * ---------------------------------------------------------------------- + * Account Site Settings + * ---------------------------------------------------------------------- + * "Site" settings that are automatically passed to Twig. Use theses + * settings to control the login and registration process + */ + 'site' => [ + 'login' => [ + 'enable_email' => true // Set to false to allow login by username only + ], + 'registration' => [ + 'enabled' => true, //if this set to false, you probably want to also set require_email_verification to false as well to disable the link on the signup page + 'captcha' => true, + 'require_email_verification' => true, + // Default roles and other settings for newly registered users + 'user_defaults' => [ + 'locale' => 'en_US', + 'group' => 'terran', + 'roles' => [ + 'user' => true ] ] - ], + ] + ], - /** - * ---------------------------------------------------------------------- - * Throttles Configuration - * ---------------------------------------------------------------------- - * No throttling is enforced by default. Everything is setup in - * production mode. See http://security.stackexchange.com/a/59550/74909 - * for the inspiration for our throttling system - */ - 'throttles' => [ - 'check_username_request' => null, - 'password_reset_request' => null, - 'registration_attempt' => null, - 'sign_in_attempt' => null, - 'verification_request' => null - ], + /* + * ---------------------------------------------------------------------- + * Throttles Configuration + * ---------------------------------------------------------------------- + * No throttling is enforced by default. Everything is setup in + * production mode. See http://security.stackexchange.com/a/59550/74909 + * for the inspiration for our throttling system + */ + 'throttles' => [ + 'check_username_request' => null, + 'password_reset_request' => null, + 'registration_attempt' => null, + 'sign_in_attempt' => null, + 'verification_request' => null + ], - /** - * ---------------------------------------------------------------------- - * Configuration for the 'email verification' feature - * ---------------------------------------------------------------------- - */ - 'verification' => [ - 'algorithm' => 'sha512', - 'timeout' => 10800 - ] - ]; + /* + * ---------------------------------------------------------------------- + * Configuration for the 'email verification' feature + * ---------------------------------------------------------------------- + */ + 'verification' => [ + 'algorithm' => 'sha512', + 'timeout' => 10800 + ] +]; diff --git a/app/sprinkles/account/config/production.php b/app/sprinkles/account/config/production.php index 0935f0fc1..d2281feee 100644 --- a/app/sprinkles/account/config/production.php +++ b/app/sprinkles/account/config/production.php @@ -1,74 +1,78 @@ [ - 'check_username_request' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 40 => 1000 - ] - ], - 'password_reset_request' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 2 => 5, - 3 => 10, - 4 => 20, - 5 => 40, - 6 => 80, - 7 => 600 - ] - ], - 'registration_attempt' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 2 => 5, - 3 => 10, - 4 => 20, - 5 => 40, - 6 => 80, - 7 => 600 - ] - ], - 'sign_in_attempt' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 4 => 5, - 5 => 10, - 6 => 20, - 7 => 40, - 8 => 80, - 9 => 600 - ] - ], - 'verification_request' => [ - 'method' => 'ip', - 'interval' => 3600, - 'delays' => [ - 2 => 5, - 3 => 10, - 4 => 20, - 5 => 40, - 6 => 80, - 7 => 600 - ] +/* + * Account production config file for UserFrosting. You may override/extend this in your site's configuration file to customize deploy settings. + */ +return [ + /* + * ---------------------------------------------------------------------- + * Throttles Configuration + * ---------------------------------------------------------------------- + * Enable throttling in production mode. + * See http://security.stackexchange.com/a/59550/74909 for the + * inspiration for our throttling system + */ + 'throttles' => [ + 'check_username_request' => [ + 'method' => 'ip', + 'interval' => 3600, + 'delays' => [ + 40 => 1000 + ] + ], + 'password_reset_request' => [ + 'method' => 'ip', + 'interval' => 3600, + 'delays' => [ + 2 => 5, + 3 => 10, + 4 => 20, + 5 => 40, + 6 => 80, + 7 => 600 + ] + ], + 'registration_attempt' => [ + 'method' => 'ip', + 'interval' => 3600, + 'delays' => [ + 2 => 5, + 3 => 10, + 4 => 20, + 5 => 40, + 6 => 80, + 7 => 600 + ] + ], + 'sign_in_attempt' => [ + 'method' => 'ip', + 'interval' => 3600, + 'delays' => [ + 4 => 5, + 5 => 10, + 6 => 20, + 7 => 40, + 8 => 80, + 9 => 600 + ] + ], + 'verification_request' => [ + 'method' => 'ip', + 'interval' => 3600, + 'delays' => [ + 2 => 5, + 3 => 10, + 4 => 20, + 5 => 40, + 6 => 80, + 7 => 600 ] ] - ]; + ] +]; diff --git a/app/sprinkles/account/factories/Permissions.php b/app/sprinkles/account/factories/Permissions.php index 591f5fdf4..17b666237 100644 --- a/app/sprinkles/account/factories/Permissions.php +++ b/app/sprinkles/account/factories/Permissions.php @@ -5,15 +5,14 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ - use League\FactoryMuffin\Faker\Facade as Faker; -/** +/* * General factory for the Permission Model */ $fm->define('UserFrosting\Sprinkle\Account\Database\Models\Permission')->setDefinitions([ - 'slug' => Faker::word(), - 'name' => Faker::word(), + 'slug' => Faker::word(), + 'name' => Faker::word(), 'description' => Faker::paragraph(), - 'conditions' => Faker::word() + 'conditions' => Faker::word() ]); diff --git a/app/sprinkles/account/factories/Roles.php b/app/sprinkles/account/factories/Roles.php index cdbb5a308..84782bf73 100644 --- a/app/sprinkles/account/factories/Roles.php +++ b/app/sprinkles/account/factories/Roles.php @@ -5,14 +5,13 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ - use League\FactoryMuffin\Faker\Facade as Faker; -/** +/* * General factory for the Role Model */ $fm->define('UserFrosting\Sprinkle\Account\Database\Models\Role')->setDefinitions([ - 'slug' => Faker::unique()->word(), - 'name' => Faker::word(), + 'slug' => Faker::unique()->word(), + 'name' => Faker::word(), 'description' => Faker::paragraph() ]); diff --git a/app/sprinkles/account/factories/Users.php b/app/sprinkles/account/factories/Users.php index 7390c4448..652303816 100644 --- a/app/sprinkles/account/factories/Users.php +++ b/app/sprinkles/account/factories/Users.php @@ -5,19 +5,18 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ - use League\FactoryMuffin\Faker\Facade as Faker; -/** +/* * General factory for the User Model */ $fm->define('UserFrosting\Sprinkle\Account\Database\Models\User')->setDefinitions([ - 'user_name' => Faker::unique()->firstNameMale(), - 'first_name' => Faker::firstNameMale(), - 'last_name' => Faker::firstNameMale(), - 'email' => Faker::unique()->email(), - 'locale' => 'en_US', + 'user_name' => Faker::unique()->firstNameMale(), + 'first_name' => Faker::firstNameMale(), + 'last_name' => Faker::firstNameMale(), + 'email' => Faker::unique()->email(), + 'locale' => 'en_US', 'flag_verified' => 1, - 'flag_enabled' => 1, - 'password' => Faker::password() + 'flag_enabled' => 1, + 'password' => Faker::password() ]); diff --git a/app/sprinkles/account/locale/ar/messages.php b/app/sprinkles/account/locale/ar/messages.php index 72039047b..5433b488c 100644 --- a/app/sprinkles/account/locale/ar/messages.php +++ b/app/sprinkles/account/locale/ar/messages.php @@ -4,173 +4,174 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Modern Standard Arabic message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\ar - * @author Alexander Weissman and Abdullah Seba + * @author Alexander Weissman + * @author Abdullah Seba */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "الحساب", + 'ACCOUNT' => [ + '@TRANSLATION' => 'الحساب', - "ACCESS_DENIED" => "يبدو أنك لا تملك صلاحية للقيام بذلك", + 'ACCESS_DENIED' => 'يبدو أنك لا تملك صلاحية للقيام بذلك', - "DISABLED" => "هذا الحساب معطل يمكنك الاتصال بنا للحصول على مزيد من المعلومات", + 'DISABLED' => 'هذا الحساب معطل يمكنك الاتصال بنا للحصول على مزيد من المعلومات', - "EMAIL_UPDATED" => "تم تجديد البريد الإلكتروني بالحساب", + 'EMAIL_UPDATED' => 'تم تجديد البريد الإلكتروني بالحساب', - "INVALID" => "هذا الحساب غير موجود قد تم حذفه يمكنك الاتصا بنا للحصول على مزيد من المعلومات", + 'INVALID' => 'هذا الحساب غير موجود قد تم حذفه يمكنك الاتصا بنا للحصول على مزيد من المعلومات', - "MASTER_NOT_EXISTS" => "لا يمكنك تسجيل حساب جديد حتى تم إنشاء الحساب الرئيسي", - "MY" => "حسابي", + 'MASTER_NOT_EXISTS' => 'لا يمكنك تسجيل حساب جديد حتى تم إنشاء الحساب الرئيسي', + 'MY' => 'حسابي', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "تم اختراق جلسنك يجب عليك الخروج على كافة الأجهزة، ثم تسجيل الدخول مرة أخرى والتأكد من أن المعلومات الخاصة بك لم يعبث بها", - "TITLE" => "من الممكن أن حسابك قد اخترق", - "TEXT" => "ربما استخدم شخص معلومات التسجيل الدخول للدخول إلى هذه الصفحة. لسلامتك، تم انتهاء جميع الجلسات يرجا التسجيل مرة اخرى وتحقق من حسابك بسبب النشاط الغريب قد ترغب في تغيير كلمة المرور" + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => 'تم اختراق جلسنك يجب عليك الخروج على كافة الأجهزة، ثم تسجيل الدخول مرة أخرى والتأكد من أن المعلومات الخاصة بك لم يعبث بها', + 'TITLE' => 'من الممكن أن حسابك قد اخترق', + 'TEXT' => 'ربما استخدم شخص معلومات التسجيل الدخول للدخول إلى هذه الصفحة. لسلامتك، تم انتهاء جميع الجلسات يرجا التسجيل مرة اخرى وتحقق من حسابك بسبب النشاط الغريب قد ترغب في تغيير كلمة المرور' ], - "SESSION_EXPIRED" => "انتهت جلستك تستطيع تسجيل الدخول مرة أخرى", + 'SESSION_EXPIRED' => 'انتهت جلستك تستطيع تسجيل الدخول مرة أخرى', - "SETTINGS" => [ - "@TRANSLATION" => "إعدادات الحساب", - "DESCRIPTION" => "غير إعدادات حسابك، بما في ذلك البريد الإلكتروني، واسم وكلمة المرور -", - "UPDATED" => "تم تجديد إعدادات الحساب" + 'SETTINGS' => [ + '@TRANSLATION' => 'إعدادات الحساب', + 'DESCRIPTION' => 'غير إعدادات حسابك، بما في ذلك البريد الإلكتروني، واسم وكلمة المرور +', + 'UPDATED' => 'تم تجديد إعدادات الحساب' ], - "TOOLS" => "أدوات الحساب", + 'TOOLS' => 'أدوات الحساب', - "UNVERIFIED" => "لم يتم التحقق من حسابك بعد افحص في رسائل البريد الإلكتروني و ملف البريد المزعج للحصول على تعليمات تفعيل الحساب", + 'UNVERIFIED' => 'لم يتم التحقق من حسابك بعد افحص في رسائل البريد الإلكتروني و ملف البريد المزعج للحصول على تعليمات تفعيل الحساب', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "لقد أرسلنا رابط جديدا لتحقق عبر البريد الإلكتروني إلى {{email}} افحص في رسائل البريد الإلكتروني و ملف البريد المزعج", - "RESEND" => "إعادة ارسال بريد التحقق", - "COMPLETE" => "لقد تم التحقق من حسابك بنجاح يمكنك الآن تسجيل الدخول", - "EMAIL" => "ادخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل، و سوف نرسل البريد الإلكتروني لتحقق مرة أخرى", - "PAGE" => "إعادة إرسال البريد الإلكتروني التحقق من حسابك الجديد", - "SEND" => "ارسل رابط للتحقق عبر البريد الالكتروني", - "TOKEN_NOT_FOUND" => "رمز التحقق غير موجود أو تم تحقق الحساب من قبل", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'لقد أرسلنا رابط جديدا لتحقق عبر البريد الإلكتروني إلى {{email}} افحص في رسائل البريد الإلكتروني و ملف البريد المزعج', + 'RESEND' => 'إعادة ارسال بريد التحقق', + 'COMPLETE' => 'لقد تم التحقق من حسابك بنجاح يمكنك الآن تسجيل الدخول', + 'EMAIL' => 'ادخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل، و سوف نرسل البريد الإلكتروني لتحقق مرة أخرى', + 'PAGE' => 'إعادة إرسال البريد الإلكتروني التحقق من حسابك الجديد', + 'SEND' => 'ارسل رابط للتحقق عبر البريد الالكتروني', + 'TOKEN_NOT_FOUND' => 'رمز التحقق غير موجود أو تم تحقق الحساب من قبل', ] ], - "EMAIL" => [ - "INVALID" => "لا يوجد حساب ل {{email}}", - "IN_USE" => "البريد الإلكتروني {{email}} قيد الاستخدام" + 'EMAIL' => [ + 'INVALID' => 'لا يوجد حساب ل {{email}}', + 'IN_USE' => 'البريد الإلكتروني {{email}} قيد الاستخدام' ], - "FIRST_NAME" => "الاسم الاول", + 'FIRST_NAME' => 'الاسم الاول', - "HEADER_MESSAGE_ROOT" => "تسجيل الدخول باسم المستخدم ROOT", + 'HEADER_MESSAGE_ROOT' => 'تسجيل الدخول باسم المستخدم ROOT', - "LAST_NAME" => "اسم العائلة", + 'LAST_NAME' => 'اسم العائلة', - "LOCALEACCOUNT" => "اللغة التي تستخدم لحسابك", + 'LOCALEACCOUNT' => 'اللغة التي تستخدم لحسابك', - "LOGIN" => [ - "@TRANSLATION" => "تسجيل الدخول", + 'LOGIN' => [ + '@TRANSLATION' => 'تسجيل الدخول', - "ALREADY_COMPLETE" => "انت بالفعل داخل", - "SOCIAL" => "أو الدخول مع", - "REQUIRED" => "عذرا، يجب عليك تسجيل الدخول للوصول إلى هذا المكان" + 'ALREADY_COMPLETE' => 'انت بالفعل داخل', + 'SOCIAL' => 'أو الدخول مع', + 'REQUIRED' => 'عذرا، يجب عليك تسجيل الدخول للوصول إلى هذا المكان' ], - "LOGOUT" => "تسجيل الخروج", + 'LOGOUT' => 'تسجيل الخروج', - "NAME" => "اسم", + 'NAME' => 'اسم', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "سجل الدخول إلى حسابك في {{site_name}} أو سجيل للحصول على حساب جديد", - "SUBTITLE" => "التسجيل مجانا أو قم بتسجيل الدخول باستخدام حساب موجود", - "TITLE" => "هيا نبدأ", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'سجل الدخول إلى حسابك في {{site_name}} أو سجيل للحصول على حساب جديد', + 'SUBTITLE' => 'التسجيل مجانا أو قم بتسجيل الدخول باستخدام حساب موجود', + 'TITLE' => 'هيا نبدأ', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "كلمه المرور", - - "BETWEEN" => "ما بين {{min}}-{{max}} حروف", - - "CONFIRM" => "تأكيد كلمة المرور", - "CONFIRM_CURRENT" => "تأكيد كلمه المرور الحالي", - "CONFIRM_NEW" => "تأكيد كلمة المرور الجديدة", - "CONFIRM_NEW_EXPLAIN" => "إعادة إدخال كلمة المرور الجديدة", - "CONFIRM_NEW_HELP" => "لازم إذا كان المطلوب اختيار كلمة مرور جديدة", - "CURRENT" => "كلمة المرور الحالية", - "CURRENT_EXPLAIN" => "يجب عليك تأكيد كلمة المرور الحالية لإجراء التغييرات", - - "FORGOTTEN" => "كلمه المرور منسية", - "FORGET" => [ - "@TRANSLATION" => "لقد نسيت كلمة المرور", - - "COULD_NOT_UPDATE" => "لا يمكن تحديث كلمة المرور", - "EMAIL" => "ادخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل وسوف نرسل تعليمات لإعادة تعيين كلمة المرور", - "EMAIL_SEND" => "أرسل رابط تعيين كلمة المرور عبر البريد الالكتروني", - "INVALID" => "لم يتم العثور على إعادة تعيين كلمة المرور، أو انتهت صلاحية رابط حاول إعادة تقديم طلبك", - "PAGE" => "الحصول على رابط لإعادة تعيين كلمة المرور", - "REQUEST_CANNED" => "إلغاء طلب كلمة المرور", - "REQUEST_SENT" => "إذا تطابق البريد الإلكتروني {{email}} حسابا في نظامنا، فسيتم إرسال رابط إعادة تعيين كلمة المرور إلى {{email}}." + 'PASSWORD' => [ + '@TRANSLATION' => 'كلمه المرور', + + 'BETWEEN' => 'ما بين {{min}}-{{max}} حروف', + + 'CONFIRM' => 'تأكيد كلمة المرور', + 'CONFIRM_CURRENT' => 'تأكيد كلمه المرور الحالي', + 'CONFIRM_NEW' => 'تأكيد كلمة المرور الجديدة', + 'CONFIRM_NEW_EXPLAIN' => 'إعادة إدخال كلمة المرور الجديدة', + 'CONFIRM_NEW_HELP' => 'لازم إذا كان المطلوب اختيار كلمة مرور جديدة', + 'CURRENT' => 'كلمة المرور الحالية', + 'CURRENT_EXPLAIN' => 'يجب عليك تأكيد كلمة المرور الحالية لإجراء التغييرات', + + 'FORGOTTEN' => 'كلمه المرور منسية', + 'FORGET' => [ + '@TRANSLATION' => 'لقد نسيت كلمة المرور', + + 'COULD_NOT_UPDATE' => 'لا يمكن تحديث كلمة المرور', + 'EMAIL' => 'ادخل عنوان البريد الإلكتروني الذي استخدمته للتسجيل وسوف نرسل تعليمات لإعادة تعيين كلمة المرور', + 'EMAIL_SEND' => 'أرسل رابط تعيين كلمة المرور عبر البريد الالكتروني', + 'INVALID' => 'لم يتم العثور على إعادة تعيين كلمة المرور، أو انتهت صلاحية رابط حاول إعادة تقديم طلبك', + 'PAGE' => 'الحصول على رابط لإعادة تعيين كلمة المرور', + 'REQUEST_CANNED' => 'إلغاء طلب كلمة المرور', + 'REQUEST_SENT' => 'إذا تطابق البريد الإلكتروني {{email}} حسابا في نظامنا، فسيتم إرسال رابط إعادة تعيين كلمة المرور إلى {{email}}.' ], - "RESET" => [ - "@TRANSLATION" => "إعادة تعيين كلمة المرور", - "CHOOSE" => "اختيار كلمة مرور جديدة للتواصل", - "PAGE" => "اختيار كلمة مرور جديدة لحسابك", - "SEND" => "تعيين كلمة المرور الجديدة وتسجيل الدخول" + 'RESET' => [ + '@TRANSLATION' => 'إعادة تعيين كلمة المرور', + 'CHOOSE' => 'اختيار كلمة مرور جديدة للتواصل', + 'PAGE' => 'اختيار كلمة مرور جديدة لحسابك', + 'SEND' => 'تعيين كلمة المرور الجديدة وتسجيل الدخول' ], - "HASH_FAILED" => "فشلت التجزئة كلمة المرور يرجى الاتصال بمسؤول الموقع", - "INVALID" => "كلمة مرور الحالية لا تتطابق مع ما لدينا", - "NEW" => "كلمة مرور الجديدة", - "NOTHING_TO_UPDATE" => "لا يمكنك تحديث مع نفس كلمة مرور", - "UPDATED" => "جدد كلمة مرور", - - "CREATE" => [ - "@TRANSLATION" => "إنشاء كلمة مرور", - "PAGE" => "اختر كلمة مرور لحسابك الجديد", - "SET" => "تعيين كلمة المرور وتسجيل الدخول" + 'HASH_FAILED' => 'فشلت التجزئة كلمة المرور يرجى الاتصال بمسؤول الموقع', + 'INVALID' => 'كلمة مرور الحالية لا تتطابق مع ما لدينا', + 'NEW' => 'كلمة مرور الجديدة', + 'NOTHING_TO_UPDATE' => 'لا يمكنك تحديث مع نفس كلمة مرور', + 'UPDATED' => 'جدد كلمة مرور', + + 'CREATE' => [ + '@TRANSLATION' => 'إنشاء كلمة مرور', + 'PAGE' => 'اختر كلمة مرور لحسابك الجديد', + 'SET' => 'تعيين كلمة المرور وتسجيل الدخول' ] ], - "REGISTER" => "تسجيل", - "REGISTER_ME" => "سجلني", - "SIGN_IN_HERE" => "هل لديك حساب؟ تسجيل الدخول هنا", - - "REGISTRATION" => [ - "BROKEN" => "نحن آسفون، هناك مشكلة مع عملية تسجيل الحساب يرجى الاتصال بنا مباشرة للحصول على المساعدة", - "COMPLETE_TYPE1" => "لقد سجلت بنجاح يمكنك الآن تسجيل الدخول", - "COMPLETE_TYPE2" => "لقد سجلت بنجاح سوف تتلقى قريبا رسالة التحقق تحتوي على رابط لتفعيل حسابك لن تكون قادرا على تسجيل الدخول حتى الانتهاء من هذه الخطوة", - "DISABLED" => "عذرا، لقد تم تعطيل تسجيل اي حساب", - "LOGOUT" => "لا يمكنك التسجيل للحصول على حساب أثناء تسجيل الدخول", - "WELCOME" => "التسجيل سريع وبسيط" + 'REGISTER' => 'تسجيل', + 'REGISTER_ME' => 'سجلني', + 'SIGN_IN_HERE' => 'هل لديك حساب؟ تسجيل الدخول هنا', + + 'REGISTRATION' => [ + 'BROKEN' => 'نحن آسفون، هناك مشكلة مع عملية تسجيل الحساب يرجى الاتصال بنا مباشرة للحصول على المساعدة', + 'COMPLETE_TYPE1' => 'لقد سجلت بنجاح يمكنك الآن تسجيل الدخول', + 'COMPLETE_TYPE2' => 'لقد سجلت بنجاح سوف تتلقى قريبا رسالة التحقق تحتوي على رابط لتفعيل حسابك لن تكون قادرا على تسجيل الدخول حتى الانتهاء من هذه الخطوة', + 'DISABLED' => 'عذرا، لقد تم تعطيل تسجيل اي حساب', + 'LOGOUT' => 'لا يمكنك التسجيل للحصول على حساب أثناء تسجيل الدخول', + 'WELCOME' => 'التسجيل سريع وبسيط' ], - "RATE_LIMIT_EXCEEDED" => "تم تجاوز الحد عددا لهذا الإجراء يجب الانتظار {{delay}} ثواني قبل القيام بمحاولة أخرى", - "REMEMBER_ME" => "تذكرنى", - "REMEMBER_ME_ON_COMPUTER" => "تذكرني على هذا الحاسوب (غير مستحسن للحواسب العامة)", + 'RATE_LIMIT_EXCEEDED' => 'تم تجاوز الحد عددا لهذا الإجراء يجب الانتظار {{delay}} ثواني قبل القيام بمحاولة أخرى', + 'REMEMBER_ME' => 'تذكرنى', + 'REMEMBER_ME_ON_COMPUTER' => 'تذكرني على هذا الحاسوب (غير مستحسن للحواسب العامة)', - "SIGNIN" => "تسجيل الدخول", - "SIGNIN_OR_REGISTER" => "تسجيل الدخول أو التسجيل", - "SIGNUP" => "تسجيل", + 'SIGNIN' => 'تسجيل الدخول', + 'SIGNIN_OR_REGISTER' => 'تسجيل الدخول أو التسجيل', + 'SIGNUP' => 'تسجيل', - "TOS" => "الأحكام والشروط", - "TOS_AGREEMENT" => "من خلال تسجيل حساب جديد في {{site_title}}, انت تقبل الأحكام والشروط", - "TOS_FOR" => "الأحكام والشروط ل {{title}}", + 'TOS' => 'الأحكام والشروط', + 'TOS_AGREEMENT' => 'من خلال تسجيل حساب جديد في {{site_title}}, انت تقبل الأحكام والشروط', + 'TOS_FOR' => 'الأحكام والشروط ل {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "اسم المستخدم", + 'USERNAME' => [ + '@TRANSLATION' => 'اسم المستخدم', - "CHOOSE" => "اختيار اسم مستخدم فريد", - "INVALID" => "اسم المستخدم غير صالح", - "IN_USE" => "اسم المستخدم {{user_name}} قيد الاستخدام" + 'CHOOSE' => 'اختيار اسم مستخدم فريد', + 'INVALID' => 'اسم المستخدم غير صالح', + 'IN_USE' => 'اسم المستخدم {{user_name}} قيد الاستخدام' ], - "USER_ID_INVALID" => "عدم وجود هوية المستخدم المطلوب", - "USER_OR_EMAIL_INVALID" => "اسم المستخدم أو عنوان البريد الإلكتروني غير صالح", - "USER_OR_PASS_INVALID" => "اسم المستخدم أو كلمة المرور غير صالحة", + 'USER_ID_INVALID' => 'عدم وجود هوية المستخدم المطلوب', + 'USER_OR_EMAIL_INVALID' => 'اسم المستخدم أو عنوان البريد الإلكتروني غير صالح', + 'USER_OR_PASS_INVALID' => 'اسم المستخدم أو كلمة المرور غير صالحة', - "WELCOME" => "مرحبا بعودتك, {{first_name}}" + 'WELCOME' => 'مرحبا بعودتك, {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/ar/validate.php b/app/sprinkles/account/locale/ar/validate.php index 10543d0b8..7b8edc253 100644 --- a/app/sprinkles/account/locale/ar/validate.php +++ b/app/sprinkles/account/locale/ar/validate.php @@ -4,15 +4,16 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Modern Standard Arabic message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\ar - * @author Alexander Weissman and Abdullah Seba + * @author Alexander Weissman + * @author Abdullah Seba */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "يجب أن تكون كلمة المرور وكلمة المرور التأكيدية نفس" + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'يجب أن تكون كلمة المرور وكلمة المرور التأكيدية نفس' ] ]; diff --git a/app/sprinkles/account/locale/de_DE/messages.php b/app/sprinkles/account/locale/de_DE/messages.php index b33155274..26a23a725 100644 --- a/app/sprinkles/account/locale/de_DE/messages.php +++ b/app/sprinkles/account/locale/de_DE/messages.php @@ -4,185 +4,185 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * German message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\de * @author X-Anonymous-Y * @author kevinrombach * @author splitt3r */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Konto", + 'ACCOUNT' => [ + '@TRANSLATION' => 'Konto', - "ACCESS_DENIED" => "Hmm, sieht aus als hätten Sie keine Berechtigung, um dies zu tun.", + 'ACCESS_DENIED' => 'Hmm, sieht aus als hätten Sie keine Berechtigung, um dies zu tun.', - "DISABLED" => "Dieses Konto wurde deaktiviert. Bitte Kontaktieren Sie uns für weitere Informationen.", + 'DISABLED' => 'Dieses Konto wurde deaktiviert. Bitte Kontaktieren Sie uns für weitere Informationen.', - "EMAIL_UPDATED" => "E-Mail-Adresse aktualisiert.", + 'EMAIL_UPDATED' => 'E-Mail-Adresse aktualisiert.', - "INVALID" => "Dieses Konto existiert nicht. Es wurde möglicherweise gelöscht. Bitte kontaktieren Sie uns für weitere Informationen.", + 'INVALID' => 'Dieses Konto existiert nicht. Es wurde möglicherweise gelöscht. Bitte kontaktieren Sie uns für weitere Informationen.', - "MASTER_NOT_EXISTS" => "Sie können kein neues Konto anlegen solange kein Root-Konto angelegt wurde!", - "MY" => "Mein Konto", + 'MASTER_NOT_EXISTS' => 'Sie können kein neues Konto anlegen solange kein Root-Konto angelegt wurde!', + 'MY' => 'Mein Konto', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Ihre Sitzung wurde beeinträchtigt. Sie sollten sich auf allen Geräten abmelden, sich dann wieder anmelden und sicherstellen, dass Ihre Daten nicht manipuliert wurden.", - "TITLE" => "Ihr Konto wurde möglicherweise beeinträchtigt", - "TEXT" => "Möglicherweise ist es jemandem gelungen, Ihren Zugang zu dieser Seite zu übernehmen. Aus Sicherheitsgründen wurden Sie überall abgemeldet. Bitte melden Sie sich neu an und untersuchen Sie das Konto nach verdächtigen Aktivitäten. Außerdem sollten Sie Ihr Passwort ändern." + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => 'Ihre Sitzung wurde beeinträchtigt. Sie sollten sich auf allen Geräten abmelden, sich dann wieder anmelden und sicherstellen, dass Ihre Daten nicht manipuliert wurden.', + 'TITLE' => 'Ihr Konto wurde möglicherweise beeinträchtigt', + 'TEXT' => 'Möglicherweise ist es jemandem gelungen, Ihren Zugang zu dieser Seite zu übernehmen. Aus Sicherheitsgründen wurden Sie überall abgemeldet. Bitte melden Sie sich neu an und untersuchen Sie das Konto nach verdächtigen Aktivitäten. Außerdem sollten Sie Ihr Passwort ändern.' ], - "SESSION_EXPIRED" => "Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.", + 'SESSION_EXPIRED' => 'Ihre Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.', - "SETTINGS" => [ - "@TRANSLATION" => "Kontoeinstellungen", - "DESCRIPTION" => "Aktualisieren Sie Ihre Kontoeinstellungen, einschließlich E-Mail, Name und Passwort.", - "UPDATED" => "Kontoeinstellungen aktualisiert" + 'SETTINGS' => [ + '@TRANSLATION' => 'Kontoeinstellungen', + 'DESCRIPTION' => 'Aktualisieren Sie Ihre Kontoeinstellungen, einschließlich E-Mail, Name und Passwort.', + 'UPDATED' => 'Kontoeinstellungen aktualisiert' ], - "TOOLS" => "Konto-Werkzeuge", + 'TOOLS' => 'Konto-Werkzeuge', - "UNVERIFIED" => "Ihr Konto wurde noch nicht bestätigt. Überprüfen Sie Ihr E-Mails/Spam-Ordner für die Konto-Aktivierungsanleitung.", + 'UNVERIFIED' => 'Ihr Konto wurde noch nicht bestätigt. Überprüfen Sie Ihr E-Mails/Spam-Ordner für die Konto-Aktivierungsanleitung.', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Wir haben einen neuen Bestätigungslink an {{email}} gesendet. Überprüfen Sie Ihr E-Mail/Spam-Ordner oder versuchen Sie es später noch einmal.", - "RESEND" => "Bestätigungsmail erneut senden", - "COMPLETE" => "Sie haben Ihr Konto erfolgreich Verifiziert. Sie können sich jetzt anmelden.", - "EMAIL" => "Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben, Überprüfen Sie Ihr E-Mails/Spam-Ordner für die Bestätigungs-E-Mail.", - "PAGE" => "Senden Sie die Bestätigungs-E-Mail erneut für Ihr neues Konto.", - "SEND" => "Bestätigungslink erneut per E-Mail zusenden", - "TOKEN_NOT_FOUND" => "Verifizierungstoken existiert nicht / Konto wurde bereits verifiziert" + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'Wir haben einen neuen Bestätigungslink an {{email}} gesendet. Überprüfen Sie Ihr E-Mail/Spam-Ordner oder versuchen Sie es später noch einmal.', + 'RESEND' => 'Bestätigungsmail erneut senden', + 'COMPLETE' => 'Sie haben Ihr Konto erfolgreich Verifiziert. Sie können sich jetzt anmelden.', + 'EMAIL' => 'Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben, Überprüfen Sie Ihr E-Mails/Spam-Ordner für die Bestätigungs-E-Mail.', + 'PAGE' => 'Senden Sie die Bestätigungs-E-Mail erneut für Ihr neues Konto.', + 'SEND' => 'Bestätigungslink erneut per E-Mail zusenden', + 'TOKEN_NOT_FOUND' => 'Verifizierungstoken existiert nicht / Konto wurde bereits verifiziert' ] ], - "EMAIL" => [ - "INVALID" => "Es gibt kein Konto für {{email}}.", - "IN_USE" => "Die E-Mail Adresse {{email}} wird bereits verwendet.", - "VERIFICATION_REQUIRED" => "E-Mail (Bestätigung benötigt - Benutzen Sie eine echte E-Mail Adresse!)" + 'EMAIL' => [ + 'INVALID' => 'Es gibt kein Konto für {{email}}.', + 'IN_USE' => 'Die E-Mail Adresse {{email}} wird bereits verwendet.', + 'VERIFICATION_REQUIRED' => 'E-Mail (Bestätigung benötigt - Benutzen Sie eine echte E-Mail Adresse!)' ], - "EMAIL_OR_USERNAME" => "Benutzername oder E-mail Adresse", + 'EMAIL_OR_USERNAME' => 'Benutzername oder E-mail Adresse', - "FIRST_NAME" => "Vorname", + 'FIRST_NAME' => 'Vorname', - "HEADER_MESSAGE_ROOT" => "Sie sind als Root-Benutzer angemeldet.", + 'HEADER_MESSAGE_ROOT' => 'Sie sind als Root-Benutzer angemeldet.', - "LAST_NAME" => "Nachname", + 'LAST_NAME' => 'Nachname', - "LOCALE" => [ - "ACCOUNT" => "Die Sprache und das Gebietsschema für Ihr Konto", - "INVALID" => "{{locale}} ist kein gültiges Gebietsschema." + 'LOCALE' => [ + 'ACCOUNT' => 'Die Sprache und das Gebietsschema für Ihr Konto', + 'INVALID' => '{{locale}} ist kein gültiges Gebietsschema.' ], - "LOGIN" => [ - "@TRANSLATION" => "Anmelden", - "ALREADY_COMPLETE" => "Sie sind bereits eingeloggt!", - "SOCIAL" => "Oder loggen Sie sich ein mit", - "REQUIRED" => "Sorry, Sie müssen angemeldet sein. Um auf diese Ressource zugreifen zu können." + 'LOGIN' => [ + '@TRANSLATION' => 'Anmelden', + 'ALREADY_COMPLETE' => 'Sie sind bereits eingeloggt!', + 'SOCIAL' => 'Oder loggen Sie sich ein mit', + 'REQUIRED' => 'Sorry, Sie müssen angemeldet sein. Um auf diese Ressource zugreifen zu können.' ], - "LOGOUT" => "Ausloggen", + 'LOGOUT' => 'Ausloggen', - "NAME" => "Name", + 'NAME' => 'Name', - "NAME_AND_EMAIL" => "Name und E-Mail", + 'NAME_AND_EMAIL' => 'Name und E-Mail', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Melden Sie sich in Ihr {{site_name}} Konto an oder registrieren Sie sich für ein neues Konto.", - "SUBTITLE" => "Registrieren Sie sich kostenlos oder melden Sie sich mit einem bestehenden Konto an.", - "TITLE" => "Lass uns anfangen!" + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'Melden Sie sich in Ihr {{site_name}} Konto an oder registrieren Sie sich für ein neues Konto.', + 'SUBTITLE' => 'Registrieren Sie sich kostenlos oder melden Sie sich mit einem bestehenden Konto an.', + 'TITLE' => 'Lass uns anfangen!' ] ], - "PASSWORD" => [ - "@TRANSLATION" => "Passwort", + 'PASSWORD' => [ + '@TRANSLATION' => 'Passwort', - "BETWEEN" => "Zwischen {{min}}-{{max}} Zeichen", + 'BETWEEN' => 'Zwischen {{min}}-{{max}} Zeichen', - "CONFIRM" => "Bestätige das Passwort", - "CONFIRM_CURRENT" => "Bitte bestätige dein jetziges Passwort", - "CONFIRM_NEW" => "Neues Passwort bestätigen", - "CONFIRM_NEW_EXPLAIN" => "Geben Sie Ihr neues Passwort erneut ein", - "CONFIRM_NEW_HELP" => "Erforderlich, wenn Sie ein neues Passwort wählen", - "CREATE" => [ - "@TRANSLATION" => "Passwort setzen", - "PAGE" => "Setzen Sie ein Passwort für den Account.", - "SET" => "Passwort setzen und anmelden" + 'CONFIRM' => 'Bestätige das Passwort', + 'CONFIRM_CURRENT' => 'Bitte bestätige dein jetziges Passwort', + 'CONFIRM_NEW' => 'Neues Passwort bestätigen', + 'CONFIRM_NEW_EXPLAIN' => 'Geben Sie Ihr neues Passwort erneut ein', + 'CONFIRM_NEW_HELP' => 'Erforderlich, wenn Sie ein neues Passwort wählen', + 'CREATE' => [ + '@TRANSLATION' => 'Passwort setzen', + 'PAGE' => 'Setzen Sie ein Passwort für den Account.', + 'SET' => 'Passwort setzen und anmelden' ], - "CURRENT" => "Aktuelles Passwort", - "CURRENT_EXPLAIN" => "Sie müssen Ihr aktuelles Passwort bestätigen, um Änderungen vorzunehmen", - - "FORGOTTEN" => "Passwort vergessen", - "FORGET" => [ - "@TRANSLATION" => "Ich habe mein Passwort vergessen", - - "COULD_NOT_UPDATE" => "Das Passwort konnte nicht aktualisiert werden.", - "EMAIL" => "Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben. Ein Link mit der Anweisungen zum Zurücksetzen Ihres Passworts wird Ihnen per E-Mail zugeschickt.", - "EMAIL_SEND" => "Neue Passwort zurücksetzen E-Mail senden", - "INVALID" => "Diese Anforderung zum Zurücksetzen des Passworts wurde nicht gefunden oder ist abgelaufen.Bitte versuchen Sie Ihre Anfrage erneut einzureichen.", - "PAGE" => "Holen Sie sich einen Link, um Ihr Passwort zurückzusetzen.", - "REQUEST_CANNED" => "Verlorene Passwortanforderung abgebrochen.", - "REQUEST_SENT" => "Wenn die E-Mail {{email}} mit einem Account in unserem System übereinstimmt, wird ein Passwort-Reset-Link an {{email}} gesendet." + 'CURRENT' => 'Aktuelles Passwort', + 'CURRENT_EXPLAIN' => 'Sie müssen Ihr aktuelles Passwort bestätigen, um Änderungen vorzunehmen', + + 'FORGOTTEN' => 'Passwort vergessen', + 'FORGET' => [ + '@TRANSLATION' => 'Ich habe mein Passwort vergessen', + + 'COULD_NOT_UPDATE' => 'Das Passwort konnte nicht aktualisiert werden.', + 'EMAIL' => 'Bitte geben Sie die E-Mail-Adresse ein, mit der Sie sich registriert haben. Ein Link mit der Anweisungen zum Zurücksetzen Ihres Passworts wird Ihnen per E-Mail zugeschickt.', + 'EMAIL_SEND' => 'Neue Passwort zurücksetzen E-Mail senden', + 'INVALID' => "Diese Anforderung zum Zurücksetzen des Passworts wurde nicht gefunden oder ist abgelaufen.Bitte versuchen Sie Ihre Anfrage erneut einzureichen.", + 'PAGE' => 'Holen Sie sich einen Link, um Ihr Passwort zurückzusetzen.', + 'REQUEST_CANNED' => 'Verlorene Passwortanforderung abgebrochen.', + 'REQUEST_SENT' => 'Wenn die E-Mail {{email}} mit einem Account in unserem System übereinstimmt, wird ein Passwort-Reset-Link an {{email}} gesendet.' ], - "HASH_FAILED" => "Passwort Hashing fehlgeschlagen. Bitte kontaktieren Sie einen Administrator.", - "INVALID" => "Das aktuelle Passwort stimmt nicht mit dem Datensatz überein", - "NEW" => "Neues Passwort", - "NOTHING_TO_UPDATE" => "Sie können nicht das gleiche Passwort zum Aktualisieren verwenden", + 'HASH_FAILED' => 'Passwort Hashing fehlgeschlagen. Bitte kontaktieren Sie einen Administrator.', + 'INVALID' => 'Das aktuelle Passwort stimmt nicht mit dem Datensatz überein', + 'NEW' => 'Neues Passwort', + 'NOTHING_TO_UPDATE' => 'Sie können nicht das gleiche Passwort zum Aktualisieren verwenden', - "RESET" => [ - "@TRANSLATION" => "Passwort zurücksetzen", - "CHOOSE" => "Bitte wählen Sie ein neues Passwort, um fortzufahren.", - "PAGE" => "Wählen Sie ein neues Passwort für Ihr Konto.", - "SEND" => "Neues Passwort festlegen und anmelden" + 'RESET' => [ + '@TRANSLATION' => 'Passwort zurücksetzen', + 'CHOOSE' => 'Bitte wählen Sie ein neues Passwort, um fortzufahren.', + 'PAGE' => 'Wählen Sie ein neues Passwort für Ihr Konto.', + 'SEND' => 'Neues Passwort festlegen und anmelden' ], - "UPDATED" => "Konto Passwort aktualisiert" + 'UPDATED' => 'Konto Passwort aktualisiert' ], - "PROFILE" => [ - "SETTINGS" => "Profileinstellungen", - "UPDATED" => "Profileinstellungen aktualisiert" + 'PROFILE' => [ + 'SETTINGS' => 'Profileinstellungen', + 'UPDATED' => 'Profileinstellungen aktualisiert' ], - "RATE_LIMIT_EXCEEDED" => "Die grenze für diese Maßnahme wurde überschritten. Sie müssen weitere {{delay}} Sekunden warten, bevor Sie einen weiteren Versuch machen dürfen.", - - "REGISTER" => "Registrieren", - "REGISTER_ME" => "Melden Sie mich an", - "REGISTRATION" => [ - "BROKEN" => "Es tut uns leid, es gibt ein Problem mit unserer Registrierung. Bitte kontaktieren Sie uns direkt für Hilfe.", - "COMPLETE_TYPE1" => "Sie haben sich erfolgreich registriert. Sie können sich jetzt anmelden.", - "COMPLETE_TYPE2" => "Sie haben sich erfolgreich registriert. Sie erhalten in Kürze eine Bestätigungs-E-Mail mit einem Link zur Aktivierung Ihres Kontos. Sie können sich nicht anmelden, bis Sie diesen Schritt abgeschlossen haben.", - "DISABLED" => "Es tut uns leid, Die Registrierung des Kontos ist deaktiviert.", - "LOGOUT" => "Es tut uns leid, Sie können kein neues Konto registrieren, während Sie angemeldet sind. Bitte melden Sie sich zuerst ab.", - "WELCOME" => "Die Registrierung ist schnell und einfach." + 'RATE_LIMIT_EXCEEDED' => 'Die grenze für diese Maßnahme wurde überschritten. Sie müssen weitere {{delay}} Sekunden warten, bevor Sie einen weiteren Versuch machen dürfen.', + + 'REGISTER' => 'Registrieren', + 'REGISTER_ME' => 'Melden Sie mich an', + 'REGISTRATION' => [ + 'BROKEN' => 'Es tut uns leid, es gibt ein Problem mit unserer Registrierung. Bitte kontaktieren Sie uns direkt für Hilfe.', + 'COMPLETE_TYPE1' => 'Sie haben sich erfolgreich registriert. Sie können sich jetzt anmelden.', + 'COMPLETE_TYPE2' => 'Sie haben sich erfolgreich registriert. Sie erhalten in Kürze eine Bestätigungs-E-Mail mit einem Link zur Aktivierung Ihres Kontos. Sie können sich nicht anmelden, bis Sie diesen Schritt abgeschlossen haben.', + 'DISABLED' => 'Es tut uns leid, Die Registrierung des Kontos ist deaktiviert.', + 'LOGOUT' => 'Es tut uns leid, Sie können kein neues Konto registrieren, während Sie angemeldet sind. Bitte melden Sie sich zuerst ab.', + 'WELCOME' => 'Die Registrierung ist schnell und einfach.' ], - "REMEMBER_ME" => "Erinnere dich an mich!", - "REMEMBER_ME_ON_COMPUTER" => "Erinnere dich an mich auf diesem Computer (nicht für öffentliche Computer empfohlen)", + 'REMEMBER_ME' => 'Erinnere dich an mich!', + 'REMEMBER_ME_ON_COMPUTER' => 'Erinnere dich an mich auf diesem Computer (nicht für öffentliche Computer empfohlen)', - "SIGN_IN_HERE" => "Sie haben bereits einen Account? Melden Sie sich hier an.", - "SIGNIN" => "Anmelden", - "SIGNIN_OR_REGISTER" => "Anmelden oder registrieren", - "SIGNUP" => "Anmelden", + 'SIGN_IN_HERE' => 'Sie haben bereits einen Account? Melden Sie sich hier an.', + 'SIGNIN' => 'Anmelden', + 'SIGNIN_OR_REGISTER' => 'Anmelden oder registrieren', + 'SIGNUP' => 'Anmelden', - "TOS" => "Geschäftsbedingungen", - "TOS_AGREEMENT" => "Durch die Registrierung eines Kontos auf {{site_title}} akzeptieren Sie die Bedingungen .", - "TOS_FOR" => "Allgemeine Geschäftsbedingungen für {{title}}", + 'TOS' => 'Geschäftsbedingungen', + 'TOS_AGREEMENT' => 'Durch die Registrierung eines Kontos auf {{site_title}} akzeptieren Sie die Bedingungen .', + 'TOS_FOR' => 'Allgemeine Geschäftsbedingungen für {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "Benutzername", + 'USERNAME' => [ + '@TRANSLATION' => 'Benutzername', - "CHOOSE" => "Wählen Sie einen eindeutigen Benutzernamen", - "INVALID" => "Ungültiger Benutzername", - "IN_USE" => "Benutzername {{user_name}} wird bereits verwendet.", - "NOT_AVAILABLE" => "Benutzername {{user_name}} ist nicht verfügbar. Wähle einen anderen Namen, der klicken Sie auf 'vorschlagen'." + 'CHOOSE' => 'Wählen Sie einen eindeutigen Benutzernamen', + 'INVALID' => 'Ungültiger Benutzername', + 'IN_USE' => 'Benutzername {{user_name}} wird bereits verwendet.', + 'NOT_AVAILABLE' => "Benutzername {{user_name}} ist nicht verfügbar. Wähle einen anderen Namen, der klicken Sie auf 'vorschlagen'." ], - "USER_ID_INVALID" => "Die angeforderte Benutzer-ID existiert nicht.", - "USER_OR_EMAIL_INVALID" => "Benutzername oder E-Mail-Adresse ist ungültig.", - "USER_OR_PASS_INVALID" => "Benutzername oder Passwort ist ungültig.", + 'USER_ID_INVALID' => 'Die angeforderte Benutzer-ID existiert nicht.', + 'USER_OR_EMAIL_INVALID' => 'Benutzername oder E-Mail-Adresse ist ungültig.', + 'USER_OR_PASS_INVALID' => 'Benutzername oder Passwort ist ungültig.', - "WELCOME" => "Willkommen zurück, {{first_name}}" + 'WELCOME' => 'Willkommen zurück, {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/de_DE/validate.php b/app/sprinkles/account/locale/de_DE/validate.php index 30cf98ba1..4529f3f1b 100644 --- a/app/sprinkles/account/locale/de_DE/validate.php +++ b/app/sprinkles/account/locale/de_DE/validate.php @@ -4,18 +4,18 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * German message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\de * @author X-Anonymous-Y * @author kevinrombach * @author splitt3r */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Ihr Passwort und das Bestätigungspasswort müssen übereinstimmen.", - "USERNAME" => "Benutzernamen dürfen nur aus Kleinbuchstaben, Zahlen, '.', '-' und '_' bestehen." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'Ihr Passwort und das Bestätigungspasswort müssen übereinstimmen.', + 'USERNAME' => "Benutzernamen dürfen nur aus Kleinbuchstaben, Zahlen, '.', '-' und '_' bestehen." ] ]; diff --git a/app/sprinkles/account/locale/en_US/messages.php b/app/sprinkles/account/locale/en_US/messages.php index 17d7582be..501407de3 100644 --- a/app/sprinkles/account/locale/en_US/messages.php +++ b/app/sprinkles/account/locale/en_US/messages.php @@ -4,180 +4,180 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * US English message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\en_US * @author Alexander Weissman */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Account", + 'ACCOUNT' => [ + '@TRANSLATION' => 'Account', - "ACCESS_DENIED" => "Hmm, looks like you don't have permission to do that.", + 'ACCESS_DENIED' => "Hmm, looks like you don't have permission to do that.", - "DISABLED" => "This account has been disabled. Please contact us for more information.", + 'DISABLED' => 'This account has been disabled. Please contact us for more information.', - "EMAIL_UPDATED" => "Account email updated", + 'EMAIL_UPDATED' => 'Account email updated', - "INVALID" => "This account does not exist. It may have been deleted. Please contact us for more information.", + 'INVALID' => 'This account does not exist. It may have been deleted. Please contact us for more information.', - "MASTER_NOT_EXISTS" => "You cannot register an account until the master account has been created!", - "MY" => "My Account", + 'MASTER_NOT_EXISTS' => 'You cannot register an account until the master account has been created!', + 'MY' => 'My Account', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Your session has been compromised. You should log out on all devices, then log back in and make sure that your data has not been tampered with.", - "TITLE" => "Your account may have been compromised", - "TEXT" => "Someone may have used your login information to acccess this page. For your safety, all sessions were logged out. Please log in and check your account for suspicious activity. You may also wish to change your password." + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => 'Your session has been compromised. You should log out on all devices, then log back in and make sure that your data has not been tampered with.', + 'TITLE' => 'Your account may have been compromised', + 'TEXT' => 'Someone may have used your login information to acccess this page. For your safety, all sessions were logged out. Please log in and check your account for suspicious activity. You may also wish to change your password.' ], - "SESSION_EXPIRED" => "Your session has expired. Please sign in again.", + 'SESSION_EXPIRED' => 'Your session has expired. Please sign in again.', - "SETTINGS" => [ - "@TRANSLATION" => "Account settings", - "DESCRIPTION" => "Update your account settings, including email, name, and password.", - "UPDATED" => "Account settings updated" + 'SETTINGS' => [ + '@TRANSLATION' => 'Account settings', + 'DESCRIPTION' => 'Update your account settings, including email, name, and password.', + 'UPDATED' => 'Account settings updated' ], - "TOOLS" => "Account tools", + 'TOOLS' => 'Account tools', - "UNVERIFIED" => "Your account has not yet been verified. Check your emails / spam folder for account activation instructions.", + 'UNVERIFIED' => 'Your account has not yet been verified. Check your emails / spam folder for account activation instructions.', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "We have emailed a new verification link to {{email}}. Please check your inbox and spam folders for this email.", - "RESEND" => "Resend verification email", - "COMPLETE" => "You have successfully verified your account. You can now login.", - "EMAIL" => "Please enter the email address you used to sign up, and your verification email will be resent.", - "PAGE" => "Resend the verification email for your new account.", - "SEND" => "Email the verification link for my account", - "TOKEN_NOT_FOUND" => "Verification token does not exist / Account is already verified", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'We have emailed a new verification link to {{email}}. Please check your inbox and spam folders for this email.', + 'RESEND' => 'Resend verification email', + 'COMPLETE' => 'You have successfully verified your account. You can now login.', + 'EMAIL' => 'Please enter the email address you used to sign up, and your verification email will be resent.', + 'PAGE' => 'Resend the verification email for your new account.', + 'SEND' => 'Email the verification link for my account', + 'TOKEN_NOT_FOUND' => 'Verification token does not exist / Account is already verified', ] ], - "EMAIL" => [ - "INVALID" => "There is no account for {{email}}.", - "IN_USE" => "Email {{email}} is already in use.", - "VERIFICATION_REQUIRED" => "Email (verification required - use a real address!)" + 'EMAIL' => [ + 'INVALID' => 'There is no account for {{email}}.', + 'IN_USE' => 'Email {{email}} is already in use.', + 'VERIFICATION_REQUIRED' => 'Email (verification required - use a real address!)' ], - "EMAIL_OR_USERNAME" => "Username or email address", + 'EMAIL_OR_USERNAME' => 'Username or email address', - "FIRST_NAME" => "First name", + 'FIRST_NAME' => 'First name', - "HEADER_MESSAGE_ROOT" => "YOU ARE SIGNED IN AS THE ROOT USER", + 'HEADER_MESSAGE_ROOT' => 'YOU ARE SIGNED IN AS THE ROOT USER', - "LAST_NAME" => "Last name", - "LOCALE" => [ - "ACCOUNT" => "The language and locale to use for your account", - "INVALID" => "{{locale}} is not a valid locale." + 'LAST_NAME' => 'Last name', + 'LOCALE' => [ + 'ACCOUNT' => 'The language and locale to use for your account', + 'INVALID' => '{{locale}} is not a valid locale.' ], - "LOGIN" => [ - "@TRANSLATION" => "Login", - "ALREADY_COMPLETE" => "You are already logged in!", - "SOCIAL" => "Or login with", - "REQUIRED" => "Sorry, you must be logged in to access this resource." + 'LOGIN' => [ + '@TRANSLATION' => 'Login', + 'ALREADY_COMPLETE' => 'You are already logged in!', + 'SOCIAL' => 'Or login with', + 'REQUIRED' => 'Sorry, you must be logged in to access this resource.' ], - "LOGOUT" => "Logout", + 'LOGOUT' => 'Logout', - "NAME" => "Name", + 'NAME' => 'Name', - "NAME_AND_EMAIL" => "Name and email", + 'NAME_AND_EMAIL' => 'Name and email', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Sign in to your {{site_name}} account, or register for a new account.", - "SUBTITLE" => "Register for free, or sign in with an existing account.", - "TITLE" => "Let's get started!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'Sign in to your {{site_name}} account, or register for a new account.', + 'SUBTITLE' => 'Register for free, or sign in with an existing account.', + 'TITLE' => "Let's get started!", ] ], - "PASSWORD" => [ - "@TRANSLATION" => "Password", + 'PASSWORD' => [ + '@TRANSLATION' => 'Password', - "BETWEEN" => "Between {{min}}-{{max}} characters", + 'BETWEEN' => 'Between {{min}}-{{max}} characters', - "CONFIRM" => "Confirm password", - "CONFIRM_CURRENT" => "Please confirm your current password", - "CONFIRM_NEW" => "Confirm New Password", - "CONFIRM_NEW_EXPLAIN" => "Re-enter your new password", - "CONFIRM_NEW_HELP" => "Required only if selecting a new password", - "CREATE" => [ - "@TRANSLATION" => "Create Password", - "PAGE" => "Choose a password for your new account.", - "SET" => "Set Password and Sign In" + 'CONFIRM' => 'Confirm password', + 'CONFIRM_CURRENT' => 'Please confirm your current password', + 'CONFIRM_NEW' => 'Confirm New Password', + 'CONFIRM_NEW_EXPLAIN' => 'Re-enter your new password', + 'CONFIRM_NEW_HELP' => 'Required only if selecting a new password', + 'CREATE' => [ + '@TRANSLATION' => 'Create Password', + 'PAGE' => 'Choose a password for your new account.', + 'SET' => 'Set Password and Sign In' ], - "CURRENT" => "Current Password", - "CURRENT_EXPLAIN" => "You must confirm your current password to make changes", - - "FORGOTTEN" => "Forgotten Password", - "FORGET" => [ - "@TRANSLATION" => "I forgot my password", - - "COULD_NOT_UPDATE" => "Couldn't update password.", - "EMAIL" => "Please enter the email address you used to sign up. A link with instructions to reset your password will be emailed to you.", - "EMAIL_SEND" => "Email Password Reset Link", - "INVALID" => "This password reset request could not be found, or has expired. Please try resubmitting your request.", - "PAGE" => "Get a link to reset your password.", - "REQUEST_CANNED" => "Lost password request cancelled.", - "REQUEST_SENT" => "If the email {{email}} matches an account in our system, a password reset link will be sent to {{email}}." + 'CURRENT' => 'Current Password', + 'CURRENT_EXPLAIN' => 'You must confirm your current password to make changes', + + 'FORGOTTEN' => 'Forgotten Password', + 'FORGET' => [ + '@TRANSLATION' => 'I forgot my password', + + 'COULD_NOT_UPDATE' => "Couldn't update password.", + 'EMAIL' => 'Please enter the email address you used to sign up. A link with instructions to reset your password will be emailed to you.', + 'EMAIL_SEND' => 'Email Password Reset Link', + 'INVALID' => 'This password reset request could not be found, or has expired. Please try resubmitting your request.', + 'PAGE' => 'Get a link to reset your password.', + 'REQUEST_CANNED' => 'Lost password request cancelled.', + 'REQUEST_SENT' => 'If the email {{email}} matches an account in our system, a password reset link will be sent to {{email}}.' ], - "HASH_FAILED" => "Password hashing failed. Please contact a site administrator.", - "INVALID" => "Current password doesn't match the one we have on record", - "NEW" => "New Password", - "NOTHING_TO_UPDATE" => "You cannot update with the same password", + 'HASH_FAILED' => 'Password hashing failed. Please contact a site administrator.', + 'INVALID' => "Current password doesn't match the one we have on record", + 'NEW' => 'New Password', + 'NOTHING_TO_UPDATE' => 'You cannot update with the same password', - "RESET" => [ - "@TRANSLATION" => "Reset Password", - "CHOOSE" => "Please choose a new password to continue.", - "PAGE" => "Choose a new password for your account.", - "SEND" => "Set New Password and Sign In" + 'RESET' => [ + '@TRANSLATION' => 'Reset Password', + 'CHOOSE' => 'Please choose a new password to continue.', + 'PAGE' => 'Choose a new password for your account.', + 'SEND' => 'Set New Password and Sign In' ], - "UPDATED" => "Account password updated" + 'UPDATED' => 'Account password updated' ], - "PROFILE" => [ - "SETTINGS" => "Profile settings", - "UPDATED" => "Profile settings updated" + 'PROFILE' => [ + 'SETTINGS' => 'Profile settings', + 'UPDATED' => 'Profile settings updated' ], - "RATE_LIMIT_EXCEEDED" => "The rate limit for this action has been exceeded. You must wait another {{delay}} seconds before you will be allowed to make another attempt.", - - "REGISTER" => "Register", - "REGISTER_ME" => "Sign me up", - "REGISTRATION" => [ - "BROKEN" => "We're sorry, there is a problem with our account registration process. Please contact us directly for assistance.", - "COMPLETE_TYPE1" => "You have successfully registered. You can now sign in.", - "COMPLETE_TYPE2" => "You have successfully registered. A link to activate your account has been sent to {{email}}. You will not be able to sign in until you complete this step.", - "DISABLED" => "We're sorry, account registration has been disabled.", - "LOGOUT" => "I'm sorry, you cannot register for an account while logged in. Please log out first.", - "WELCOME" => "Registration is fast and simple." + 'RATE_LIMIT_EXCEEDED' => 'The rate limit for this action has been exceeded. You must wait another {{delay}} seconds before you will be allowed to make another attempt.', + + 'REGISTER' => 'Register', + 'REGISTER_ME' => 'Sign me up', + 'REGISTRATION' => [ + 'BROKEN' => "We're sorry, there is a problem with our account registration process. Please contact us directly for assistance.", + 'COMPLETE_TYPE1' => 'You have successfully registered. You can now sign in.', + 'COMPLETE_TYPE2' => 'You have successfully registered. A link to activate your account has been sent to {{email}}. You will not be able to sign in until you complete this step.', + 'DISABLED' => "We're sorry, account registration has been disabled.", + 'LOGOUT' => "I'm sorry, you cannot register for an account while logged in. Please log out first.", + 'WELCOME' => 'Registration is fast and simple.' ], - "REMEMBER_ME" => "Keep me signed in", - "REMEMBER_ME_ON_COMPUTER" => "Remember me on this computer (not recommended for public computers)", + 'REMEMBER_ME' => 'Keep me signed in', + 'REMEMBER_ME_ON_COMPUTER' => 'Remember me on this computer (not recommended for public computers)', - "SIGN_IN_HERE" => "Already have an account? Sign in here.", - "SIGNIN" => "Sign in", - "SIGNIN_OR_REGISTER" => "Sign in or register", - "SIGNUP" => "Sign Up", + 'SIGN_IN_HERE' => 'Already have an account? Sign in here.', + 'SIGNIN' => 'Sign in', + 'SIGNIN_OR_REGISTER' => 'Sign in or register', + 'SIGNUP' => 'Sign Up', - "TOS" => "Terms and Conditions", - "TOS_AGREEMENT" => "By registering an account with {{site_title}}, you accept the terms and conditions.", - "TOS_FOR" => "Terms and Conditions for {{title}}", + 'TOS' => 'Terms and Conditions', + 'TOS_AGREEMENT' => 'By registering an account with {{site_title}}, you accept the terms and conditions.', + 'TOS_FOR' => 'Terms and Conditions for {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "Username", + 'USERNAME' => [ + '@TRANSLATION' => 'Username', - "CHOOSE" => "Choose a unique username", - "INVALID" => "Invalid username", - "IN_USE" => "Username {{user_name}} is already in use.", - "NOT_AVAILABLE" => "Username {{user_name}} is not available. Choose a different name, or click 'suggest'." + 'CHOOSE' => 'Choose a unique username', + 'INVALID' => 'Invalid username', + 'IN_USE' => 'Username {{user_name}} is already in use.', + 'NOT_AVAILABLE' => "Username {{user_name}} is not available. Choose a different name, or click 'suggest'." ], - "USER_ID_INVALID" => "The requested user id does not exist.", - "USER_OR_EMAIL_INVALID" => "Username or email address is invalid.", - "USER_OR_PASS_INVALID" => "User not found or password is invalid.", + 'USER_ID_INVALID' => 'The requested user id does not exist.', + 'USER_OR_EMAIL_INVALID' => 'Username or email address is invalid.', + 'USER_OR_PASS_INVALID' => 'User not found or password is invalid.', - "WELCOME" => "Welcome back, {{first_name}}" + 'WELCOME' => 'Welcome back, {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/en_US/validate.php b/app/sprinkles/account/locale/en_US/validate.php index f91ecfed7..40f8df6aa 100644 --- a/app/sprinkles/account/locale/en_US/validate.php +++ b/app/sprinkles/account/locale/en_US/validate.php @@ -4,16 +4,16 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * US English message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\en_US * @author Alexander Weissman */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Your password and confirmation password must match.", - "USERNAME" => "Username may consist only of lowercase letters, numbers, '.', '-', and '_'." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'Your password and confirmation password must match.', + 'USERNAME' => "Username may consist only of lowercase letters, numbers, '.', '-', and '_'." ] ]; diff --git a/app/sprinkles/account/locale/es_ES/messages.php b/app/sprinkles/account/locale/es_ES/messages.php index e60c7d172..567c202ca 100755 --- a/app/sprinkles/account/locale/es_ES/messages.php +++ b/app/sprinkles/account/locale/es_ES/messages.php @@ -4,186 +4,185 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Spanish message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\es_ES * @author rafa31gz */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Perfil", + 'ACCOUNT' => [ + '@TRANSLATION' => 'Perfil', - "ACCESS_DENIED" => "Hmm, parece que no tienes permiso para hacer eso.", + 'ACCESS_DENIED' => 'Hmm, parece que no tienes permiso para hacer eso.', - "DISABLED" => "Esta cuenta se ha inhabilitado. Por favor contáctanos para más información.", + 'DISABLED' => 'Esta cuenta se ha inhabilitado. Por favor contáctanos para más información.', - "EMAIL_UPDATED" => "Correo electrónico de la cuenta actualizado", + 'EMAIL_UPDATED' => 'Correo electrónico de la cuenta actualizado', - "INVALID" => "Esta cuenta no existe. Puede haber sido eliminado. Por favor contáctanos para más información.", + 'INVALID' => 'Esta cuenta no existe. Puede haber sido eliminado. Por favor contáctanos para más información.', - "MASTER_NOT_EXISTS" => "No puedes registrar una cuenta hasta que se haya creado la cuenta principal.", - "MY" => "Mi Perfil", + 'MASTER_NOT_EXISTS' => 'No puedes registrar una cuenta hasta que se haya creado la cuenta principal.', + 'MY' => 'Mi Perfil', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Tu sesión ha sido comprometida. Debes desconectarse de todos los dispositivos y, a continuación, volver a iniciar sesión y asegurarte de que sus datos no han sido manipulados.", - "TITLE" => "Es posible que tu cuenta se haya visto comprometida.", - "TEXT" => "Alguien puede haber utilizado tu información de acceso para acceder a esta página. Para tu seguridad, todas las sesiones se cerraron. ingrese y comprueba si tu actividad es sospechosa en tu cuenta. También puedes cambiar su contraseña." + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => 'Tu sesión ha sido comprometida. Debes desconectarse de todos los dispositivos y, a continuación, volver a iniciar sesión y asegurarte de que sus datos no han sido manipulados.', + 'TITLE' => 'Es posible que tu cuenta se haya visto comprometida.', + 'TEXT' => 'Alguien puede haber utilizado tu información de acceso para acceder a esta página. Para tu seguridad, todas las sesiones se cerraron. ingrese y comprueba si tu actividad es sospechosa en tu cuenta. También puedes cambiar su contraseña.' ], - "SESSION_EXPIRED" => "Tu sesión ha caducado. Inicie sesión nuevamente.", + 'SESSION_EXPIRED' => 'Tu sesión ha caducado. Inicie sesión nuevamente.', - "SETTINGS" => [ - "@TRANSLATION" => "Configuraciones de la cuenta", - "DESCRIPTION" => "Actualiza la configuración de su cuenta, incluido el correo electrónico, el nombre y la contraseña.", - "UPDATED" => "Configuración de la cuenta actualizada" + 'SETTINGS' => [ + '@TRANSLATION' => 'Configuraciones de la cuenta', + 'DESCRIPTION' => 'Actualiza la configuración de su cuenta, incluido el correo electrónico, el nombre y la contraseña.', + 'UPDATED' => 'Configuración de la cuenta actualizada' ], - "TOOLS" => "Herramientas de la cuenta", + 'TOOLS' => 'Herramientas de la cuenta', - "UNVERIFIED" => "Tu cuenta aún no se ha verificado. Revisa sus correos electrónicos / carpeta de spam para obtener instrucciones sobre la activación de la cuenta.", + 'UNVERIFIED' => 'Tu cuenta aún no se ha verificado. Revisa sus correos electrónicos / carpeta de spam para obtener instrucciones sobre la activación de la cuenta.', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Hemos enviado por correo electrónico un nuevo enlace de verificación a {{email}}. Comprueba tu bandeja de entrada y las carpetas de spam para este correo electrónico.", - "RESEND" => "Reenviar correo electrónico de verificación", - "COMPLETE" => "Has verificado correctamente su cuenta. Ahora puedes iniciar sesión.", - "EMAIL" => "Ingresa la dirección de correo electrónico que utilizaste para registrarte y tu correo electrónico de verificación será enviado de nuevo.", - "PAGE" => "Vuelve a enviar el correo electrónico de verificación de tu nueva cuenta.", - "SEND" => "Reenviar correo de verificación", - "TOKEN_NOT_FOUND" => "El token de verificación no existe / La cuenta ya está verificada", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'Hemos enviado por correo electrónico un nuevo enlace de verificación a {{email}}. Comprueba tu bandeja de entrada y las carpetas de spam para este correo electrónico.', + 'RESEND' => 'Reenviar correo electrónico de verificación', + 'COMPLETE' => 'Has verificado correctamente su cuenta. Ahora puedes iniciar sesión.', + 'EMAIL' => 'Ingresa la dirección de correo electrónico que utilizaste para registrarte y tu correo electrónico de verificación será enviado de nuevo.', + 'PAGE' => 'Vuelve a enviar el correo electrónico de verificación de tu nueva cuenta.', + 'SEND' => 'Reenviar correo de verificación', + 'TOKEN_NOT_FOUND' => 'El token de verificación no existe / La cuenta ya está verificada', ] ], - "EMAIL" => [ - "INVALID" => "No hay cuenta para {{email}} .", - "IN_USE" => "El correo electrónico {{email}} ya está en uso.", - "VERIFICATION_REQUIRED" => "Correo electrónico (se requiere verificación - ¡usa una dirección real!)" + 'EMAIL' => [ + 'INVALID' => 'No hay cuenta para {{email}} .', + 'IN_USE' => 'El correo electrónico {{email}} ya está en uso.', + 'VERIFICATION_REQUIRED' => 'Correo electrónico (se requiere verificación - ¡usa una dirección real!)' ], - "EMAIL_OR_USERNAME" => "Nombre de usuario o dirección de correo electrónico", + 'EMAIL_OR_USERNAME' => 'Nombre de usuario o dirección de correo electrónico', - "FIRST_NAME" => "Nombre", + 'FIRST_NAME' => 'Nombre', - "HEADER_MESSAGE_ROOT" => "USTED HA INGRESADO COMO USUARIO ROOT", + 'HEADER_MESSAGE_ROOT' => 'USTED HA INGRESADO COMO USUARIO ROOT', - "LAST_NAME" => "Apellidos", + 'LAST_NAME' => 'Apellidos', - "LOCALE" => [ - "ACCOUNT" => "El idioma y la configuración regional para utilizar en tu cuenta", - "INVALID" => "{{locale}} no es un idioma válido." + 'LOCALE' => [ + 'ACCOUNT' => 'El idioma y la configuración regional para utilizar en tu cuenta', + 'INVALID' => '{{locale}} no es un idioma válido.' ], - "LOGIN" => [ - "@TRANSLATION" => "Acceder", - "ALREADY_COMPLETE" => "¡Ya te has autentificado!", - "SOCIAL" => "O ingresa con", - "REQUIRED" => "Lo sentimos, debes iniciar sesión para acceder a este recurso." + 'LOGIN' => [ + '@TRANSLATION' => 'Acceder', + 'ALREADY_COMPLETE' => '¡Ya te has autentificado!', + 'SOCIAL' => 'O ingresa con', + 'REQUIRED' => 'Lo sentimos, debes iniciar sesión para acceder a este recurso.' ], - "LOGOUT" => "Cerrar sesión", + 'LOGOUT' => 'Cerrar sesión', - "NAME" => "Nombre", + 'NAME' => 'Nombre', - "NAME_AND_EMAIL" => "Nombre y correo electrónico", + 'NAME_AND_EMAIL' => 'Nombre y correo electrónico', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Inicia sesión en tu cuenta de {{site_name}} o regístrate para obtener una nueva cuenta.", - "SUBTITLE" => "Regístrate gratis o inicia sesión con una cuenta existente.", - "TITLE" => "¡Empecemos!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'Inicia sesión en tu cuenta de {{site_name}} o regístrate para obtener una nueva cuenta.', + 'SUBTITLE' => 'Regístrate gratis o inicia sesión con una cuenta existente.', + 'TITLE' => '¡Empecemos!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "Contraseña", + 'PASSWORD' => [ + '@TRANSLATION' => 'Contraseña', - "BETWEEN" => "Entre {{min}} - {{max}} (recomendado 12)", + 'BETWEEN' => 'Entre {{min}} - {{max}} (recomendado 12)', - "CONFIRM" => "Confirmar contraseña", - "CONFIRM_CURRENT" => "Por favor, confirma tu contraseña actual", - "CONFIRM_NEW" => "Confirmar nueva contraseña", - "CONFIRM_NEW_EXPLAIN" => "Vuelve a ingresar tu nueva contraseña", - "CONFIRM_NEW_HELP" => "Sólo se requiere si se selecciona una nueva contraseña", - "CREATE" => [ - "@TRANSLATION" => "Crear contraseña", - "PAGE" => "Elije una contraseña para su nueva cuenta.", - "SET" => "Establecer contraseña e iniciar sesión" + 'CONFIRM' => 'Confirmar contraseña', + 'CONFIRM_CURRENT' => 'Por favor, confirma tu contraseña actual', + 'CONFIRM_NEW' => 'Confirmar nueva contraseña', + 'CONFIRM_NEW_EXPLAIN' => 'Vuelve a ingresar tu nueva contraseña', + 'CONFIRM_NEW_HELP' => 'Sólo se requiere si se selecciona una nueva contraseña', + 'CREATE' => [ + '@TRANSLATION' => 'Crear contraseña', + 'PAGE' => 'Elije una contraseña para su nueva cuenta.', + 'SET' => 'Establecer contraseña e iniciar sesión' ], - "CURRENT" => "Contraseña actual", - "CURRENT_EXPLAIN" => "Debes confirmar tu contraseña actual para realizar cambios", - - "FORGOTTEN" => "Contraseña olvidada", - "FORGET" => [ - "@TRANSLATION" => "Olvidé mi contraseña", - - "COULD_NOT_UPDATE" => "No se pudo actualizar la contraseña.", - "EMAIL" => "Introduce la dirección de correo electrónico que utilizaste para registrarte. Se te enviará por correo electrónico un enlace con las instrucciones para restablecer tu contraseña.", - "EMAIL_SEND" => "Contraseña de correo electrónico Restablecer enlace", - "INVALID" => "No se pudo encontrar esta solicitud de restablecimiento de contraseña o ha caducado. Intenta volver a enviar tu solicitud .", - "PAGE" => "Obtén un enlace para restablecer tu contraseña.", - "REQUEST_CANNED" => "Se ha cancelado la solicitud de contraseña perdida.", - "REQUEST_SENT" => "Se ha enviado un enlace de restablecimiento de contraseña a {{email}} ." + 'CURRENT' => 'Contraseña actual', + 'CURRENT_EXPLAIN' => 'Debes confirmar tu contraseña actual para realizar cambios', + + 'FORGOTTEN' => 'Contraseña olvidada', + 'FORGET' => [ + '@TRANSLATION' => 'Olvidé mi contraseña', + + 'COULD_NOT_UPDATE' => 'No se pudo actualizar la contraseña.', + 'EMAIL' => 'Introduce la dirección de correo electrónico que utilizaste para registrarte. Se te enviará por correo electrónico un enlace con las instrucciones para restablecer tu contraseña.', + 'EMAIL_SEND' => 'Contraseña de correo electrónico Restablecer enlace', + 'INVALID' => 'No se pudo encontrar esta solicitud de restablecimiento de contraseña o ha caducado. Intenta volver a enviar tu solicitud .', + 'PAGE' => 'Obtén un enlace para restablecer tu contraseña.', + 'REQUEST_CANNED' => 'Se ha cancelado la solicitud de contraseña perdida.', + 'REQUEST_SENT' => 'Se ha enviado un enlace de restablecimiento de contraseña a {{email}} .' ], - "RESET" => [ - "@TRANSLATION" => "Restablecer la contraseña", - "CHOOSE" => "Por favor, elije una nueva contraseña para continuar.", - "PAGE" => "Elige una nueva contraseña para tu cuenta.", - "SEND" => "Establecer nueva contraseña e iniciar sesión" + 'RESET' => [ + '@TRANSLATION' => 'Restablecer la contraseña', + 'CHOOSE' => 'Por favor, elije una nueva contraseña para continuar.', + 'PAGE' => 'Elige una nueva contraseña para tu cuenta.', + 'SEND' => 'Establecer nueva contraseña e iniciar sesión' ], - "HASH_FAILED" => "El hash de la contraseña ha fallado. Ponte en contacto con un administrador del sitio.", - "INVALID" => "La contraseña actual no coincide con la que tenemos registrada", - "NEW" => "Nueva contraseña", - "NOTHING_TO_UPDATE" => "No se puede actualizar con la misma contraseña", - "UPDATED" => "Contraseña de la cuenta actualizada" + 'HASH_FAILED' => 'El hash de la contraseña ha fallado. Ponte en contacto con un administrador del sitio.', + 'INVALID' => 'La contraseña actual no coincide con la que tenemos registrada', + 'NEW' => 'Nueva contraseña', + 'NOTHING_TO_UPDATE' => 'No se puede actualizar con la misma contraseña', + 'UPDATED' => 'Contraseña de la cuenta actualizada' ], - "PROFILE" => [ - "SETTINGS" => "Configuración de perfil", - "UPDATED" => "Configuración del perfil actualizada" + 'PROFILE' => [ + 'SETTINGS' => 'Configuración de perfil', + 'UPDATED' => 'Configuración del perfil actualizada' ], - "RATE_LIMIT_EXCEEDED" => "Se ha superado el límite de velocidad para esta acción. Debe esperar otro {{delay}} segundos antes de que se le permita hacer otro intento.", - - "REGISTER" => "Registro", - "REGISTER_ME" => "Inscríbeme", - "REGISTRATION" => [ - "BROKEN" => "Lo sentimos, hay un problema con nuestro proceso de registro de cuenta. Ponte en contacto con nosotros directamente para obtener ayuda.", - "COMPLETE_TYPE1" => "Te has registrado exitosamente. Ahora puedes iniciar sesión.", - "COMPLETE_TYPE2" => "Te has registrado exitosamente. Se ha enviado un enlace para activar tu cuenta a {{email}} . No podrás iniciar sesión hasta que complete este paso.", - "DISABLED" => "Lo sentimos, el registro de cuenta se ha deshabilitado.", - "LOGOUT" => "Lo siento, no puedes registrarte para una cuenta mientras está conectado. Por favor, cierra la sesión primero.", - "WELCOME" => "El registro es rápido y sencillo." + 'RATE_LIMIT_EXCEEDED' => 'Se ha superado el límite de velocidad para esta acción. Debe esperar otro {{delay}} segundos antes de que se le permita hacer otro intento.', + + 'REGISTER' => 'Registro', + 'REGISTER_ME' => 'Inscríbeme', + 'REGISTRATION' => [ + 'BROKEN' => 'Lo sentimos, hay un problema con nuestro proceso de registro de cuenta. Ponte en contacto con nosotros directamente para obtener ayuda.', + 'COMPLETE_TYPE1' => 'Te has registrado exitosamente. Ahora puedes iniciar sesión.', + 'COMPLETE_TYPE2' => 'Te has registrado exitosamente. Se ha enviado un enlace para activar tu cuenta a {{email}} . No podrás iniciar sesión hasta que complete este paso.', + 'DISABLED' => 'Lo sentimos, el registro de cuenta se ha deshabilitado.', + 'LOGOUT' => 'Lo siento, no puedes registrarte para una cuenta mientras está conectado. Por favor, cierra la sesión primero.', + 'WELCOME' => 'El registro es rápido y sencillo.' ], - - "REMEMBER_ME" => "¡Recuérdame!", - "REMEMBER_ME_ON_COMPUTER" => "Recuérdame en este ordenador (no se recomienda para ordenadores públicos)", - "SIGNIN" => "Iniciar sesión", - "SIGNIN_OR_REGISTER" => "Ingresa o Registro", - "SIGNUP" => "Regístrate", - "SUGGEST" => "Sugerencia", - "HAVE_ACCOUNT" => "¿Ya tienes una cuenta?", - "SIGN_IN_HERE"=> "¿Ya tienes una cuenta? Acceda aquí. ", + 'REMEMBER_ME' => '¡Recuérdame!', + 'REMEMBER_ME_ON_COMPUTER' => 'Recuérdame en este ordenador (no se recomienda para ordenadores públicos)', + 'SIGNIN' => 'Iniciar sesión', + 'SIGNIN_OR_REGISTER' => 'Ingresa o Registro', + 'SIGNUP' => 'Regístrate', + 'SUGGEST' => 'Sugerencia', + 'HAVE_ACCOUNT' => '¿Ya tienes una cuenta?', + 'SIGN_IN_HERE' => '¿Ya tienes una cuenta? Acceda aquí. ', - "TOS" => "Términos y Condiciones", - "TOS_AGREEMENT" => "Al registrar una cuenta con {{site_title}}, acepta los términos y condiciones .", - "TOS_FOR" => "Términos y condiciones para {{title}}", + 'TOS' => 'Términos y Condiciones', + 'TOS_AGREEMENT' => 'Al registrar una cuenta con {{site_title}}, acepta los términos y condiciones .', + 'TOS_FOR' => 'Términos y condiciones para {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "Nombre de usuario", + 'USERNAME' => [ + '@TRANSLATION' => 'Nombre de usuario', - "CHOOSE" => "Elige un nombre de usuario único", - "INVALID" => "Nombre de usuario no válido", - "IN_USE" => "El nombre de usuario {{user_name}} ya está en uso.", - "NOT_AVAILABLE" => "El nombre de usuario {{user_name}} no está disponible. Elija otro nombre o haga clic en \"sugerir\"." + 'CHOOSE' => 'Elige un nombre de usuario único', + 'INVALID' => 'Nombre de usuario no válido', + 'IN_USE' => 'El nombre de usuario {{user_name}} ya está en uso.', + 'NOT_AVAILABLE' => 'El nombre de usuario {{user_name}} no está disponible. Elija otro nombre o haga clic en "sugerir".' ], - "USER_ID_INVALID" => "El ID de usuario solicitado no existe.", - "USER_OR_EMAIL_INVALID" => "El nombre de usuario o la dirección de correo electrónico no son válidos.", - "USER_OR_PASS_INVALID" => "Usuario no encontrado o la contraseña no es válida.", + 'USER_ID_INVALID' => 'El ID de usuario solicitado no existe.', + 'USER_OR_EMAIL_INVALID' => 'El nombre de usuario o la dirección de correo electrónico no son válidos.', + 'USER_OR_PASS_INVALID' => 'Usuario no encontrado o la contraseña no es válida.', - "WELCOME" => "Bienvenido de nuevo, {{first_name}}" + 'WELCOME' => 'Bienvenido de nuevo, {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/es_ES/validate.php b/app/sprinkles/account/locale/es_ES/validate.php index 3f788fe16..11276e212 100755 --- a/app/sprinkles/account/locale/es_ES/validate.php +++ b/app/sprinkles/account/locale/es_ES/validate.php @@ -4,16 +4,16 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Spanish message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\es_ES * @author rafa31gz */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Tu contraseña y contraseña de confirmación deben coincidir.", - "USERNAME" => "El nombre de usuario puede consistir sólo en letras minúsculas, números, '.', '-' y '_'." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'Tu contraseña y contraseña de confirmación deben coincidir.', + 'USERNAME' => "El nombre de usuario puede consistir sólo en letras minúsculas, números, '.', '-' y '_'." ] ]; diff --git a/app/sprinkles/account/locale/fa/messages.php b/app/sprinkles/account/locale/fa/messages.php index 22623babf..adfed759d 100644 --- a/app/sprinkles/account/locale/fa/messages.php +++ b/app/sprinkles/account/locale/fa/messages.php @@ -5,174 +5,174 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Standard Farsi/Persian message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\fa * @author aminakbari */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "حساب", + 'ACCOUNT' => [ + '@TRANSLATION' => 'حساب', - "ACCESS_DENIED" => "به نظر می آید که شما اجازه انجام این کار را ندارید", + 'ACCESS_DENIED' => 'به نظر می آید که شما اجازه انجام این کار را ندارید', - "DISABLED" => "این حساب کاربری غیر فعال شده است. برای اطلاعات بیشتر، لطفا با ما تماس برقرار کنید.", + 'DISABLED' => 'این حساب کاربری غیر فعال شده است. برای اطلاعات بیشتر، لطفا با ما تماس برقرار کنید.', - "EMAIL_UPDATED" => "آدرس پست الکترونیکی حساب، به روز رسانی شد", + 'EMAIL_UPDATED' => 'آدرس پست الکترونیکی حساب، به روز رسانی شد', - "INVALID" => "این اکانت موجود نیست. ممکن است که حذف شده باشد. برای اطلاعات بیشتر، لطفا با ما تماس برقرار کنید.", + 'INVALID' => 'این اکانت موجود نیست. ممکن است که حذف شده باشد. برای اطلاعات بیشتر، لطفا با ما تماس برقرار کنید.', - "MASTER_NOT_EXISTS" => "تا زمانی که حساب اصلی ساخته نشده است نمیتوانید حساب کاربری جدیدی بسازید.", - "MY" => "حساب من", + 'MASTER_NOT_EXISTS' => 'تا زمانی که حساب اصلی ساخته نشده است نمیتوانید حساب کاربری جدیدی بسازید.', + 'MY' => 'حساب من', - "SESSION_COMPROMISED" => "ممکن است سژن شما مورد حمله واقع شده باشد. بهتر است با همه دستگاه های خود از وب سایت خارج شوید و دوباره وارد شوید. همچنین توجه بفرمایید که اطلاعات حسابتان، مورد حمله واقع نشده باشد. ", - "SESSION_COMPROMISED_TITLE" => "ممکن است که اکانت شما مورد حمله واقع شده باشد", - "SESSION_EXPIRED" => "سژن شما به پایان رسیده است. لطفا دوباره وارد شوید.", + 'SESSION_COMPROMISED' => 'ممکن است سژن شما مورد حمله واقع شده باشد. بهتر است با همه دستگاه های خود از وب سایت خارج شوید و دوباره وارد شوید. همچنین توجه بفرمایید که اطلاعات حسابتان، مورد حمله واقع نشده باشد. ', + 'SESSION_COMPROMISED_TITLE' => 'ممکن است که اکانت شما مورد حمله واقع شده باشد', + 'SESSION_EXPIRED' => 'سژن شما به پایان رسیده است. لطفا دوباره وارد شوید.', - "SETTINGS" => [ - "@TRANSLATION" => "تنظیمات حساب", - "DESCRIPTION" => "اطلاعات حسابتان یعنی پست الکترونیکی،نام و گذرواژه خود را به روز رسانی کنید", - "UPDATED" => "تنظیمات حساب به روز رسانی شد" + 'SETTINGS' => [ + '@TRANSLATION' => 'تنظیمات حساب', + 'DESCRIPTION' => 'اطلاعات حسابتان یعنی پست الکترونیکی،نام و گذرواژه خود را به روز رسانی کنید', + 'UPDATED' => 'تنظیمات حساب به روز رسانی شد' ], - "TOOLS" => "ابزار حساب", + 'TOOLS' => 'ابزار حساب', - "UNVERIFIED" => "شما هنوز آدرس پست الکترونیکی خود را فعال نکرده اید. برای فعال سازی لطفا ایمیل خود را چک کنید.", + 'UNVERIFIED' => 'شما هنوز آدرس پست الکترونیکی خود را فعال نکرده اید. برای فعال سازی لطفا ایمیل خود را چک کنید.', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "لینک فعال سازی برای ایمیل {{email}} ارسال شد. لطفا ایمیل خود را چک کنید.", - "RESEND" => "ارسال دوباره ایمیل فعال سازی", - "COMPLETE" => "شما پست الکترونیکی خود را با موفقیت فعال سازی کردید. حالا می توانید وارد شوید.", - "EMAIL" => "لطفا آدرس پست الکترونیکی که با آن ثبت نام کردید وارد کنید تا ایمیل فعال سازی دوباره برایتان ارسال شود.", - "PAGE" => "ارسال دوباره ایمیل فعال سازی برای حساب جدید شما", - "SEND" => "ارسال ایمیل فعال سازی برای حساب کاربری", - "TOKEN_NOT_FOUND" => "این حساب کاربری یا قبلا فعال شده است و یا کد فعال سازی موجود نیست.", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'لینک فعال سازی برای ایمیل {{email}} ارسال شد. لطفا ایمیل خود را چک کنید.', + 'RESEND' => 'ارسال دوباره ایمیل فعال سازی', + 'COMPLETE' => 'شما پست الکترونیکی خود را با موفقیت فعال سازی کردید. حالا می توانید وارد شوید.', + 'EMAIL' => 'لطفا آدرس پست الکترونیکی که با آن ثبت نام کردید وارد کنید تا ایمیل فعال سازی دوباره برایتان ارسال شود.', + 'PAGE' => 'ارسال دوباره ایمیل فعال سازی برای حساب جدید شما', + 'SEND' => 'ارسال ایمیل فعال سازی برای حساب کاربری', + 'TOKEN_NOT_FOUND' => 'این حساب کاربری یا قبلا فعال شده است و یا کد فعال سازی موجود نیست.', ] ], - "EMAIL" => [ - "INVALID" => "حساب کاربری با {{email}} ثبت نشده است.", - "IN_USE" => "ایمیل {{email}} قبلا استفاده شده است", - "VERIFICATION_REQUIRED" => "آدرس پست الکترونیکی را بصورت صحیح وارد کنید" + 'EMAIL' => [ + 'INVALID' => 'حساب کاربری با {{email}} ثبت نشده است.', + 'IN_USE' => 'ایمیل {{email}} قبلا استفاده شده است', + 'VERIFICATION_REQUIRED' => 'آدرس پست الکترونیکی را بصورت صحیح وارد کنید' ], - "EMAIL_OR_USERNAME" => "نام کاربری یا آدرس پست الکترونیکی", + 'EMAIL_OR_USERNAME' => 'نام کاربری یا آدرس پست الکترونیکی', - "FIRST_NAME" => "نام", + 'FIRST_NAME' => 'نام', - "HEADER_MESSAGE_ROOT" => "شما بعنوان کاربر اصلی وارد شده اید", + 'HEADER_MESSAGE_ROOT' => 'شما بعنوان کاربر اصلی وارد شده اید', - "LAST_NAME" => "نام خانوادگی", + 'LAST_NAME' => 'نام خانوادگی', - "LOCALE" => [ - "ACCOUNT" => "زبان انتخابی برای حساب شما", - "INVALID" => "{{locale}} زبان صحیحی نیست" + 'LOCALE' => [ + 'ACCOUNT' => 'زبان انتخابی برای حساب شما', + 'INVALID' => '{{locale}} زبان صحیحی نیست' ], - "LOGIN" => [ - "@TRANSLATION" => "ورود", - "ALREADY_COMPLETE" => "شما قبلا وارد شده اید.", - "SOCIAL" => "یا با روش های زیر وارد شوید", - "REQUIRED" => "برای دیدن این صفحه لازم است که وارد شوید" + 'LOGIN' => [ + '@TRANSLATION' => 'ورود', + 'ALREADY_COMPLETE' => 'شما قبلا وارد شده اید.', + 'SOCIAL' => 'یا با روش های زیر وارد شوید', + 'REQUIRED' => 'برای دیدن این صفحه لازم است که وارد شوید' ], - "LOGOUT" => "خروج", + 'LOGOUT' => 'خروج', - "NAME" => "نام", + 'NAME' => 'نام', - "NAME_AND_EMAIL" => "نام و پست الکترونیکی", + 'NAME_AND_EMAIL' => 'نام و پست الکترونیکی', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "به حساب کاربری خود در {{site_name}} وارد شوید و یا حساب کاربری جدیدی بسازید", - "SUBTITLE" => "ثبت نام کنید و یا با حساب کاربری خود وارد شوید", - "TITLE" => "بیایید شروع کنیم!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'به حساب کاربری خود در {{site_name}} وارد شوید و یا حساب کاربری جدیدی بسازید', + 'SUBTITLE' => 'ثبت نام کنید و یا با حساب کاربری خود وارد شوید', + 'TITLE' => 'بیایید شروع کنیم!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "گذرواژه", - - "BETWEEN" => "بین {{min}}-{{max}} حرف", - - "CONFIRM" => "رمز عبور را وارد کنید", - "CONFIRM_CURRENT" => "لطفا رمز عبور فعلی را تایید کنید", - "CONFIRM_NEW" => "رمز عبور جدید را وارد کنید", - "CONFIRM_NEW_EXPLAIN" => "رمز عبور جدید را تکرار کنید", - "CONFIRM_NEW_HELP" => "فقط زمانی لازم است که می خواهید گذرواژه جدیدی انتخاب کنید", - "CURRENT" => "گذرواژه فعلی", - "CURRENT_EXPLAIN" => "شما باید گذرواژه فعلی خود را وارد کنید تا بتوانید اطلاعات را به روز رسانی کنید", - - "FORGOTTEN" => "فراموشی گذرواژه", - "FORGET" => [ - "@TRANSLATION" => "گذرواژه خود را فراموش کرده ام", - - "COULD_NOT_UPDATE" => "گذرواژه به روز رسانی نشد", - "EMAIL" => "لطفا آدرس پست الکترونیکی که در زمان ثبت نام استفاده کردید، وارد کنید. لینک بازیابی گذرواژه برای شما ایمیل خواهد شد.", - "EMAIL_SEND" => "لینک بازیابی گذرواژه ایمیل شود", - "INVALID" => "درخواست بازیابی کذرواژه پیدا نشد و یا منقضی شده است. لطفا درخواست را دوباره ارسال کنید", - "PAGE" => "دریافت لینک بازیابی گذرواژه", - "REQUEST_CANNED" => "درخواست فراموشی گذرواژه، حذف شد.", - "REQUEST_SENT" => "ایمیل بازیابی گذرواژه به {{email}} ارسال شد." + 'PASSWORD' => [ + '@TRANSLATION' => 'گذرواژه', + + 'BETWEEN' => 'بین {{min}}-{{max}} حرف', + + 'CONFIRM' => 'رمز عبور را وارد کنید', + 'CONFIRM_CURRENT' => 'لطفا رمز عبور فعلی را تایید کنید', + 'CONFIRM_NEW' => 'رمز عبور جدید را وارد کنید', + 'CONFIRM_NEW_EXPLAIN' => 'رمز عبور جدید را تکرار کنید', + 'CONFIRM_NEW_HELP' => 'فقط زمانی لازم است که می خواهید گذرواژه جدیدی انتخاب کنید', + 'CURRENT' => 'گذرواژه فعلی', + 'CURRENT_EXPLAIN' => 'شما باید گذرواژه فعلی خود را وارد کنید تا بتوانید اطلاعات را به روز رسانی کنید', + + 'FORGOTTEN' => 'فراموشی گذرواژه', + 'FORGET' => [ + '@TRANSLATION' => 'گذرواژه خود را فراموش کرده ام', + + 'COULD_NOT_UPDATE' => 'گذرواژه به روز رسانی نشد', + 'EMAIL' => 'لطفا آدرس پست الکترونیکی که در زمان ثبت نام استفاده کردید، وارد کنید. لینک بازیابی گذرواژه برای شما ایمیل خواهد شد.', + 'EMAIL_SEND' => 'لینک بازیابی گذرواژه ایمیل شود', + 'INVALID' => 'درخواست بازیابی کذرواژه پیدا نشد و یا منقضی شده است. لطفا درخواست را دوباره ارسال کنید', + 'PAGE' => 'دریافت لینک بازیابی گذرواژه', + 'REQUEST_CANNED' => 'درخواست فراموشی گذرواژه، حذف شد.', + 'REQUEST_SENT' => 'ایمیل بازیابی گذرواژه به {{email}} ارسال شد.' ], - "RESET" => [ - "@TRANSLATION" => "تغییر گذرواژه", - "CHOOSE" => "لطفا گذرواژه جدید را انتخاب کنید", - "PAGE" => "برای حساب خود، گذرواژه جدیدی انتخاب کنید.", - "SEND" => "گذرواژه جدید را انتخاب کرده و وارد شوید" + 'RESET' => [ + '@TRANSLATION' => 'تغییر گذرواژه', + 'CHOOSE' => 'لطفا گذرواژه جدید را انتخاب کنید', + 'PAGE' => 'برای حساب خود، گذرواژه جدیدی انتخاب کنید.', + 'SEND' => 'گذرواژه جدید را انتخاب کرده و وارد شوید' ], - "HASH_FAILED" => "هشینگ گذرواژه با مشکل روبرو شد. لطفا با مسولین وب سایت تماس برقرار کنید", - "INVALID" => "گذرواژه فعلی درست وارد نشده است", - "NEW" => "گذرواژه جدید", - "NOTHING_TO_UPDATE" => "شما نمیتوانید همان گذرواژه را دوباره وارد کنید", - "UPDATED" => "گذرواژه به روز رسانی شد" + 'HASH_FAILED' => 'هشینگ گذرواژه با مشکل روبرو شد. لطفا با مسولین وب سایت تماس برقرار کنید', + 'INVALID' => 'گذرواژه فعلی درست وارد نشده است', + 'NEW' => 'گذرواژه جدید', + 'NOTHING_TO_UPDATE' => 'شما نمیتوانید همان گذرواژه را دوباره وارد کنید', + 'UPDATED' => 'گذرواژه به روز رسانی شد' ], - "PROFILE" => [ - "SETTINGS" => "تنظیمات شخصی حساب", - "UPDATED" => "تنظیمات شخصی حساب به روز رسانی شد" + 'PROFILE' => [ + 'SETTINGS' => 'تنظیمات شخصی حساب', + 'UPDATED' => 'تنظیمات شخصی حساب به روز رسانی شد' ], - "REGISTER" => "ثبت نام", - "REGISTER_ME" => "ثبت نام کن", + 'REGISTER' => 'ثبت نام', + 'REGISTER_ME' => 'ثبت نام کن', - "REGISTRATION" => [ - "BROKEN" => "متاسفانه پروسه ثبت نام با مشکلی روبرو شد. برای دریافت کمک لطفا با ما تماس بگیرید.", - "COMPLETE_TYPE1" => "شما با موفقیت ثبت نام کردید. حالا میتوانید وارد شوید.", - "COMPLETE_TYPE2" => "شما با موفقیت ثبت نام کردید. لینک فعال سازی حساب به آدرس پست الکترونیکیتان {{email}} ارسال شد. بدون فعال سازی نمیتوانید وارد شوید.", - "DISABLED" => "با عرض تاسف، امکان ثبت در وب سایت، غیر فعال شده است.", - "LOGOUT" => "شما همزمان این که وارد شده اید نمیتوانید حساب کاربری جدیدی بسازید. لطفا ابتدا خارج شوید.", - "WELCOME" => "سریع و ساده ثبت نام کنید" + 'REGISTRATION' => [ + 'BROKEN' => 'متاسفانه پروسه ثبت نام با مشکلی روبرو شد. برای دریافت کمک لطفا با ما تماس بگیرید.', + 'COMPLETE_TYPE1' => 'شما با موفقیت ثبت نام کردید. حالا میتوانید وارد شوید.', + 'COMPLETE_TYPE2' => 'شما با موفقیت ثبت نام کردید. لینک فعال سازی حساب به آدرس پست الکترونیکیتان {{email}} ارسال شد. بدون فعال سازی نمیتوانید وارد شوید.', + 'DISABLED' => 'با عرض تاسف، امکان ثبت در وب سایت، غیر فعال شده است.', + 'LOGOUT' => 'شما همزمان این که وارد شده اید نمیتوانید حساب کاربری جدیدی بسازید. لطفا ابتدا خارج شوید.', + 'WELCOME' => 'سریع و ساده ثبت نام کنید' ], - "RATE_LIMIT_EXCEEDED" => "شما محدودیت تعداد انجام این کار را پشت سر گذاشتید. لطفا {{delay}} ثانیه دیگر صبر کرده و دوباره تلاش کنید.", - "REMEMBER_ME" => "من را به خاطر بسپار!", - "REMEMBER_ME_ON_COMPUTER" => "من را در این دستگاه به خاطر بسپار (برای دستگاه های عمومی پیشنهاد نمی شود)", + 'RATE_LIMIT_EXCEEDED' => 'شما محدودیت تعداد انجام این کار را پشت سر گذاشتید. لطفا {{delay}} ثانیه دیگر صبر کرده و دوباره تلاش کنید.', + 'REMEMBER_ME' => 'من را به خاطر بسپار!', + 'REMEMBER_ME_ON_COMPUTER' => 'من را در این دستگاه به خاطر بسپار (برای دستگاه های عمومی پیشنهاد نمی شود)', - "SIGNIN" => "ورود", - "SIGNIN_OR_REGISTER" => "ثبت نام کنید و یا وارد شوید", - "SIGNUP" => "ثبت نام", + 'SIGNIN' => 'ورود', + 'SIGNIN_OR_REGISTER' => 'ثبت نام کنید و یا وارد شوید', + 'SIGNUP' => 'ثبت نام', - "TOS" => "شرایط و مقررات", - "TOS_AGREEMENT" => "با ثبت نام در {{site_title}} موافقت خود با شرایط و مقررات را نشان میدهید.", - "TOS_FOR" => "شرایط و مقررات {{title}}", + 'TOS' => 'شرایط و مقررات', + 'TOS_AGREEMENT' => 'با ثبت نام در {{site_title}} موافقت خود با شرایط و مقررات را نشان میدهید.', + 'TOS_FOR' => 'شرایط و مقررات {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "نام کاربری", + 'USERNAME' => [ + '@TRANSLATION' => 'نام کاربری', - "CHOOSE" => "یک نام کاربری منحصر به فرد انتخاب کنید", - "INVALID" => "نام کاربری معتبر نیست", - "IN_USE" => "نام کاربری {{user_name}} قبلا استفاده شده است", - "NOT_AVAILABLE" => "نام کاربری {{user_name}} موجود نیست. لطفا نام کاربری دیگری انتخاب کنید" + 'CHOOSE' => 'یک نام کاربری منحصر به فرد انتخاب کنید', + 'INVALID' => 'نام کاربری معتبر نیست', + 'IN_USE' => 'نام کاربری {{user_name}} قبلا استفاده شده است', + 'NOT_AVAILABLE' => 'نام کاربری {{user_name}} موجود نیست. لطفا نام کاربری دیگری انتخاب کنید' ], - "USER_ID_INVALID" => "آی دی کاربری مد نظر شما موجود نیست", - "USER_OR_EMAIL_INVALID" => "نام کاربری و یا آدرس پست الکترونیکی معتبر نیست", - "USER_OR_PASS_INVALID" => "کاربری یافت نشد و یا گذرواژه صحیح نیست", + 'USER_ID_INVALID' => 'آی دی کاربری مد نظر شما موجود نیست', + 'USER_OR_EMAIL_INVALID' => 'نام کاربری و یا آدرس پست الکترونیکی معتبر نیست', + 'USER_OR_PASS_INVALID' => 'کاربری یافت نشد و یا گذرواژه صحیح نیست', - "WELCOME" => "خوش آمدید {{first_name}}" + 'WELCOME' => 'خوش آمدید {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/fa/validate.php b/app/sprinkles/account/locale/fa/validate.php index 4e8dc74e0..98dd9d4cb 100644 --- a/app/sprinkles/account/locale/fa/validate.php +++ b/app/sprinkles/account/locale/fa/validate.php @@ -5,16 +5,16 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Standard Farsi/Persian message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\fa * @author aminakbari */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "گذرواژه و تکرار آن باید با یکدیگر تطبیق پیدا کنند", - "USERNAME" => "نام کاربری فقط میتواند از حروف کوچک، اعداد، '.'، '-' و '_' متشکل شوند." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'گذرواژه و تکرار آن باید با یکدیگر تطبیق پیدا کنند', + 'USERNAME' => "نام کاربری فقط میتواند از حروف کوچک، اعداد، '.'، '-' و '_' متشکل شوند." ] ]; diff --git a/app/sprinkles/account/locale/fr_FR/messages.php b/app/sprinkles/account/locale/fr_FR/messages.php index 6e5a032f1..b40472e61 100644 --- a/app/sprinkles/account/locale/fr_FR/messages.php +++ b/app/sprinkles/account/locale/fr_FR/messages.php @@ -4,176 +4,176 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * French message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\fr * @author Louis Charette */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Compte d'utilisateur", + 'ACCOUNT' => [ + '@TRANSLATION' => "Compte d'utilisateur", - "ACCESS_DENIED" => "Hmm, on dirait que vous n'avez pas la permission de faire ceci.", + 'ACCESS_DENIED' => "Hmm, on dirait que vous n'avez pas la permission de faire ceci.", - "DISABLED" => "Ce compte a été désactivé. Veuillez nous contacter pour plus d'informations.", + 'DISABLED' => "Ce compte a été désactivé. Veuillez nous contacter pour plus d'informations.", - "EMAIL_UPDATED" => "Adresse email mise à jour", + 'EMAIL_UPDATED' => 'Adresse email mise à jour', - "INVALID" => "Ce compte n'existe pas. Il a peut-être été supprimé. Veuillez nous contacter pour plus d'informations.", + 'INVALID' => "Ce compte n'existe pas. Il a peut-être été supprimé. Veuillez nous contacter pour plus d'informations.", - "MASTER_NOT_EXISTS" => "Vous ne pouvez pas enregistrer un compte tant que le compte principal n'a pas été créé!", - "MY" => "Mon compte", + 'MASTER_NOT_EXISTS' => "Vous ne pouvez pas enregistrer un compte tant que le compte principal n'a pas été créé!", + 'MY' => 'Mon compte', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Votre session a été compromise. Vous devez vous déconnecter de tous les périphériques, puis vous reconnecter et vous assurer que vos données n'ont pas été altérées.", - "TITLE" => "Votre compte peut avoir été compromis" + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => "Votre session a été compromise. Vous devez vous déconnecter de tous les périphériques, puis vous reconnecter et vous assurer que vos données n'ont pas été altérées.", + 'TITLE' => 'Votre compte peut avoir été compromis' ], - "SESSION_EXPIRED" => "Votre session a expiré. Veuillez vous connecter à nouveau.", + 'SESSION_EXPIRED' => 'Votre session a expiré. Veuillez vous connecter à nouveau.', - "SETTINGS" => [ - "@TRANSLATION" => "Paramètres du compte", - "DESCRIPTION" => "Mettez à jour les paramètres de votre compte, y compris votre adresse e-mail, votre nom et votre mot de passe.", - "UPDATED" => "Paramètres du compte mis à jour" + 'SETTINGS' => [ + '@TRANSLATION' => 'Paramètres du compte', + 'DESCRIPTION' => 'Mettez à jour les paramètres de votre compte, y compris votre adresse e-mail, votre nom et votre mot de passe.', + 'UPDATED' => 'Paramètres du compte mis à jour' ], - "TOOLS" => "Outils du compte", + 'TOOLS' => 'Outils du compte', - "UNVERIFIED" => "Votre compte n'a pas encore été vérifié. Vérifiez vos emails / dossier spam pour les instructions d'activation du compte.", + 'UNVERIFIED' => "Votre compte n'a pas encore été vérifié. Vérifiez vos emails / dossier spam pour les instructions d'activation du compte.", - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Nous avons envoyé un nouveau lien de vérification à {{email}}. Veuillez vérifier vos dossiers de boîte de réception et de spam pour ce courriel.", - "RESEND" => "Renvoyer le courriel de validation", - "COMPLETE" => "Votre compte a été validé. Vous pouvez maintenant vous connecter.", - "EMAIL" => "Veuillez saisir l'adresse email que vous avez utilisée pour vous inscrire et votre courriel de vérification sera renvoyé.", - "PAGE" => "Renvoyer l'email de validation de votre nouveau compte.", - "SEND" => "Envoyer le lien de validation de mon compte", - "TOKEN_NOT_FOUND" => "Le jeton de vérification n'existe pas / Le compte est déjà vérifié", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'Nous avons envoyé un nouveau lien de vérification à {{email}}. Veuillez vérifier vos dossiers de boîte de réception et de spam pour ce courriel.', + 'RESEND' => 'Renvoyer le courriel de validation', + 'COMPLETE' => 'Votre compte a été validé. Vous pouvez maintenant vous connecter.', + 'EMAIL' => "Veuillez saisir l'adresse email que vous avez utilisée pour vous inscrire et votre courriel de vérification sera renvoyé.", + 'PAGE' => "Renvoyer l'email de validation de votre nouveau compte.", + 'SEND' => 'Envoyer le lien de validation de mon compte', + 'TOKEN_NOT_FOUND' => "Le jeton de vérification n'existe pas / Le compte est déjà vérifié", ] ], - "EMAIL" => [ - "INVALID" => "Il n'y a aucun compte pour {{email}}.", - "IN_USE" => "Le email {{email}} est déjà utilisé.", - "VERIFICATION_REQUIRED" => "Email (vérification requise - utiliser une adresse réelle!)" + 'EMAIL' => [ + 'INVALID' => "Il n'y a aucun compte pour {{email}}.", + 'IN_USE' => 'Le email {{email}} est déjà utilisé.', + 'VERIFICATION_REQUIRED' => 'Email (vérification requise - utiliser une adresse réelle!)' ], - "EMAIL_OR_USERNAME" => "Nom d'utilisateur ou adresse email", + 'EMAIL_OR_USERNAME' => "Nom d'utilisateur ou adresse email", - "FIRST_NAME" => "Prénom", + 'FIRST_NAME' => 'Prénom', - "HEADER_MESSAGE_ROOT" => "VOUS ÊTES CONNECTÉ EN TANT QUE L'UTILISATEUR ROOT", + 'HEADER_MESSAGE_ROOT' => "VOUS ÊTES CONNECTÉ EN TANT QUE L'UTILISATEUR ROOT", - "LAST_NAME" => "Nom de famille", + 'LAST_NAME' => 'Nom de famille', - "LOCALE" => [ - "ACCOUNT" => "La langue utilisé pour votre compte d'utilisateur", - "INVALID" => "{{locale}} n'est pas une langue valide." + 'LOCALE' => [ + 'ACCOUNT' => "La langue utilisé pour votre compte d'utilisateur", + 'INVALID' => "{{locale}} n'est pas une langue valide." ], - "LOGIN" => [ - "@TRANSLATION" => "Connexion", - "ALREADY_COMPLETE" => "Vous êtes déjà connecté!", - "SOCIAL" => "Ou se connecter avec", - "REQUIRED" => "Désolé, vous devez être connecté pour accéder à cette ressource." + 'LOGIN' => [ + '@TRANSLATION' => 'Connexion', + 'ALREADY_COMPLETE' => 'Vous êtes déjà connecté!', + 'SOCIAL' => 'Ou se connecter avec', + 'REQUIRED' => 'Désolé, vous devez être connecté pour accéder à cette ressource.' ], - "LOGOUT" => "Déconnexion", + 'LOGOUT' => 'Déconnexion', - "NAME" => "Nom", + 'NAME' => 'Nom', - "NAME_AND_EMAIL" => "Nom et email", + 'NAME_AND_EMAIL' => 'Nom et email', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Connectez-vous à votre compte {{site_name}} ou enregistrez-vous pour un nouveau compte.", - "SUBTITLE" => "Inscrivez-vous gratuitement ou connectez-vous avec un compte existant.", - "TITLE" => "Commençons!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'Connectez-vous à votre compte {{site_name}} ou enregistrez-vous pour un nouveau compte.', + 'SUBTITLE' => 'Inscrivez-vous gratuitement ou connectez-vous avec un compte existant.', + 'TITLE' => 'Commençons!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "Mot de passe", - - "BETWEEN" => "Entre {{min}} et {{max}} charactères", - - "CONFIRM" => "Confirmer le mot de passe", - "CONFIRM_CURRENT" => "Veuillez confirmer votre mot de passe actuel", - "CONFIRM_NEW" => "Confirmer le nouveau mot de passe", - "CONFIRM_NEW_EXPLAIN" => "Confirmer le mot de passe", - "CONFIRM_NEW_HELP" => "Obligatoire uniquement si vous sélectionnez un nouveau mot de passe", - "CURRENT" => "Mot de passe actuel", - "CURRENT_EXPLAIN" => "Vous devez confirmer votre mot de passe actuel pour apporter des modifications", - - "FORGOTTEN" => "Mot de passe oublié", - "FORGET" => [ - "@TRANSLATION" => "J'ai oublié mon mot de passe", - - "COULD_NOT_UPDATE" => "Impossible de mettre à jour le mot de passe.", - "EMAIL" => "Veuillez saisir l'adresse e-mail que vous avez utilisée pour vous inscrire. Un lien avec les instructions pour réinitialiser votre mot de passe vous sera envoyé par email.", - "EMAIL_SEND" => "Envoyer le lien de réinitialisation", - "INVALID" => "Cette requête de réinitialisation de mot de passe n'a pas pu être trouvée ou a expiré. Veuillez réessayer de soumettre votre demande .", - "PAGE" => "Obtenir un lien pour réinitialiser votre mot de passe.", - "REQUEST_CANNED" => "Demande de mot de passe perdu annulée.", - "REQUEST_SENT" => "Si l'adresse e-mail {{email}} correspond à un compte dans notre système, un lien de réinitialisation de mot de passe sera envoyé à {{email}}." + 'PASSWORD' => [ + '@TRANSLATION' => 'Mot de passe', + + 'BETWEEN' => 'Entre {{min}} et {{max}} charactères', + + 'CONFIRM' => 'Confirmer le mot de passe', + 'CONFIRM_CURRENT' => 'Veuillez confirmer votre mot de passe actuel', + 'CONFIRM_NEW' => 'Confirmer le nouveau mot de passe', + 'CONFIRM_NEW_EXPLAIN' => 'Confirmer le mot de passe', + 'CONFIRM_NEW_HELP' => 'Obligatoire uniquement si vous sélectionnez un nouveau mot de passe', + 'CURRENT' => 'Mot de passe actuel', + 'CURRENT_EXPLAIN' => 'Vous devez confirmer votre mot de passe actuel pour apporter des modifications', + + 'FORGOTTEN' => 'Mot de passe oublié', + 'FORGET' => [ + '@TRANSLATION' => "J'ai oublié mon mot de passe", + + 'COULD_NOT_UPDATE' => 'Impossible de mettre à jour le mot de passe.', + 'EMAIL' => "Veuillez saisir l'adresse e-mail que vous avez utilisée pour vous inscrire. Un lien avec les instructions pour réinitialiser votre mot de passe vous sera envoyé par email.", + 'EMAIL_SEND' => 'Envoyer le lien de réinitialisation', + 'INVALID' => "Cette requête de réinitialisation de mot de passe n'a pas pu être trouvée ou a expiré. Veuillez réessayer de soumettre votre demande .", + 'PAGE' => 'Obtenir un lien pour réinitialiser votre mot de passe.', + 'REQUEST_CANNED' => 'Demande de mot de passe perdu annulée.', + 'REQUEST_SENT' => "Si l'adresse e-mail {{email}} correspond à un compte dans notre système, un lien de réinitialisation de mot de passe sera envoyé à {{email}}." ], - "RESET" => [ - "@TRANSLATION" => "Réinitialiser le mot de passe", - "CHOOSE" => "Veuillez choisir un nouveau mot de passe pour continuer.", - "PAGE" => "Choisissez un nouveau mot de passe pour votre compte.", - "SEND" => "Définir un nouveau mot de passe" + 'RESET' => [ + '@TRANSLATION' => 'Réinitialiser le mot de passe', + 'CHOOSE' => 'Veuillez choisir un nouveau mot de passe pour continuer.', + 'PAGE' => 'Choisissez un nouveau mot de passe pour votre compte.', + 'SEND' => 'Définir un nouveau mot de passe' ], - "HASH_FAILED" => "Le hachage du mot de passe a échoué. Veuillez contacter un administrateur de site.", - "INVALID" => "Le mot de passe actuel ne correspond pas à celui que nous avons au dossier", - "NEW" => "Nouveau mot de passe", - "NOTHING_TO_UPDATE" => "Vous ne pouvez pas mettre à jour avec le même mot de passe", - "UPDATED" => "Mot de passe du compte mis à jour" + 'HASH_FAILED' => 'Le hachage du mot de passe a échoué. Veuillez contacter un administrateur de site.', + 'INVALID' => 'Le mot de passe actuel ne correspond pas à celui que nous avons au dossier', + 'NEW' => 'Nouveau mot de passe', + 'NOTHING_TO_UPDATE' => 'Vous ne pouvez pas mettre à jour avec le même mot de passe', + 'UPDATED' => 'Mot de passe du compte mis à jour' ], - "PROFILE" => [ - "SETTINGS" => "Paramètres du profil", - "UPDATED" => "Paramètres du profil mis à jour" + 'PROFILE' => [ + 'SETTINGS' => 'Paramètres du profil', + 'UPDATED' => 'Paramètres du profil mis à jour' ], - "REGISTER" => "S'inscrire", - "REGISTER_ME" => "S'inscrire", + 'REGISTER' => "S'inscrire", + 'REGISTER_ME' => "S'inscrire", - "REGISTRATION" => [ - "BROKEN" => "Nous sommes désolés, il ya un problème avec notre processus d'enregistrement de compte. Veuillez nous contacter directement pour obtenir de l'aide.", - "COMPLETE_TYPE1" => "Vous êtes inscrit avec succès. Vous pouvez maintenant vous connecter.", - "COMPLETE_TYPE2" => "Vous êtes inscrit avec succès. Vous recevrez bientôt un e-mail de validation contenant un lien pour activer votre compte. Vous ne pourrez pas vous connecter avant d'avoir terminé cette étape.", - "DISABLED" => "Désolé, l'enregistrement de compte a été désactivé.", - "LOGOUT" => "Désolé, vous ne pouvez pas vous inscrire tout en étant connecté. Veuillez vous déconnecter en premier.", - "WELCOME" => "L'inscription est rapide et simple." + 'REGISTRATION' => [ + 'BROKEN' => "Nous sommes désolés, il ya un problème avec notre processus d'enregistrement de compte. Veuillez nous contacter directement pour obtenir de l'aide.", + 'COMPLETE_TYPE1' => 'Vous êtes inscrit avec succès. Vous pouvez maintenant vous connecter.', + 'COMPLETE_TYPE2' => "Vous êtes inscrit avec succès. Vous recevrez bientôt un e-mail de validation contenant un lien pour activer votre compte. Vous ne pourrez pas vous connecter avant d'avoir terminé cette étape.", + 'DISABLED' => "Désolé, l'enregistrement de compte a été désactivé.", + 'LOGOUT' => 'Désolé, vous ne pouvez pas vous inscrire tout en étant connecté. Veuillez vous déconnecter en premier.', + 'WELCOME' => "L'inscription est rapide et simple." ], - "RATE_LIMIT_EXCEEDED" => "La limite de tentatives pour cette action a été dépassée. Vous devez attendre {{delay}} secondes avant de pouvoir effectuer une autre tentative.", - "REMEMBER_ME" => "Se souvenir de moi!", - "REMEMBER_ME_ON_COMPUTER" => "Se souvenir de moi sur cet ordinateur (non recommandé pour les ordinateurs publics)", + 'RATE_LIMIT_EXCEEDED' => 'La limite de tentatives pour cette action a été dépassée. Vous devez attendre {{delay}} secondes avant de pouvoir effectuer une autre tentative.', + 'REMEMBER_ME' => 'Se souvenir de moi!', + 'REMEMBER_ME_ON_COMPUTER' => 'Se souvenir de moi sur cet ordinateur (non recommandé pour les ordinateurs publics)', - "SIGNIN" => "Se connecter", - "SIGNIN_OR_REGISTER" => "Se connecter ou s'inscrire", - "SIGNUP" => "S'inscrire", + 'SIGNIN' => 'Se connecter', + 'SIGNIN_OR_REGISTER' => "Se connecter ou s'inscrire", + 'SIGNUP' => "S'inscrire", - "TOS" => "Termes et conditions", - "TOS_AGREEMENT" => "En créant un compte avec {{site_title}}, vous acceptez les termes et conditions.", - "TOS_FOR" => "Termes et conditions pour {{title}}", + 'TOS' => 'Termes et conditions', + 'TOS_AGREEMENT' => 'En créant un compte avec {{site_title}}, vous acceptez les termes et conditions.', + 'TOS_FOR' => 'Termes et conditions pour {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "Nom d'utilisateur", + 'USERNAME' => [ + '@TRANSLATION' => "Nom d'utilisateur", - "CHOOSE" => "Choisissez un nom d'utilisateur unique", - "INVALID" => "Nom d'utilisateur invalide", - "IN_USE" => "Le nom d'utilisateur '{{username}}' est déjà utilisé.", - "NOT_AVAILABLE" => "Le nom d'utilisateur {{user_name}} n'est pas disponible. Choisissez un autre nom, ou cliquez sur « suggérer »." + 'CHOOSE' => "Choisissez un nom d'utilisateur unique", + 'INVALID' => "Nom d'utilisateur invalide", + 'IN_USE' => "Le nom d'utilisateur '{{username}}' est déjà utilisé.", + 'NOT_AVAILABLE' => "Le nom d'utilisateur {{user_name}} n'est pas disponible. Choisissez un autre nom, ou cliquez sur « suggérer »." ], - "USER_ID_INVALID" => "L'identifiant d'utilisateur demandé n'existe pas.", - "USER_OR_EMAIL_INVALID" => "Nom d'utilisateur ou adresse e-mail non valide.", - "USER_OR_PASS_INVALID" => "Nom d'utilisateur ou mot de passe incorrect.", + 'USER_ID_INVALID' => "L'identifiant d'utilisateur demandé n'existe pas.", + 'USER_OR_EMAIL_INVALID' => "Nom d'utilisateur ou adresse e-mail non valide.", + 'USER_OR_PASS_INVALID' => "Nom d'utilisateur ou mot de passe incorrect.", - "WELCOME" => "Bienvenue {{first_name}}" + 'WELCOME' => 'Bienvenue {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/fr_FR/validate.php b/app/sprinkles/account/locale/fr_FR/validate.php index 2d4d65fae..116c8c65b 100644 --- a/app/sprinkles/account/locale/fr_FR/validate.php +++ b/app/sprinkles/account/locale/fr_FR/validate.php @@ -4,15 +4,15 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * French message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\fr * @author Louis Charette */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Votre mot de passe et votre mot de passe de confirmation doivent correspondre." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'Votre mot de passe et votre mot de passe de confirmation doivent correspondre.' ] ]; diff --git a/app/sprinkles/account/locale/it_IT/messages.php b/app/sprinkles/account/locale/it_IT/messages.php index 455a302cc..6aceaf28c 100644 --- a/app/sprinkles/account/locale/it_IT/messages.php +++ b/app/sprinkles/account/locale/it_IT/messages.php @@ -4,183 +4,182 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Italian message token translations for the 'account' sprinkle. * This translation was generated with Google translate. Please contribute if you are a native speaker. * - * @package userfrosting\i18n\it * @author Alexander Weissman * @author Pietro Marangon (@Pe46dro) */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Account", + 'ACCOUNT' => [ + '@TRANSLATION' => 'Account', - "ACCESS_DENIED" => "Sembra tu non abbia il permesso per effettuare questa azione.", + 'ACCESS_DENIED' => 'Sembra tu non abbia il permesso per effettuare questa azione.', - "DISABLED" => "Questo account è stato disattivato, contattaci per maggiori informazioni", + 'DISABLED' => 'Questo account è stato disattivato, contattaci per maggiori informazioni', - "EMAIL_UPDATED" => "Email aggiornata", + 'EMAIL_UPDATED' => 'Email aggiornata', - "INVALID" => "Questo account non esiste. Può essere stato eliminato. Contattaci per ulteriori informazioni.", + 'INVALID' => 'Questo account non esiste. Può essere stato eliminato. Contattaci per ulteriori informazioni.', - "MASTER_NOT_EXISTS" => "Non puoi registrare un account finché l'account primario non sarà creato!", - "MY" => "Il mio account", + 'MASTER_NOT_EXISTS' => "Non puoi registrare un account finché l'account primario non sarà creato!", + 'MY' => 'Il mio account', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "La tua sessione è stata compromessa. Devi eseguire il logout su tutti i dispositivi, quindi accedere nuovamente e assicurarti che i tuoi dati non siano stati manomessi.", - "TITLE" => "Il tuo account potrebbe essere stato compromesso", - "TEXT" => "Qualcuno potrebbe aver utilizzato le tue informazioni di accesso per accedere a questa pagina. Per la tua sicurezza tutte le sessioni sono state disconnesse. Accedi e controlla l'account per attività sospette. Potresti anche voler cambiare la password." + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => 'La tua sessione è stata compromessa. Devi eseguire il logout su tutti i dispositivi, quindi accedere nuovamente e assicurarti che i tuoi dati non siano stati manomessi.', + 'TITLE' => 'Il tuo account potrebbe essere stato compromesso', + 'TEXT' => "Qualcuno potrebbe aver utilizzato le tue informazioni di accesso per accedere a questa pagina. Per la tua sicurezza tutte le sessioni sono state disconnesse. Accedi e controlla l'account per attività sospette. Potresti anche voler cambiare la password." ], - "SESSION_EXPIRED" => "La tua sessione è scaduta. Accedi nuovamente.", + 'SESSION_EXPIRED' => 'La tua sessione è scaduta. Accedi nuovamente.', - "SETTINGS" => [ - "@TRANSLATION" => "Impostazioni account", - "DESCRIPTION" => "Aggiorna le impostazioni del tuo account, tra cui email, nome e password.", - "UPDATED" => "Impostazioni account aggiornate" + 'SETTINGS' => [ + '@TRANSLATION' => 'Impostazioni account', + 'DESCRIPTION' => 'Aggiorna le impostazioni del tuo account, tra cui email, nome e password.', + 'UPDATED' => 'Impostazioni account aggiornate' ], - "TOOLS" => "Strumenti account", + 'TOOLS' => 'Strumenti account', - "UNVERIFIED" => "Il tuo account non è stato attivato. Controlla nella tua mail (anche nella cartella dello spam) per ricevere le instruzioni per attivare il tuo account", + 'UNVERIFIED' => 'Il tuo account non è stato attivato. Controlla nella tua mail (anche nella cartella dello spam) per ricevere le instruzioni per attivare il tuo account', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Ti è stato inviato un nuovo codice di attivazione, controlla la tua email ({{email}}).", - "RESEND" => "Invia nuovamente email di verifica.", - "COMPLETE" => "Hai verificato con successo il tuo account. Puoi ora accedere.", - "EMAIL" => "Inserisci l'indirizzo email che hai utilizzato per registrarti e la tua email di verifica sarà inviata nuovamente.", - "PAGE" => "Invia nuovamente l'email di verifica per il tuo nuovo account.", - "SEND" => "Invia il collegamento di verifica per il mio account", - "TOKEN_NOT_FOUND" => "Il token non esiste / l'account è già stato attivato" + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'Ti è stato inviato un nuovo codice di attivazione, controlla la tua email ({{email}}).', + 'RESEND' => 'Invia nuovamente email di verifica.', + 'COMPLETE' => 'Hai verificato con successo il tuo account. Puoi ora accedere.', + 'EMAIL' => "Inserisci l'indirizzo email che hai utilizzato per registrarti e la tua email di verifica sarà inviata nuovamente.", + 'PAGE' => "Invia nuovamente l'email di verifica per il tuo nuovo account.", + 'SEND' => 'Invia il collegamento di verifica per il mio account', + 'TOKEN_NOT_FOUND' => "Il token non esiste / l'account è già stato attivato" ] ], - "EMAIL" => [ - "INVALID" => "Non esiste alcun account per {{email}}.", - "IN_USE" => "L'email '{{email}}' è già in uso", - "VERIFICATION_REQUIRED" => "Email (verifica richiesta - utilizza un indirizzo reale!)" + 'EMAIL' => [ + 'INVALID' => 'Non esiste alcun account per {{email}}.', + 'IN_USE' => "L'email '{{email}}' è già in uso", + 'VERIFICATION_REQUIRED' => 'Email (verifica richiesta - utilizza un indirizzo reale!)' ], - "EMAIL_OR_USERNAME" => "Nome utente o Indirizzo Email", + 'EMAIL_OR_USERNAME' => 'Nome utente o Indirizzo Email', + + 'FIRST_NAME' => 'Nome', - "FIRST_NAME" => "Nome", + 'HEADER_MESSAGE_ROOT' => 'ACCESSO ROOT', - "HEADER_MESSAGE_ROOT" => "ACCESSO ROOT", + 'LAST_NAME' => 'Cognome', + 'LOCALE' => [ + 'ACCOUNT' => 'La lingua da utilizzare per il tuo account', + 'INVALID' => '{{locale}} non è una lingua valida.', - "LAST_NAME" => "Cognome", - "LOCALE" => [ - "ACCOUNT" => "La lingua da utilizzare per il tuo account", - "INVALID" => "{{locale}} non è una lingua valida.", - - ], - "LOGIN" => [ - "@TRANSLATION" => "Accesso", - "ALREADY_COMPLETE" => "Hai già eseguito l'accesso!", - "SOCIAL" => "O accedi con", - "REQUIRED" => "Devi eseguire l'accesso per accedere a questa risorsa" + 'LOGIN' => [ + '@TRANSLATION' => 'Accesso', + 'ALREADY_COMPLETE' => "Hai già eseguito l'accesso!", + 'SOCIAL' => 'O accedi con', + 'REQUIRED' => "Devi eseguire l'accesso per accedere a questa risorsa" ], - "LOGOUT" => "Esci", + 'LOGOUT' => 'Esci', - "NAME" => "Nome", + 'NAME' => 'Nome', - "NAME_AND_EMAIL" => "Nome e email", + 'NAME_AND_EMAIL' => 'Nome e email', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Accedi al tuo account {{site_name}} o iscriviti per un nuovo account.", - "SUBTITLE" => "Registrati gratuitamente o accedi con un account esistente.", - "TITLE" => "Iniziamo!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'Accedi al tuo account {{site_name}} o iscriviti per un nuovo account.', + 'SUBTITLE' => 'Registrati gratuitamente o accedi con un account esistente.', + 'TITLE' => 'Iniziamo!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "Password", + 'PASSWORD' => [ + '@TRANSLATION' => 'Password', - "BETWEEN" => "La password deve essere tra {{min}} e i {{max}} caratteri", + 'BETWEEN' => 'La password deve essere tra {{min}} e i {{max}} caratteri', - "CONFIRM" => "Conferma la password", - "CONFIRM_CURRENT" => "Conferma la password attuale", - "CONFIRM_NEW" => "Conferma la tua nuova password", - "CONFIRM_NEW_EXPLAIN" => "Inserisci nuovamente la nuova password", - "CONFIRM_NEW_HELP" => "Richiesto solo se si seleziona una nuova password", - "CREATE" => [ - "@TRANSLATION" => "Crea password", - "PAGE" => "Scegli una password per il tuo nuovo account.", - "SET" => "Imposta password e accedi" + 'CONFIRM' => 'Conferma la password', + 'CONFIRM_CURRENT' => 'Conferma la password attuale', + 'CONFIRM_NEW' => 'Conferma la tua nuova password', + 'CONFIRM_NEW_EXPLAIN' => 'Inserisci nuovamente la nuova password', + 'CONFIRM_NEW_HELP' => 'Richiesto solo se si seleziona una nuova password', + 'CREATE' => [ + '@TRANSLATION' => 'Crea password', + 'PAGE' => 'Scegli una password per il tuo nuovo account.', + 'SET' => 'Imposta password e accedi' ], - "CURRENT" => "Password attuale", - "CURRENT_EXPLAIN" => "Devi confermare la tua password corrente per apportare modifiche", - - "FORGOTTEN" => "Password dimenticata", - "FORGET" => [ - "@TRANSLATION" => "Ho dimenticato la mia password", - - "COULD_NOT_UPDATE" => "Password non aggiornata", - "EMAIL" => "Inserisci l'indirizzo email che hai utilizzato per iscriverti. Un link con le istruzioni per reimpostare la tua password verrà inviata via email.", - "EMAIL_SEND" => "Invia email per il reset della password", - "INVALID" => "Questa richiesta di ripristino della password non è stata trovata o è scaduta. Prova a reinviare la tua richiesta.", - "PAGE" => "Ottieni un collegamento per reimpostare la tua password.", - "REQUEST_CANNED" => "Richiesta di recupero password annullata.", - "REQUEST_SENT" => "Se l'email {{email}} corrisponde a un account, verrà inviato un collegamento per la reimpostazione della password a {{email}}." + 'CURRENT' => 'Password attuale', + 'CURRENT_EXPLAIN' => 'Devi confermare la tua password corrente per apportare modifiche', + + 'FORGOTTEN' => 'Password dimenticata', + 'FORGET' => [ + '@TRANSLATION' => 'Ho dimenticato la mia password', + + 'COULD_NOT_UPDATE' => 'Password non aggiornata', + 'EMAIL' => "Inserisci l'indirizzo email che hai utilizzato per iscriverti. Un link con le istruzioni per reimpostare la tua password verrà inviata via email.", + 'EMAIL_SEND' => 'Invia email per il reset della password', + 'INVALID' => 'Questa richiesta di ripristino della password non è stata trovata o è scaduta. Prova a reinviare la tua richiesta.', + 'PAGE' => 'Ottieni un collegamento per reimpostare la tua password.', + 'REQUEST_CANNED' => 'Richiesta di recupero password annullata.', + 'REQUEST_SENT' => "Se l'email {{email}} corrisponde a un account, verrà inviato un collegamento per la reimpostazione della password a {{email}}." ], - "HASH_FAILED" => "Hash della password fallito. Contatta l'amministratore di sistema.", - "INVALID" => "La password corrente non corrisponde con quella attuale", - "NEW" => "Nuova Password", - "NOTHING_TO_UPDATE" => "Non puoi impostare la stessa password precedente", + 'HASH_FAILED' => "Hash della password fallito. Contatta l'amministratore di sistema.", + 'INVALID' => 'La password corrente non corrisponde con quella attuale', + 'NEW' => 'Nuova Password', + 'NOTHING_TO_UPDATE' => 'Non puoi impostare la stessa password precedente', - "RESET" => [ - "@TRANSLATION" => "Reimposta la Password", - "CHOOSE" => "Inserisci la tua nuova password", - "PAGE" => "Scegli una nuova password per il tuo account.", - "SEND" => "Imposta nuova password e accedi" + 'RESET' => [ + '@TRANSLATION' => 'Reimposta la Password', + 'CHOOSE' => 'Inserisci la tua nuova password', + 'PAGE' => 'Scegli una nuova password per il tuo account.', + 'SEND' => 'Imposta nuova password e accedi' ], - "UPDATED" => "Password aggiornata" + 'UPDATED' => 'Password aggiornata' ], - "PROFILE" => [ - "SETTINGS" => "Impostazioni profilo", - "UPDATED" => "Impostazioni profilo aggiornate" + 'PROFILE' => [ + 'SETTINGS' => 'Impostazioni profilo', + 'UPDATED' => 'Impostazioni profilo aggiornate' ], - "RATE_LIMIT_EXCEEDED" => "Il limite di esecuzioni per questa azione è stato superato. Devi aspettare altri {{delay}} secondi prima che tu possa fare un altro tentativo.", - "REGISTER" => "Registrati", - "REGISTER_ME" => "Iscrivimi", - "REGISTRATION" => [ - "BROKEN" => "Siamo spiacenti, c'è un problema con il nostro processo di registrazione dell'account. Vi preghiamo di contattarci direttamente per assistenza.", - "COMPLETE_TYPE1" => "Registrazione effettuata con successo. Ora puoi eseguire il login", - "COMPLETE_TYPE2" => "Registrazione effettuata con successo. Riceverai presto una mail a {{email}} per l'attivazione. Devi attivare il tuo account prima di eseguire il login.", - "DISABLED" => "La registrazione di nuovi account è limitata", - "LOGOUT" => "Non è possibile registrare un account mentre hai eseguito l'accesso ad un altro account", - "WELCOME" => "La registrazione è semplice e veloce" + 'RATE_LIMIT_EXCEEDED' => 'Il limite di esecuzioni per questa azione è stato superato. Devi aspettare altri {{delay}} secondi prima che tu possa fare un altro tentativo.', + 'REGISTER' => 'Registrati', + 'REGISTER_ME' => 'Iscrivimi', + 'REGISTRATION' => [ + 'BROKEN' => "Siamo spiacenti, c'è un problema con il nostro processo di registrazione dell'account. Vi preghiamo di contattarci direttamente per assistenza.", + 'COMPLETE_TYPE1' => 'Registrazione effettuata con successo. Ora puoi eseguire il login', + 'COMPLETE_TYPE2' => "Registrazione effettuata con successo. Riceverai presto una mail a {{email}} per l'attivazione. Devi attivare il tuo account prima di eseguire il login.", + 'DISABLED' => 'La registrazione di nuovi account è limitata', + 'LOGOUT' => "Non è possibile registrare un account mentre hai eseguito l'accesso ad un altro account", + 'WELCOME' => 'La registrazione è semplice e veloce' ], - "REMEMBER_ME" => "Ricordami", - "REMEMBER_ME_ON_COMPUTER" => "Ricordami su questo dispositivo (non consigliato per i computer pubblici)", + 'REMEMBER_ME' => 'Ricordami', + 'REMEMBER_ME_ON_COMPUTER' => 'Ricordami su questo dispositivo (non consigliato per i computer pubblici)', - "SIGN_IN_HERE" => "Hai già un account? Accedi qui", - "SIGNIN" => "Accedi", - "SIGNIN_OR_REGISTER" => "Accedi o iscriviti", - "SIGNUP" => "Registrazione", + 'SIGN_IN_HERE' => 'Hai già un account? Accedi qui', + 'SIGNIN' => 'Accedi', + 'SIGNIN_OR_REGISTER' => 'Accedi o iscriviti', + 'SIGNUP' => 'Registrazione', - "TOS" => "Termini e condizioni", - "TOS_AGREEMENT" => "Registrando un account su {{site_title}}, accetti i Termini e le Condizioni.", - "TOS_FOR" => "Termini e condizioni di {{title}}", + 'TOS' => 'Termini e condizioni', + 'TOS_AGREEMENT' => 'Registrando un account su {{site_title}}, accetti i Termini e le Condizioni.', + 'TOS_FOR' => 'Termini e condizioni di {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "Nome utente", + 'USERNAME' => [ + '@TRANSLATION' => 'Nome utente', - "CHOOSE" => "Inserisci il tuo nome utente", - "INVALID" => "Nome utente non valido", - "IN_USE" => "Il nome utente '{{user_name}}' è già in uso", - "NOT_AVAILABLE" => "Il nome utente {{user_name}} non è disponibile. Scegli un nome diverso, oppure fai clic su \"suggerisci\"." + 'CHOOSE' => 'Inserisci il tuo nome utente', + 'INVALID' => 'Nome utente non valido', + 'IN_USE' => "Il nome utente '{{user_name}}' è già in uso", + 'NOT_AVAILABLE' => 'Il nome utente {{user_name}} non è disponibile. Scegli un nome diverso, oppure fai clic su "suggerisci".' ], - "USER_ID_INVALID" => "Questo ID utente non esiste", - "USER_OR_EMAIL_INVALID" => "L'indirizzo mail o il nome utente non sono validi", - "USER_OR_PASS_INVALID" => "Il nome utente o la password non sono validi", + 'USER_ID_INVALID' => 'Questo ID utente non esiste', + 'USER_OR_EMAIL_INVALID' => "L'indirizzo mail o il nome utente non sono validi", + 'USER_OR_PASS_INVALID' => 'Il nome utente o la password non sono validi', - "WELCOME" => "Bentornato, {{display_name}}" + 'WELCOME' => 'Bentornato, {{display_name}}' ]; diff --git a/app/sprinkles/account/locale/it_IT/validate.php b/app/sprinkles/account/locale/it_IT/validate.php index 46f7e6d66..009cd2df2 100644 --- a/app/sprinkles/account/locale/it_IT/validate.php +++ b/app/sprinkles/account/locale/it_IT/validate.php @@ -4,18 +4,18 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Italian message token translations for the 'account' sprinkle. * This translation was generated with Google translate. Please contribute if you are a native speaker. * - * @package userfrosting\i18n\it * @author Alexander Weissman * @author Pietro Marangon (@Pe46dro) */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "I due campi devono combaciare", - "USERNAME" => "Il nome utente può essere composto solo da caratteri alfanumerici, '.', '-', e '_'." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'I due campi devono combaciare', + 'USERNAME' => "Il nome utente può essere composto solo da caratteri alfanumerici, '.', '-', e '_'." ] ]; diff --git a/app/sprinkles/account/locale/pt_PT/messages.php b/app/sprinkles/account/locale/pt_PT/messages.php index 3db4200b4..01fad9fa9 100644 --- a/app/sprinkles/account/locale/pt_PT/messages.php +++ b/app/sprinkles/account/locale/pt_PT/messages.php @@ -4,163 +4,163 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Portuguese message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\pt * @author Bruno Silva (brunomnsilva@gmail.com) */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Conta", + 'ACCOUNT' => [ + '@TRANSLATION' => 'Conta', - "ACCESS_DENIED" => "Hmm, parece que não tem permissões para fazer isso.", + 'ACCESS_DENIED' => 'Hmm, parece que não tem permissões para fazer isso.', - "DISABLED" => "Esta conta foi desativada. Por favor contacte-nos para mais informações.", + 'DISABLED' => 'Esta conta foi desativada. Por favor contacte-nos para mais informações.', - "EMAIL_UPDATED" => "Email da conta atualizado", + 'EMAIL_UPDATED' => 'Email da conta atualizado', - "INVALID" => "Esta conta não existe. Pode ter sido removida. Por favor contacte-nos para mais informações.", + 'INVALID' => 'Esta conta não existe. Pode ter sido removida. Por favor contacte-nos para mais informações.', - "MASTER_NOT_EXISTS" => "Não pode registrar uma conta enquanto a conta principal não for criada!", - "MY" => "A minha conta", + 'MASTER_NOT_EXISTS' => 'Não pode registrar uma conta enquanto a conta principal não for criada!', + 'MY' => 'A minha conta', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "A sua sessão foi comprometida. Deverá fechar todas as sessões, voltar a iniciar sessão e verificar que os seus dados não foram alterados por alheios.", - "TITLE" => "A sua sessão pode ter sido comprometida" + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => 'A sua sessão foi comprometida. Deverá fechar todas as sessões, voltar a iniciar sessão e verificar que os seus dados não foram alterados por alheios.', + 'TITLE' => 'A sua sessão pode ter sido comprometida' ], - "SESSION_EXPIRED" => "A sua sessão expirou. Por favor inicie nova sessão.", + 'SESSION_EXPIRED' => 'A sua sessão expirou. Por favor inicie nova sessão.', - "SETTINGS" => [ - "@TRANSLATION" => "Definições de conta", - "DESCRIPTION" => "Atualize as suas definições, incluindo email, nome e password.", - "UPDATED" => "Definições de conta atualizadas" + 'SETTINGS' => [ + '@TRANSLATION' => 'Definições de conta', + 'DESCRIPTION' => 'Atualize as suas definições, incluindo email, nome e password.', + 'UPDATED' => 'Definições de conta atualizadas' ], - "TOOLS" => "Ferramentas de conta", + 'TOOLS' => 'Ferramentas de conta', - "UNVERIFIED" => "A sua conta ainda não foi verificada. Consulte o seu email (incluindo a pasta de spam) para instruções de ativação.", + 'UNVERIFIED' => 'A sua conta ainda não foi verificada. Consulte o seu email (incluindo a pasta de spam) para instruções de ativação.', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Enviámos um link de verificação para o endereço {{email}}. Por favor consulte o seu email (incluindo a pasta de spam).", - "RESEND" => "Enviar novamente email de verificação", - "COMPLETE" => "Verificou com sucesso a sua conta. Pode iniciar sessão.", - "EMAIL" => "Por favor introduza o endereço de email que utilizou no registro e um email de verificação será enviado.", - "PAGE" => "Reenviar email de verificação para a sua nova conta.", - "SEND" => "Enviar email com link de verificação", - "TOKEN_NOT_FOUND" => "Token de verificação inexistente / Conta já verificada", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'Enviámos um link de verificação para o endereço {{email}}. Por favor consulte o seu email (incluindo a pasta de spam).', + 'RESEND' => 'Enviar novamente email de verificação', + 'COMPLETE' => 'Verificou com sucesso a sua conta. Pode iniciar sessão.', + 'EMAIL' => 'Por favor introduza o endereço de email que utilizou no registro e um email de verificação será enviado.', + 'PAGE' => 'Reenviar email de verificação para a sua nova conta.', + 'SEND' => 'Enviar email com link de verificação', + 'TOKEN_NOT_FOUND' => 'Token de verificação inexistente / Conta já verificada', ] ], - "EMAIL" => [ - "INVALID" => "Não existe nenhuma conta para {{email}}.", - "IN_USE" => "O email {{email}} já se encontra em uso." + 'EMAIL' => [ + 'INVALID' => 'Não existe nenhuma conta para {{email}}.', + 'IN_USE' => 'O email {{email}} já se encontra em uso.' ], - "FIRST_NAME" => "Primeiro nome", + 'FIRST_NAME' => 'Primeiro nome', - "HEADER_MESSAGE_ROOT" => "INICIOU SESSÃO COM A CONTA ROOT", + 'HEADER_MESSAGE_ROOT' => 'INICIOU SESSÃO COM A CONTA ROOT', - "LAST_NAME" => "Último nome", + 'LAST_NAME' => 'Último nome', - "LOCALE.ACCOUNT" => "Linguagem e localização a utilizar na sua conta", + 'LOCALE.ACCOUNT' => 'Linguagem e localização a utilizar na sua conta', - "LOGIN" => [ - "@TRANSLATION" => "Entrar", + 'LOGIN' => [ + '@TRANSLATION' => 'Entrar', - "ALREADY_COMPLETE" => "Sessão já iniciada!", - "SOCIAL" => "Ou inicie sessão com", - "REQUIRED" => "Lamentamos, tem de iniciar sessão para aceder a este recurso." + 'ALREADY_COMPLETE' => 'Sessão já iniciada!', + 'SOCIAL' => 'Ou inicie sessão com', + 'REQUIRED' => 'Lamentamos, tem de iniciar sessão para aceder a este recurso.' ], - "LOGOUT" => "Sair", + 'LOGOUT' => 'Sair', - "NAME" => "Nome", + 'NAME' => 'Nome', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Inicie sessão na sua conta {{site_name}}, ou registre-se para uma nova conta.", - "SUBTITLE" => "Registre-se gratuitamente, ou inicie sessão com uma conta existente.", - "TITLE" => "Vamos começar!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'Inicie sessão na sua conta {{site_name}}, ou registre-se para uma nova conta.', + 'SUBTITLE' => 'Registre-se gratuitamente, ou inicie sessão com uma conta existente.', + 'TITLE' => 'Vamos começar!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "Password", - - "BETWEEN" => "Entre {{min}}-{{max}} carateres", - - "CONFIRM" => "Confirme a password", - "CONFIRM_CURRENT" => "Por favor confirme a sua password atual", - "CONFIRM_NEW" => "Confirmar Nova Password", - "CONFIRM_NEW_EXPLAIN" => "Re-introduza a sua nova password", - "CONFIRM_NEW_HELP" => "Apenas necessário se escolher uma nova password", - "CURRENT" => "Password Atual", - "CURRENT_EXPLAIN" => "Tem de confirmar a sua password atual para efetuar alterações", - - "FORGOTTEN" => "Password Esquecida", - "FORGET" => [ - "@TRANSLATION" => "Esqueci a minha password", - - "COULD_NOT_UPDATE" => "Não foi possível atualizar a password.", - "EMAIL" => "Por favor introduza o endereço de email que utilizou no registro. Enviaremos um email com instruções para efetuar o reset à sua password.", - "EMAIL_SEND" => "Enviar email com link de reset da password", - "INVALID" => "This password reset request could not be found, or has expired. Please try resubmitting your request.", - "PAGE" => "Obtenha um link para fazer reset à sua password.", - "REQUEST_CANNED" => "Pedido de password esquecida foi cancelado.", - "REQUEST_SENT" => "Se o email {{email}} corresponder a uma conta em nosso sistema, um link de redefinição de senha será enviado para {{email}}." + 'PASSWORD' => [ + '@TRANSLATION' => 'Password', + + 'BETWEEN' => 'Entre {{min}}-{{max}} carateres', + + 'CONFIRM' => 'Confirme a password', + 'CONFIRM_CURRENT' => 'Por favor confirme a sua password atual', + 'CONFIRM_NEW' => 'Confirmar Nova Password', + 'CONFIRM_NEW_EXPLAIN' => 'Re-introduza a sua nova password', + 'CONFIRM_NEW_HELP' => 'Apenas necessário se escolher uma nova password', + 'CURRENT' => 'Password Atual', + 'CURRENT_EXPLAIN' => 'Tem de confirmar a sua password atual para efetuar alterações', + + 'FORGOTTEN' => 'Password Esquecida', + 'FORGET' => [ + '@TRANSLATION' => 'Esqueci a minha password', + + 'COULD_NOT_UPDATE' => 'Não foi possível atualizar a password.', + 'EMAIL' => 'Por favor introduza o endereço de email que utilizou no registro. Enviaremos um email com instruções para efetuar o reset à sua password.', + 'EMAIL_SEND' => 'Enviar email com link de reset da password', + 'INVALID' => 'This password reset request could not be found, or has expired. Please try resubmitting your request.', + 'PAGE' => 'Obtenha um link para fazer reset à sua password.', + 'REQUEST_CANNED' => 'Pedido de password esquecida foi cancelado.', + 'REQUEST_SENT' => 'Se o email {{email}} corresponder a uma conta em nosso sistema, um link de redefinição de senha será enviado para {{email}}.' ], - "RESET" => [ - "@TRANSLATION" => "Reset Password", - "CHOOSE" => "Por favor escolha uma nova password para continuar.", - "PAGE" => "Escolha uma nova password para a sua conta.", - "SEND" => "Definir nova password e registrar" + 'RESET' => [ + '@TRANSLATION' => 'Reset Password', + 'CHOOSE' => 'Por favor escolha uma nova password para continuar.', + 'PAGE' => 'Escolha uma nova password para a sua conta.', + 'SEND' => 'Definir nova password e registrar' ], - "HASH_FAILED" => "Falhou o hashing da password. Por favor contacte um administrador do site.", - "INVALID" => "A password atual não coincide com a que temos em sistema", - "NEW" => "Nova Password", - "NOTHING_TO_UPDATE" => "Não pode atualizar para a mesma password", - "UPDATED" => "Password da conta foi atualizada" + 'HASH_FAILED' => 'Falhou o hashing da password. Por favor contacte um administrador do site.', + 'INVALID' => 'A password atual não coincide com a que temos em sistema', + 'NEW' => 'Nova Password', + 'NOTHING_TO_UPDATE' => 'Não pode atualizar para a mesma password', + 'UPDATED' => 'Password da conta foi atualizada' ], - "REGISTER" => "Registrar", - "REGISTER_ME" => "Registrar-me", + 'REGISTER' => 'Registrar', + 'REGISTER_ME' => 'Registrar-me', - "REGISTRATION" => [ - "BROKEN" => "Lamentamos, existe um problema com o nosso processo de registro. Contacte-nos diretamente para assistência.", - "COMPLETE_TYPE1" => "Registrou-se com sucesso. Pode iniciar sessão.", - "COMPLETE_TYPE2" => "Registrou-se com sucesso. Receberá em breve um email de verificação contendo um link para verificar a sua conta. Não será possível iniciar sessão até completar este passo.", - "DISABLED" => "Lamentamos, o registro de novas contas foi desativado.", - "LOGOUT" => "Não pode registrar uma nova conta enquanto tiver sessão iniciada. Por favor feche a sua sessão primeiro.", - "WELCOME" => "O registro é rápido e simples." + 'REGISTRATION' => [ + 'BROKEN' => 'Lamentamos, existe um problema com o nosso processo de registro. Contacte-nos diretamente para assistência.', + 'COMPLETE_TYPE1' => 'Registrou-se com sucesso. Pode iniciar sessão.', + 'COMPLETE_TYPE2' => 'Registrou-se com sucesso. Receberá em breve um email de verificação contendo um link para verificar a sua conta. Não será possível iniciar sessão até completar este passo.', + 'DISABLED' => 'Lamentamos, o registro de novas contas foi desativado.', + 'LOGOUT' => 'Não pode registrar uma nova conta enquanto tiver sessão iniciada. Por favor feche a sua sessão primeiro.', + 'WELCOME' => 'O registro é rápido e simples.' ], - "RATE_LIMIT_EXCEEDED" => "Excedeu o número de tentativas para esta ação. Tem de aguardar {{delay}} segundos até lhe ser permitida nova tentativa.", - "REMEMBER_ME" => "Lembrar de mim!", - "REMEMBER_ME_ON_COMPUTER" => "Lembrar de mim neste computador (não recomendado em computadores públicos)", + 'RATE_LIMIT_EXCEEDED' => 'Excedeu o número de tentativas para esta ação. Tem de aguardar {{delay}} segundos até lhe ser permitida nova tentativa.', + 'REMEMBER_ME' => 'Lembrar de mim!', + 'REMEMBER_ME_ON_COMPUTER' => 'Lembrar de mim neste computador (não recomendado em computadores públicos)', - "SIGNIN" => "Iniciar Sessão", - "SIGNIN_OR_REGISTER" => "Iniciar sessão ou registrar", - "SIGNUP" => "Registrar", + 'SIGNIN' => 'Iniciar Sessão', + 'SIGNIN_OR_REGISTER' => 'Iniciar sessão ou registrar', + 'SIGNUP' => 'Registrar', - "TOS" => "Termos e Condições", - "TOS_AGREEMENT" => "Ao registrar uma conta em {{site_title}}, está a aceitar os termos e condições.", - "TOS_FOR" => "Termos e Condições para {{title}}", + 'TOS' => 'Termos e Condições', + 'TOS_AGREEMENT' => 'Ao registrar uma conta em {{site_title}}, está a aceitar os termos e condições.', + 'TOS_FOR' => 'Termos e Condições para {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "Nome de utilizador", + 'USERNAME' => [ + '@TRANSLATION' => 'Nome de utilizador', - "CHOOSE" => "Escolha um nome de utilizador único", - "INVALID" => "Nome de utilizador inválido", - "IN_USE" => "O nome de utilizador {{user_name}} já se encontra em uso." + 'CHOOSE' => 'Escolha um nome de utilizador único', + 'INVALID' => 'Nome de utilizador inválido', + 'IN_USE' => 'O nome de utilizador {{user_name}} já se encontra em uso.' ], - "USER_ID_INVALID" => "O id de utilizador solicitado não existe.", - "USER_OR_EMAIL_INVALID" => "Nome de utilizador ou endereço de email inválidos.", - "USER_OR_PASS_INVALID" => "Nome de utilizador ou password inválidos.", + 'USER_ID_INVALID' => 'O id de utilizador solicitado não existe.', + 'USER_OR_EMAIL_INVALID' => 'Nome de utilizador ou endereço de email inválidos.', + 'USER_OR_PASS_INVALID' => 'Nome de utilizador ou password inválidos.', - "WELCOME" => "Bem-vindo, {{first_name}}" + 'WELCOME' => 'Bem-vindo, {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/pt_PT/validate.php b/app/sprinkles/account/locale/pt_PT/validate.php index 4acc93e36..4293bacae 100644 --- a/app/sprinkles/account/locale/pt_PT/validate.php +++ b/app/sprinkles/account/locale/pt_PT/validate.php @@ -4,15 +4,15 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Portuguese message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\pt * @author Bruno Silva (brunomnsilva@gmail.com) */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "A password e respetiva confirmação têm de coincidir." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'A password e respetiva confirmação têm de coincidir.' ] ]; diff --git a/app/sprinkles/account/locale/ru_RU/messages.php b/app/sprinkles/account/locale/ru_RU/messages.php index 328db13bb..3c03b7360 100644 --- a/app/sprinkles/account/locale/ru_RU/messages.php +++ b/app/sprinkles/account/locale/ru_RU/messages.php @@ -4,180 +4,180 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Russian message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\ru_RU * @author @rendername */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Аккаунт", + 'ACCOUNT' => [ + '@TRANSLATION' => 'Аккаунт', - "ACCESS_DENIED" => "Для получения доступа у вас недостаточно прав.", + 'ACCESS_DENIED' => 'Для получения доступа у вас недостаточно прав.', - "DISABLED" => "Аккаунт отключен. Пожалуйста, свяжитесь с нами для получения дополнительной информации.", + 'DISABLED' => 'Аккаунт отключен. Пожалуйста, свяжитесь с нами для получения дополнительной информации.', - "EMAIL_UPDATED" => "Email аккаунта обновлён", + 'EMAIL_UPDATED' => 'Email аккаунта обновлён', - "INVALID" => "Этот аккаунт не существует. Возможно, он удалён. Пожалуйста, свяжитесь с нами для получения дополнительной информации.", + 'INVALID' => 'Этот аккаунт не существует. Возможно, он удалён. Пожалуйста, свяжитесь с нами для получения дополнительной информации.', - "MASTER_NOT_EXISTS" => "Вы не можете зарегистрировать аккаунт до тех пор, пока основная учётная запись не будет создана!", - "MY" => "Мой профиль", + 'MASTER_NOT_EXISTS' => 'Вы не можете зарегистрировать аккаунт до тех пор, пока основная учётная запись не будет создана!', + 'MY' => 'Мой профиль', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Ваша сессия была скомпрометирована. Вы должны выйти на всех устройствах, а затем снова войти и убедиться, что ваши данные не были изменены.", - "TITLE" => "Возможно, ваш аккаунт был скомпрометированн", - "TEXT" => "Возможно, кто-то использовал ваши данные для входа на эту страницу. В целях безопасности все сеансы были завершены. Пожалуйста, повторно войдите и проверьте свой аккаунт на подозрительную активность. Рекомендуем сменить пароль." + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => 'Ваша сессия была скомпрометирована. Вы должны выйти на всех устройствах, а затем снова войти и убедиться, что ваши данные не были изменены.', + 'TITLE' => 'Возможно, ваш аккаунт был скомпрометированн', + 'TEXT' => 'Возможно, кто-то использовал ваши данные для входа на эту страницу. В целях безопасности все сеансы были завершены. Пожалуйста, повторно войдите и проверьте свой аккаунт на подозрительную активность. Рекомендуем сменить пароль.' ], - "SESSION_EXPIRED" => "Срок вашей сессии истек. Пожалуйста войдите еще раз.", + 'SESSION_EXPIRED' => 'Срок вашей сессии истек. Пожалуйста войдите еще раз.', - "SETTINGS" => [ - "@TRANSLATION" => "Настройки аккаунта", - "DESCRIPTION" => "Обновите настройки своего аккаунта, включая адрес электронной почты, имя и пароль.", - "UPDATED" => "Данные аккаунта обновлены" + 'SETTINGS' => [ + '@TRANSLATION' => 'Настройки аккаунта', + 'DESCRIPTION' => 'Обновите настройки своего аккаунта, включая адрес электронной почты, имя и пароль.', + 'UPDATED' => 'Данные аккаунта обновлены' ], - "TOOLS" => "Инструменты аккаунта", + 'TOOLS' => 'Инструменты аккаунта', - "UNVERIFIED" => "Ваш аккаунт ещё не подтверждён. Проверьте вашу email почту, в том числе папку спам и следуйте инструкциям.", + 'UNVERIFIED' => 'Ваш аккаунт ещё не подтверждён. Проверьте вашу email почту, в том числе папку спам и следуйте инструкциям.', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "Мы отправили на ваш email новую ссылку для активации {{email}}. Пожалуйста, проверьте папку \"Входящие\" и \"Спам\".", - "RESEND" => "Повторно отправить письмо с подтверждением", - "COMPLETE" => "Вы успешно подтвердили свой аккаунт. Теперь вы можете войти.", - "EMAIL" => "Введите email, который вы использовали для регистрации, вам будет повторно отправлено письмо с подтверждением.", - "PAGE" => "Повторно оправить письмо подтверждения на email для нового аккаунта.", - "SEND" => "Проверка по электронной почте для аккаунта", - "TOKEN_NOT_FOUND" => "Код подтверждения не действителен либо аккаунт уже подтверждён", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'Мы отправили на ваш email новую ссылку для активации {{email}}. Пожалуйста, проверьте папку "Входящие" и "Спам".', + 'RESEND' => 'Повторно отправить письмо с подтверждением', + 'COMPLETE' => 'Вы успешно подтвердили свой аккаунт. Теперь вы можете войти.', + 'EMAIL' => 'Введите email, который вы использовали для регистрации, вам будет повторно отправлено письмо с подтверждением.', + 'PAGE' => 'Повторно оправить письмо подтверждения на email для нового аккаунта.', + 'SEND' => 'Проверка по электронной почте для аккаунта', + 'TOKEN_NOT_FOUND' => 'Код подтверждения не действителен либо аккаунт уже подтверждён', ] ], - "EMAIL" => [ - "INVALID" => "Нет не одного аккаунта с {{email}} .", - "IN_USE" => "Email {{email}} уже используется.", - "VERIFICATION_REQUIRED" => "Email (указывайте верный - необходим для активации!)" + 'EMAIL' => [ + 'INVALID' => 'Нет не одного аккаунта с {{email}} .', + 'IN_USE' => 'Email {{email}} уже используется.', + 'VERIFICATION_REQUIRED' => 'Email (указывайте верный - необходим для активации!)' ], - "EMAIL_OR_USERNAME" => "Имя пользователя или Email", + 'EMAIL_OR_USERNAME' => 'Имя пользователя или Email', - "FIRST_NAME" => "Имя", + 'FIRST_NAME' => 'Имя', - "HEADER_MESSAGE_ROOT" => "ВЫ АВТОРИЗОВАНЫ С СУПЕР-ПРАВАМИ", + 'HEADER_MESSAGE_ROOT' => 'ВЫ АВТОРИЗОВАНЫ С СУПЕР-ПРАВАМИ', - "LAST_NAME" => "Фамилия", - "LOCALE" => [ - "ACCOUNT" => "Основной язык для вашего аккаунта", - "INVALID" => "{{locale}} язык недопустим." + 'LAST_NAME' => 'Фамилия', + 'LOCALE' => [ + 'ACCOUNT' => 'Основной язык для вашего аккаунта', + 'INVALID' => '{{locale}} язык недопустим.' ], - "LOGIN" => [ - "@TRANSLATION" => "Вход", - "ALREADY_COMPLETE" => "Вы уже выполнили вход!", - "SOCIAL" => "Или войти через", - "REQUIRED" => "Извините, Вы должны авторизоваться для доступа к этому ресурсу." + 'LOGIN' => [ + '@TRANSLATION' => 'Вход', + 'ALREADY_COMPLETE' => 'Вы уже выполнили вход!', + 'SOCIAL' => 'Или войти через', + 'REQUIRED' => 'Извините, Вы должны авторизоваться для доступа к этому ресурсу.' ], - "LOGOUT" => "Выход", + 'LOGOUT' => 'Выход', - "NAME" => "Имя", + 'NAME' => 'Имя', - "NAME_AND_EMAIL" => "Имя и email", + 'NAME_AND_EMAIL' => 'Имя и email', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "Войдите в свой аккаунт {{site_name}}, или Зарегистрируйтесь.", - "SUBTITLE" => "Зарегистрироваться или войти в существующий аккаунт.", - "TITLE" => "Приступим!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'Войдите в свой аккаунт {{site_name}}, или Зарегистрируйтесь.', + 'SUBTITLE' => 'Зарегистрироваться или войти в существующий аккаунт.', + 'TITLE' => 'Приступим!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "Пароль", + 'PASSWORD' => [ + '@TRANSLATION' => 'Пароль', - "BETWEEN" => "Кол-во {{min}}-{{max}} символов", + 'BETWEEN' => 'Кол-во {{min}}-{{max}} символов', - "CONFIRM" => "Подтверждение пароля", - "CONFIRM_CURRENT" => "Пожалуйста, введите ваш текущий пароль", - "CONFIRM_NEW" => "Подтвердите новый пароль", - "CONFIRM_NEW_EXPLAIN" => "Повторно введите Ваш новый пароль", - "CONFIRM_NEW_HELP" => "Требуется только при выборе нового пароля", - "CREATE" => [ - "@TRANSLATION" => "Создать пароль", - "PAGE" => "Выберите пароль для вашего аккаунта.", - "SET" => "Установить пароль и войти" + 'CONFIRM' => 'Подтверждение пароля', + 'CONFIRM_CURRENT' => 'Пожалуйста, введите ваш текущий пароль', + 'CONFIRM_NEW' => 'Подтвердите новый пароль', + 'CONFIRM_NEW_EXPLAIN' => 'Повторно введите Ваш новый пароль', + 'CONFIRM_NEW_HELP' => 'Требуется только при выборе нового пароля', + 'CREATE' => [ + '@TRANSLATION' => 'Создать пароль', + 'PAGE' => 'Выберите пароль для вашего аккаунта.', + 'SET' => 'Установить пароль и войти' ], - "CURRENT" => "Текущий пароль", - "CURRENT_EXPLAIN" => "Для продолжения вы должны ввести текущий пароль", - - "FORGOTTEN" => "Забытый пароль?", - "FORGET" => [ - "@TRANSLATION" => "Я забыл свой пароль", - - "COULD_NOT_UPDATE" => "Не удалось обновить пароль.", - "EMAIL" => "Пожалуйста, введите адрес электронной почты, который Вы использовали при регистрации. Ссылка с инструкцией по сбросу пароля будет отправлена вам по электронной почте.", - "EMAIL_SEND" => "Ссылка сброса пароля по Email", - "INVALID" => "Этот запрос сброса пароля не может быть найден, или истек. Пожалуйста, попробуйте повторно сбросить пароль.", - "PAGE" => "Получите ссылку для сброса пароля.", - "REQUEST_CANNED" => "Запрос на сброс пароля отменен.", - "REQUEST_SENT" => "Если email {{email}} существует в нашей системе у какого-либо аккаунта, ссылка на сброс пароля будет направлена на {{email}}." + 'CURRENT' => 'Текущий пароль', + 'CURRENT_EXPLAIN' => 'Для продолжения вы должны ввести текущий пароль', + + 'FORGOTTEN' => 'Забытый пароль?', + 'FORGET' => [ + '@TRANSLATION' => 'Я забыл свой пароль', + + 'COULD_NOT_UPDATE' => 'Не удалось обновить пароль.', + 'EMAIL' => 'Пожалуйста, введите адрес электронной почты, который Вы использовали при регистрации. Ссылка с инструкцией по сбросу пароля будет отправлена вам по электронной почте.', + 'EMAIL_SEND' => 'Ссылка сброса пароля по Email', + 'INVALID' => 'Этот запрос сброса пароля не может быть найден, или истек. Пожалуйста, попробуйте повторно сбросить пароль.', + 'PAGE' => 'Получите ссылку для сброса пароля.', + 'REQUEST_CANNED' => 'Запрос на сброс пароля отменен.', + 'REQUEST_SENT' => 'Если email {{email}} существует в нашей системе у какого-либо аккаунта, ссылка на сброс пароля будет направлена на {{email}}.' ], - "HASH_FAILED" => "Хэширование пароля не удалось. Пожалуйста, попробуйте другой пароль, либо свяжитесь с администратором сайта.", - "INVALID" => "Текущий пароль не соответствует тому, который задан в системе.", - "NEW" => "Новый пароль", - "NOTHING_TO_UPDATE" => "Невозможно обновить с тем же паролем", + 'HASH_FAILED' => 'Хэширование пароля не удалось. Пожалуйста, попробуйте другой пароль, либо свяжитесь с администратором сайта.', + 'INVALID' => 'Текущий пароль не соответствует тому, который задан в системе.', + 'NEW' => 'Новый пароль', + 'NOTHING_TO_UPDATE' => 'Невозможно обновить с тем же паролем', - "RESET" => [ - "@TRANSLATION" => "Сбросить пароль", - "CHOOSE" => "Пожалуйста, выберите новый пароль, чтобы продолжить.", - "PAGE" => "Выберите новый пароль для вашего аккаунта.", - "SEND" => "Задать новый пароль и войти" + 'RESET' => [ + '@TRANSLATION' => 'Сбросить пароль', + 'CHOOSE' => 'Пожалуйста, выберите новый пароль, чтобы продолжить.', + 'PAGE' => 'Выберите новый пароль для вашего аккаунта.', + 'SEND' => 'Задать новый пароль и войти' ], - "UPDATED" => "Пароль аккаунта обновлён" + 'UPDATED' => 'Пароль аккаунта обновлён' ], - "PROFILE" => [ - "SETTINGS" => "Настройки профиля", - "UPDATED" => "Настройки профиля обновлены" + 'PROFILE' => [ + 'SETTINGS' => 'Настройки профиля', + 'UPDATED' => 'Настройки профиля обновлены' ], - "RATE_LIMIT_EXCEEDED" => "Превышен лимит попыток для этого действия. Вы должны подождать еще {{delay}} секунд, прежде чем вам вам будет разрешено сделать ещё попытку.", - - "REGISTER" => "Регистрация", - "REGISTER_ME" => "Зарегистрируйте меня", - "REGISTRATION" => [ - "BROKEN" => "К сожалению, есть проблема с регистрации аккаунта. Свяжитесь с нами напрямую для получения помощи.", - "COMPLETE_TYPE1" => "Вы успешно зарегистрировались. Теперь вы можете войти.", - "COMPLETE_TYPE2" => "Вы успешно зарегистрировались. Ссылка для активации вашего аккаунта была отправлена на {{email}}. Вы сможете войти в систему только после активации аккаунта.", - "DISABLED" => "Извините, регистрация аккаунта была отключена.", - "LOGOUT" => "Извините, вы не можете зарегистрироваться когда уже авторизовались в системе. Сначала выйдите из системы.", - "WELCOME" => "Быстрая и простая регистрация." + 'RATE_LIMIT_EXCEEDED' => 'Превышен лимит попыток для этого действия. Вы должны подождать еще {{delay}} секунд, прежде чем вам вам будет разрешено сделать ещё попытку.', + + 'REGISTER' => 'Регистрация', + 'REGISTER_ME' => 'Зарегистрируйте меня', + 'REGISTRATION' => [ + 'BROKEN' => 'К сожалению, есть проблема с регистрации аккаунта. Свяжитесь с нами напрямую для получения помощи.', + 'COMPLETE_TYPE1' => 'Вы успешно зарегистрировались. Теперь вы можете войти.', + 'COMPLETE_TYPE2' => 'Вы успешно зарегистрировались. Ссылка для активации вашего аккаунта была отправлена на {{email}}. Вы сможете войти в систему только после активации аккаунта.', + 'DISABLED' => 'Извините, регистрация аккаунта была отключена.', + 'LOGOUT' => 'Извините, вы не можете зарегистрироваться когда уже авторизовались в системе. Сначала выйдите из системы.', + 'WELCOME' => 'Быстрая и простая регистрация.' ], - "REMEMBER_ME" => "Запомнить", - "REMEMBER_ME_ON_COMPUTER" => "Запомнить меня на этом компьютере (не рекомендуется для общедоступных компьютеров)", + 'REMEMBER_ME' => 'Запомнить', + 'REMEMBER_ME_ON_COMPUTER' => 'Запомнить меня на этом компьютере (не рекомендуется для общедоступных компьютеров)', - "SIGN_IN_HERE" => "Уже есть аккаунт? войти.", - "SIGNIN" => "Вход", - "SIGNIN_OR_REGISTER" => "Регистрация или вход", - "SIGNUP" => "Вход", + 'SIGN_IN_HERE' => 'Уже есть аккаунт? войти.', + 'SIGNIN' => 'Вход', + 'SIGNIN_OR_REGISTER' => 'Регистрация или вход', + 'SIGNUP' => 'Вход', - "TOS" => "Пользовательское соглашение", - "TOS_AGREEMENT" => "Регистрируя аккаунт на {{site_title}}, вы принимаете условия и положения.", - "TOS_FOR" => "Правила и условия для {{title}}", + 'TOS' => 'Пользовательское соглашение', + 'TOS_AGREEMENT' => 'Регистрируя аккаунт на {{site_title}}, вы принимаете условия и положения.', + 'TOS_FOR' => 'Правила и условия для {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "Пользователь", + 'USERNAME' => [ + '@TRANSLATION' => 'Пользователь', - "CHOOSE" => "Выберите имя пользователя", - "INVALID" => "Недопустимое имя пользователя", - "IN_USE" => "{{user_name}} имя пользователя уже используется.", - "NOT_AVAILABLE" => "Имя пользователя {{user_name}} не доступно. Выберите другое имя или нажмите кнопку «предложить»." + 'CHOOSE' => 'Выберите имя пользователя', + 'INVALID' => 'Недопустимое имя пользователя', + 'IN_USE' => '{{user_name}} имя пользователя уже используется.', + 'NOT_AVAILABLE' => 'Имя пользователя {{user_name}} не доступно. Выберите другое имя или нажмите кнопку «предложить».' ], - "USER_ID_INVALID" => "ID запрашиваемого пользователя не существует.", - "USER_OR_EMAIL_INVALID" => "Имя пользователя или email не верный.", - "USER_OR_PASS_INVALID" => "Пользователь не найден или пароль является недействительным.", + 'USER_ID_INVALID' => 'ID запрашиваемого пользователя не существует.', + 'USER_OR_EMAIL_INVALID' => 'Имя пользователя или email не верный.', + 'USER_OR_PASS_INVALID' => 'Пользователь не найден или пароль является недействительным.', - "WELCOME" => "Добро пожаловать, {{first_name}}" + 'WELCOME' => 'Добро пожаловать, {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/ru_RU/validate.php b/app/sprinkles/account/locale/ru_RU/validate.php index 4d39bbef0..981b65356 100644 --- a/app/sprinkles/account/locale/ru_RU/validate.php +++ b/app/sprinkles/account/locale/ru_RU/validate.php @@ -4,16 +4,16 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Russian message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\ru_RU * @author @rendername */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Пароли не совпадают.", - "USERNAME" => "Имя может состоять только из строчных букв, цифр, '.', '-' и «_»." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'Пароли не совпадают.', + 'USERNAME' => "Имя может состоять только из строчных букв, цифр, '.', '-' и «_»." ] ]; diff --git a/app/sprinkles/account/locale/th_TH/messages.php b/app/sprinkles/account/locale/th_TH/messages.php index 012c7f4f8..8fb36cef9 100644 --- a/app/sprinkles/account/locale/th_TH/messages.php +++ b/app/sprinkles/account/locale/th_TH/messages.php @@ -4,161 +4,161 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Thai message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\th * @author Karuhut Komol */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "บัญชี", + 'ACCOUNT' => [ + '@TRANSLATION' => 'บัญชี', - "ACCESS_DENIED" => "หืมม ดูเหมือนว่าคุณไม่ได้รับอนุญาตให้ทำเช่นนั้น", + 'ACCESS_DENIED' => 'หืมม ดูเหมือนว่าคุณไม่ได้รับอนุญาตให้ทำเช่นนั้น', - "DISABLED" => "บัญชีนี้ถูกปิดการใช้งานไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม", + 'DISABLED' => 'บัญชีนี้ถูกปิดการใช้งานไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม', - "EMAIL_UPDATED" => "ปรับปรุงบัญชีอีเมลแล้ว", + 'EMAIL_UPDATED' => 'ปรับปรุงบัญชีอีเมลแล้ว', - "INVALID" => "ไม่พบบัญชีนี้ มันอาจถูกลบไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม", + 'INVALID' => 'ไม่พบบัญชีนี้ มันอาจถูกลบไปแล้ว กรุณาติดต่อเราสำหรับข้อมูลเพิ่มเติม', - "MASTER_NOT_EXISTS" => "คุณไม่สามารถสมัครสมาชิกได้จนกว่าจะสร้างบัญชีหลัก!", - "MY" => "บัญชีของฉัน", + 'MASTER_NOT_EXISTS' => 'คุณไม่สามารถสมัครสมาชิกได้จนกว่าจะสร้างบัญชีหลัก!', + 'MY' => 'บัญชีของฉัน', - "SESSION_COMPROMISED" => "เซสชันของคุณถูกลักลอบใช้ คุณควรจะออกจากระบบบนอุปกรณ์ทั้งหมดแล้วกลับเข้าสู่ระบบและตรวจสอบให้แน่ใจว่าไม่มีการแก้ไขข้อมูลของคุณ", - "SESSION_COMPROMISED_TITLE" => "บัญชีของคุณอาจถูกบุกรุก", - "SESSION_EXPIRED" => "เซสชันของคุณหมดอายุ กรุณาเข้าสู่ระบบอีกครั้ง", + 'SESSION_COMPROMISED' => 'เซสชันของคุณถูกลักลอบใช้ คุณควรจะออกจากระบบบนอุปกรณ์ทั้งหมดแล้วกลับเข้าสู่ระบบและตรวจสอบให้แน่ใจว่าไม่มีการแก้ไขข้อมูลของคุณ', + 'SESSION_COMPROMISED_TITLE' => 'บัญชีของคุณอาจถูกบุกรุก', + 'SESSION_EXPIRED' => 'เซสชันของคุณหมดอายุ กรุณาเข้าสู่ระบบอีกครั้ง', - "SETTINGS" => [ - "@TRANSLATION" => "การตั้งค่าบัญชี", - "DESCRIPTION" => "ปรับปรุงการตั้งค่าบัญชีของคุณ รวมไปถึงอีเมล ชื่อ และรหัสผ่าน", - "UPDATED" => "ปรับปรุงการตั้งค่าบัญชีของคุณแล้ว" + 'SETTINGS' => [ + '@TRANSLATION' => 'การตั้งค่าบัญชี', + 'DESCRIPTION' => 'ปรับปรุงการตั้งค่าบัญชีของคุณ รวมไปถึงอีเมล ชื่อ และรหัสผ่าน', + 'UPDATED' => 'ปรับปรุงการตั้งค่าบัญชีของคุณแล้ว' ], - "TOOLS" => "เครื่องมือบัญชี", + 'TOOLS' => 'เครื่องมือบัญชี', - "UNVERIFIED" => "บัญชีของคุณยังไม่ได้รับการยืนยัน กรุณาตรวจสอบกล่องอีเมลและจดหมายขยะของคุณสำหรับขั้นตอนการเปิดใช้งานบัญชี", + 'UNVERIFIED' => 'บัญชีของคุณยังไม่ได้รับการยืนยัน กรุณาตรวจสอบกล่องอีเมลและจดหมายขยะของคุณสำหรับขั้นตอนการเปิดใช้งานบัญชี', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "เราได้ส่งลิงก์สำหรับการยืนยันใหม่ไปยังอีเมล {{email}} กรุณาตรวจสอบอีเมลนี้ในกล่องอีเมลและจดหมายขยะของคุณ", - "RESEND" => "ส่งอีเมลยืนยันอีกครั้ง", - "COMPLETE" => "คุณได้ยืนยันอีเมลของคุณเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที", - "EMAIL" => "กรุณากรอกอีเมลที่คุณได้ใช้สมัครไว้แล้วอีเมลยืนยันจะถูกส่งไปให้ใหม่", - "PAGE" => "ส่งอีเมลยืนยันสำหรับบัญชีของฉันใหม่", - "SEND" => "ส่งอีเมลยืนยันให้บัญชีของฉัน", - "TOKEN_NOT_FOUND" => "ไม่พบโทเคนยืนยันอีเมล / บัญชีนี้ได้ยืนยันแล้ว", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => 'เราได้ส่งลิงก์สำหรับการยืนยันใหม่ไปยังอีเมล {{email}} กรุณาตรวจสอบอีเมลนี้ในกล่องอีเมลและจดหมายขยะของคุณ', + 'RESEND' => 'ส่งอีเมลยืนยันอีกครั้ง', + 'COMPLETE' => 'คุณได้ยืนยันอีเมลของคุณเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที', + 'EMAIL' => 'กรุณากรอกอีเมลที่คุณได้ใช้สมัครไว้แล้วอีเมลยืนยันจะถูกส่งไปให้ใหม่', + 'PAGE' => 'ส่งอีเมลยืนยันสำหรับบัญชีของฉันใหม่', + 'SEND' => 'ส่งอีเมลยืนยันให้บัญชีของฉัน', + 'TOKEN_NOT_FOUND' => 'ไม่พบโทเคนยืนยันอีเมล / บัญชีนี้ได้ยืนยันแล้ว', ] ], - "EMAIL" => [ - "INVALID" => "อีเมล {{email}} ไม่มีอยู่จริง", - "IN_USE" => "อีเมล {{email}} ได้ถูกใช้งานแล้ว" + 'EMAIL' => [ + 'INVALID' => 'อีเมล {{email}} ไม่มีอยู่จริง', + 'IN_USE' => 'อีเมล {{email}} ได้ถูกใช้งานแล้ว' ], - "FIRST_NAME" => "ชื่อจริง", + 'FIRST_NAME' => 'ชื่อจริง', - "HEADER_MESSAGE_ROOT" => "คุณได้เข้าสู่ระบบเป็นผู้ดูแลสูงสุด", + 'HEADER_MESSAGE_ROOT' => 'คุณได้เข้าสู่ระบบเป็นผู้ดูแลสูงสุด', - "LAST_NAME" => "นามสกุล", + 'LAST_NAME' => 'นามสกุล', - "LOCALE.ACCOUNT" => "ภาษาและสถานที่ที่จะใช้สำหรับบัญชีของคุณ", + 'LOCALE.ACCOUNT' => 'ภาษาและสถานที่ที่จะใช้สำหรับบัญชีของคุณ', - "LOGIN" => [ - "@TRANSLATION" => "เข้าสู่ะระบบ", + 'LOGIN' => [ + '@TRANSLATION' => 'เข้าสู่ะระบบ', - "ALREADY_COMPLETE" => "คุณได้เข้าสู่ระบบอยู่แล้ว!", - "SOCIAL" => "หรือเข้าสู่ระบบด้วย", - "REQUIRED" => "ขออภัย คุณจะต้องเข้าสู่ระบบเพื่อเข้าถึงส่วนนี้" + 'ALREADY_COMPLETE' => 'คุณได้เข้าสู่ระบบอยู่แล้ว!', + 'SOCIAL' => 'หรือเข้าสู่ระบบด้วย', + 'REQUIRED' => 'ขออภัย คุณจะต้องเข้าสู่ระบบเพื่อเข้าถึงส่วนนี้' ], - "LOGOUT" => "ออกจากระบบ", + 'LOGOUT' => 'ออกจากระบบ', - "NAME" => "ชื่อ", + 'NAME' => 'ชื่อ', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "เข้าสู่ระบบไปยังบัญชี {{site_name}} หรือสมัครสมาชิกสำหรับบัญชีใหม่", - "SUBTITLE" => "สมัครสมาชิกฟรี หรือเข้าสู่ระบบด้วยบัญชีที่มีอยู่", - "TITLE" => "มาเริ่มกันเลย!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => 'เข้าสู่ระบบไปยังบัญชี {{site_name}} หรือสมัครสมาชิกสำหรับบัญชีใหม่', + 'SUBTITLE' => 'สมัครสมาชิกฟรี หรือเข้าสู่ระบบด้วยบัญชีที่มีอยู่', + 'TITLE' => 'มาเริ่มกันเลย!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "รหัสผ่าน", - - "BETWEEN" => "ระหว่าง {{min}}-{{max}} ตัวอักษร", - - "CONFIRM" => "ยืนยันรหัสผ่าน", - "CONFIRM_CURRENT" => "กรุณายืนยันรหัสผ่านปัจจุบันของคุณ", - "CONFIRM_NEW" => "ยืนยันรหัสผ่านใหม่", - "CONFIRM_NEW_EXPLAIN" => "กรอกรหัสผ่านใหม่ของคุณอีกครั้ง", - "CONFIRM_NEW_HELP" => "กรอกเฉพาะเมื่อคุณต้องการตั้งรหัสผ่านใหม่", - "CURRENT" => "รหัสผ่านปัจจุบัน", - "CURRENT_EXPLAIN" => "คุณจะต้องยืนยันรหัสผ่านปัจจุบันเพื่อแก้ไขข้อมูล", - - "FORGOTTEN" => "ลืมรหัสผ่าน", - "FORGET" => [ - "@TRANSLATION" => "ฉันลืมรหัสผ่านของฉัน", - - "COULD_NOT_UPDATE" => "ไม่สามารถปรับปรุงรหัสผ่าน", - "EMAIL" => "กรุณากรอกที่อยู่อีเมลที่คุณเคยใช้เข้าสู่ระบบ ลิงก์ขั้นตอนการรีเซ็ตรหัสผ่านของคุณจะถูกส่งไปให้คุณ", - "EMAIL_SEND" => "ลิงก์รีเซ็ตรหัสผ่านจากอีเมล", - "INVALID" => "ขอรีเซ็ตรหัสผ่านนี้ไม่มีอยู่ หรือหมดอายุไปแล้ว กรุณาลอง ส่งคำขอของคุณอีกครั้ง", - "PAGE" => "รับลิงก์สำหรับการรีเซ็ตรหัสผ่านของคุณ", - "REQUEST_CANNED" => "คำขอลืมรหัสผ่านได้ถูกยกเลิก", - "REQUEST_SENT" => "หากอีเมล {{email}} ตรงกับบัญชีในระบบของเราลิงก์การรีเซ็ตรหัสผ่านจะถูกส่งไปที่ {{email}}" + 'PASSWORD' => [ + '@TRANSLATION' => 'รหัสผ่าน', + + 'BETWEEN' => 'ระหว่าง {{min}}-{{max}} ตัวอักษร', + + 'CONFIRM' => 'ยืนยันรหัสผ่าน', + 'CONFIRM_CURRENT' => 'กรุณายืนยันรหัสผ่านปัจจุบันของคุณ', + 'CONFIRM_NEW' => 'ยืนยันรหัสผ่านใหม่', + 'CONFIRM_NEW_EXPLAIN' => 'กรอกรหัสผ่านใหม่ของคุณอีกครั้ง', + 'CONFIRM_NEW_HELP' => 'กรอกเฉพาะเมื่อคุณต้องการตั้งรหัสผ่านใหม่', + 'CURRENT' => 'รหัสผ่านปัจจุบัน', + 'CURRENT_EXPLAIN' => 'คุณจะต้องยืนยันรหัสผ่านปัจจุบันเพื่อแก้ไขข้อมูล', + + 'FORGOTTEN' => 'ลืมรหัสผ่าน', + 'FORGET' => [ + '@TRANSLATION' => 'ฉันลืมรหัสผ่านของฉัน', + + 'COULD_NOT_UPDATE' => 'ไม่สามารถปรับปรุงรหัสผ่าน', + 'EMAIL' => 'กรุณากรอกที่อยู่อีเมลที่คุณเคยใช้เข้าสู่ระบบ ลิงก์ขั้นตอนการรีเซ็ตรหัสผ่านของคุณจะถูกส่งไปให้คุณ', + 'EMAIL_SEND' => 'ลิงก์รีเซ็ตรหัสผ่านจากอีเมล', + 'INVALID' => 'ขอรีเซ็ตรหัสผ่านนี้ไม่มีอยู่ หรือหมดอายุไปแล้ว กรุณาลอง ส่งคำขอของคุณอีกครั้ง', + 'PAGE' => 'รับลิงก์สำหรับการรีเซ็ตรหัสผ่านของคุณ', + 'REQUEST_CANNED' => 'คำขอลืมรหัสผ่านได้ถูกยกเลิก', + 'REQUEST_SENT' => 'หากอีเมล {{email}} ตรงกับบัญชีในระบบของเราลิงก์การรีเซ็ตรหัสผ่านจะถูกส่งไปที่ {{email}}' ], - "RESET" => [ - "@TRANSLATION" => "รีเซ็ตรหัสผ่าน", - "CHOOSE" => "กรุณาเลือกรหัสผ่านใหม่เพื่อดำเนินการต่อ", - "PAGE" => "เลือกรหัสผ่านใหม่สำหรับบัญชีของคุณ", - "SEND" => "ตั้งรหัสผ่านใหม่และเข้าสู่ระบบ" + 'RESET' => [ + '@TRANSLATION' => 'รีเซ็ตรหัสผ่าน', + 'CHOOSE' => 'กรุณาเลือกรหัสผ่านใหม่เพื่อดำเนินการต่อ', + 'PAGE' => 'เลือกรหัสผ่านใหม่สำหรับบัญชีของคุณ', + 'SEND' => 'ตั้งรหัสผ่านใหม่และเข้าสู่ระบบ' ], - "HASH_FAILED" => "เข้ารหัสรหัสผ่านล้มเหลว กรุณาติดต่อผู้ดูแลระบบของเว็บไซต์", - "INVALID" => "รหัสผ่านปัจจุบันไม่ตรงกับรหัสผ่านที่เราบันทึกไว้", - "NEW" => "รหัสผ่านใหม่", - "NOTHING_TO_UPDATE" => "คุณไม่สามารถปรังปรุงด้วยรหัสผ่านเดียวกัน", - "UPDATED" => "ปรังปรุงรหัสผ่านของบัญชีแล้ว" + 'HASH_FAILED' => 'เข้ารหัสรหัสผ่านล้มเหลว กรุณาติดต่อผู้ดูแลระบบของเว็บไซต์', + 'INVALID' => 'รหัสผ่านปัจจุบันไม่ตรงกับรหัสผ่านที่เราบันทึกไว้', + 'NEW' => 'รหัสผ่านใหม่', + 'NOTHING_TO_UPDATE' => 'คุณไม่สามารถปรังปรุงด้วยรหัสผ่านเดียวกัน', + 'UPDATED' => 'ปรังปรุงรหัสผ่านของบัญชีแล้ว' ], - "REGISTER" => "สมัครสมาชิก", - "REGISTER_ME" => "ให้ฉันสมัครสมาชิกด้วย", + 'REGISTER' => 'สมัครสมาชิก', + 'REGISTER_ME' => 'ให้ฉันสมัครสมาชิกด้วย', - "REGISTRATION" => [ - "BROKEN" => "เราขออภัย มันมีปัญหาในการดำเนินการสมัครสมาชิกของเรา กรุณาติดต่อเราโดยตรงเพื่อขอความช่วยเหลือ", - "COMPLETE_TYPE1" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที", - "COMPLETE_TYPE2" => "คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณจะได้รับอีเมลยืนยันที่มีลิงก์สำหรับเปิดใช้งานบัญชีของคุณอยู่ คุณจะไม่สามารถเข้าสู่ระบบจนกว่าคุณจะยืนยันอีเมลแล้ว", - "DISABLED" => "เราขออภัย ระบบสมัครสมาชิกได้ถูกปิดไว้", - "LOGOUT" => "เราขออภัย คุณไม่สามารถสมัครสมาชิกขณะที่เข้าสู่ระบบอยู่ กรุณาออกจากระบบก่อน", - "WELCOME" => "การสมัครสมาชิกนั้นรวดเร็ว และง่ายดาย" + 'REGISTRATION' => [ + 'BROKEN' => 'เราขออภัย มันมีปัญหาในการดำเนินการสมัครสมาชิกของเรา กรุณาติดต่อเราโดยตรงเพื่อขอความช่วยเหลือ', + 'COMPLETE_TYPE1' => 'คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณสามารถเข้าสู่ระบบได้ทันที', + 'COMPLETE_TYPE2' => 'คุณได้สมัครสมาชิกเรียบร้อยแล้ว คุณจะได้รับอีเมลยืนยันที่มีลิงก์สำหรับเปิดใช้งานบัญชีของคุณอยู่ คุณจะไม่สามารถเข้าสู่ระบบจนกว่าคุณจะยืนยันอีเมลแล้ว', + 'DISABLED' => 'เราขออภัย ระบบสมัครสมาชิกได้ถูกปิดไว้', + 'LOGOUT' => 'เราขออภัย คุณไม่สามารถสมัครสมาชิกขณะที่เข้าสู่ระบบอยู่ กรุณาออกจากระบบก่อน', + 'WELCOME' => 'การสมัครสมาชิกนั้นรวดเร็ว และง่ายดาย' ], - "RATE_LIMIT_EXCEEDED" => "ถึงขีดจำกัดสำหรับการกระทำนี้แล้ว คุณจะต้องรออีก {{delay}} วินาที ก่อนที่คุณจะได้รับอนุญาตให้ลองใหม่อีกครั้ง", - "REMEMBER_ME" => "จำฉันไว้ในระบบ!", - "REMEMBER_ME_ON_COMPUTER" => "จำฉันไว้ในระบบบนคอมพิวเตอร์นี้ (ไม่แนะนำสำหรับคอมพิวเตอร์สาธารณะ)", + 'RATE_LIMIT_EXCEEDED' => 'ถึงขีดจำกัดสำหรับการกระทำนี้แล้ว คุณจะต้องรออีก {{delay}} วินาที ก่อนที่คุณจะได้รับอนุญาตให้ลองใหม่อีกครั้ง', + 'REMEMBER_ME' => 'จำฉันไว้ในระบบ!', + 'REMEMBER_ME_ON_COMPUTER' => 'จำฉันไว้ในระบบบนคอมพิวเตอร์นี้ (ไม่แนะนำสำหรับคอมพิวเตอร์สาธารณะ)', - "SIGNIN" => "เข้าสู่ะระบบ", - "SIGNIN_OR_REGISTER" => "เข้าสู่ระบบหรือสมัครสมาชิก", - "SIGNUP" => "สมัครสมาชิก", + 'SIGNIN' => 'เข้าสู่ะระบบ', + 'SIGNIN_OR_REGISTER' => 'เข้าสู่ระบบหรือสมัครสมาชิก', + 'SIGNUP' => 'สมัครสมาชิก', - "TOS" => "ข้อตกลงและเงื่อนไข", - "TOS_AGREEMENT" => "ในการสมัครสมาชิกกับ {{site_title}} หมายถึงคุณยอมรับ ข้อตกลงและเงื่อนไข แล้ว", - "TOS_FOR" => "ข้อตกลงและเงื่อนไขสำหรับ {{title}}", + 'TOS' => 'ข้อตกลงและเงื่อนไข', + 'TOS_AGREEMENT' => 'ในการสมัครสมาชิกกับ {{site_title}} หมายถึงคุณยอมรับ ข้อตกลงและเงื่อนไข แล้ว', + 'TOS_FOR' => 'ข้อตกลงและเงื่อนไขสำหรับ {{title}}', - "USERNAME" => [ - "@TRANSLATION" => "ชื่อผู้ใช้", + 'USERNAME' => [ + '@TRANSLATION' => 'ชื่อผู้ใช้', - "CHOOSE" => "เลือกชื่อผู้ใช้ที่เป็นเป็นเอกลักษณ์", - "INVALID" => "ชื่อผู้ใช้ไม่ถูกต้อง", - "IN_USE" => "ชื่อผู้ใช้ {{user_name}} ถูกใช้งานแล้ว" + 'CHOOSE' => 'เลือกชื่อผู้ใช้ที่เป็นเป็นเอกลักษณ์', + 'INVALID' => 'ชื่อผู้ใช้ไม่ถูกต้อง', + 'IN_USE' => 'ชื่อผู้ใช้ {{user_name}} ถูกใช้งานแล้ว' ], - "USER_ID_INVALID" => "ไม่พบหมายเลขผู้ใช้ที่ร้องขอมา", - "USER_OR_EMAIL_INVALID" => "ชื่อผู้ใช้หรือที่อยู่อีเมลไม่ถูกต้อง", - "USER_OR_PASS_INVALID" => "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง", + 'USER_ID_INVALID' => 'ไม่พบหมายเลขผู้ใช้ที่ร้องขอมา', + 'USER_OR_EMAIL_INVALID' => 'ชื่อผู้ใช้หรือที่อยู่อีเมลไม่ถูกต้อง', + 'USER_OR_PASS_INVALID' => 'ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง', - "WELCOME" => "ยินดีต้อนรับ {{first_name}}" + 'WELCOME' => 'ยินดีต้อนรับ {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/th_TH/validate.php b/app/sprinkles/account/locale/th_TH/validate.php index 14a7adb2d..edc84ce74 100644 --- a/app/sprinkles/account/locale/th_TH/validate.php +++ b/app/sprinkles/account/locale/th_TH/validate.php @@ -4,15 +4,15 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Thai message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\th * @author Karuhut Komol */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "รหัสผ่านและรหัสผ่านยืนยันของคุณจะต้องตรงกัน" + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'รหัสผ่านและรหัสผ่านยืนยันของคุณจะต้องตรงกัน' ] ]; diff --git a/app/sprinkles/account/locale/tr/messages.php b/app/sprinkles/account/locale/tr/messages.php index 5213490cb..d61cf2afb 100644 --- a/app/sprinkles/account/locale/tr/messages.php +++ b/app/sprinkles/account/locale/tr/messages.php @@ -4,180 +4,180 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Turkish message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\tr * @author Dumblledore */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "Hesap", + 'ACCOUNT' => [ + '@TRANSLATION' => 'Hesap', - "ACCESS_DENIED" => "Hmm. görünüşe göre böyle bir şey için izne sahip değilsiniz.", + 'ACCESS_DENIED' => 'Hmm. görünüşe göre böyle bir şey için izne sahip değilsiniz.', - "DISABLED" => "Bu hesap durduruldu. Daha çok bilgi için bizimle iletişime geçin.", + 'DISABLED' => 'Bu hesap durduruldu. Daha çok bilgi için bizimle iletişime geçin.', - "EMAIL_UPDATED" => "Hesap maili güncellendi", + 'EMAIL_UPDATED' => 'Hesap maili güncellendi', - "INVALID" => "Bu hesap bulunamadı. Silinmiş olabilir. Daha çok bilgi için bizimle iletişime geçin.", + 'INVALID' => 'Bu hesap bulunamadı. Silinmiş olabilir. Daha çok bilgi için bizimle iletişime geçin.', - "MASTER_NOT_EXISTS" => "Ana hesap oluşturuluncaya kadar bir hesap oluşturamazsın!", - "MY" => "Hesabım", + 'MASTER_NOT_EXISTS' => 'Ana hesap oluşturuluncaya kadar bir hesap oluşturamazsın!', + 'MY' => 'Hesabım', - "SESSION_COMPROMISED" => [ - "@TRANSLATION" => "Oturumunuz tehlikeye atıldı. Tüm cihazlardan çıkmanız, daha sonra giriş yapmanız ve bilgilerinizin değiştirilmediğini kontrol etmeniz gerekir.", - "TITLE" => "Hesabınız tehlikeye atılmış olabilir", - "TEXT" => "Birisi bu sayfayı ele geçirmek için giriş verilerinizi kullanmış olabilir. Güvenliğiniz için tüm oturumlar günlüğe kaydedildi. Lütfen giriş yapınve şüpheli hareketler için hesabınızı kontrol edin. Ayrıca şifrenizi değiştirmek isteyebilirsiniz." + 'SESSION_COMPROMISED' => [ + '@TRANSLATION' => 'Oturumunuz tehlikeye atıldı. Tüm cihazlardan çıkmanız, daha sonra giriş yapmanız ve bilgilerinizin değiştirilmediğini kontrol etmeniz gerekir.', + 'TITLE' => 'Hesabınız tehlikeye atılmış olabilir', + 'TEXT' => 'Birisi bu sayfayı ele geçirmek için giriş verilerinizi kullanmış olabilir. Güvenliğiniz için tüm oturumlar günlüğe kaydedildi. Lütfen giriş yapınve şüpheli hareketler için hesabınızı kontrol edin. Ayrıca şifrenizi değiştirmek isteyebilirsiniz.' ], - "SESSION_EXPIRED" => "Oturumunuz sona erdi. Lütfen tekrar oturum açın.", + 'SESSION_EXPIRED' => 'Oturumunuz sona erdi. Lütfen tekrar oturum açın.', - "SETTINGS" => [ - "@TRANSLATION" => "Hesap ayarları", - "DESCRIPTION" => "E-posta, isim ve parolanız da dahil olmak üzere hesap ayarlarınızı güncelleyin.", - "UPDATED" => "Hesap ayarları güncellendi" + 'SETTINGS' => [ + '@TRANSLATION' => 'Hesap ayarları', + 'DESCRIPTION' => 'E-posta, isim ve parolanız da dahil olmak üzere hesap ayarlarınızı güncelleyin.', + 'UPDATED' => 'Hesap ayarları güncellendi' ], - "TOOLS" => "Hesap araçları", + 'TOOLS' => 'Hesap araçları', - "UNVERIFIED" => "Hesap henüz onaylanmadı. Hesap etkinleştirme talimatları için e-postalarınızı ve spam klasörünüzü kontrol edin.", + 'UNVERIFIED' => 'Hesap henüz onaylanmadı. Hesap etkinleştirme talimatları için e-postalarınızı ve spam klasörünüzü kontrol edin.', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "{{email}} için yeni bir doğrulama bağlantısı e-posta ile gönderildi. Lütfen bu e-postanın gelen kutusunu ve spam klasörlerini kontrol edin.", - "RESEND" => "Doğrulama e-postasını tekrar gönder", - "COMPLETE" => "Hesabınızı başarıyla doğruladınız. Şimdi giriş yapabilirsiniz.", - "EMAIL" => "Kaydolmak için kullandığınız e-posta adresinizi giriniz, ve doğrulama e-postanızı tekrar gönderin.", - "PAGE" => "Yeni hesabınız için doğrulama e-postasını tekrar gönder.", - "SEND" => "Hesabım için doğrulama bağlantısını e-posta ile gönder", - "TOKEN_NOT_FOUND" => "Doğrulama belirteci bulunumadı / Hesap zaten doğrulandı", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => '{{email}} için yeni bir doğrulama bağlantısı e-posta ile gönderildi. Lütfen bu e-postanın gelen kutusunu ve spam klasörlerini kontrol edin.', + 'RESEND' => 'Doğrulama e-postasını tekrar gönder', + 'COMPLETE' => 'Hesabınızı başarıyla doğruladınız. Şimdi giriş yapabilirsiniz.', + 'EMAIL' => 'Kaydolmak için kullandığınız e-posta adresinizi giriniz, ve doğrulama e-postanızı tekrar gönderin.', + 'PAGE' => 'Yeni hesabınız için doğrulama e-postasını tekrar gönder.', + 'SEND' => 'Hesabım için doğrulama bağlantısını e-posta ile gönder', + 'TOKEN_NOT_FOUND' => 'Doğrulama belirteci bulunumadı / Hesap zaten doğrulandı', ] ], - "EMAIL" => [ - "INVALID" => "{{email}} için hesap yoktur.", - "IN_USE" => "E-posta {{email}} zaten kullanılıyor.", - "VERIFICATION_REQUIRED" => "E-posta (doğrulama gerekli - gerçek bir adres kullanın!)" + 'EMAIL' => [ + 'INVALID' => '{{email}} için hesap yoktur.', + 'IN_USE' => 'E-posta {{email}} zaten kullanılıyor.', + 'VERIFICATION_REQUIRED' => 'E-posta (doğrulama gerekli - gerçek bir adres kullanın!)' ], - "EMAIL_OR_USERNAME" => "Kullanıcı adı veya e-posta adresi", + 'EMAIL_OR_USERNAME' => 'Kullanıcı adı veya e-posta adresi', - "FIRST_NAME" => "Adınız", + 'FIRST_NAME' => 'Adınız', - "HEADER_MESSAGE_ROOT" => "Kök kullanıcı olarak giriş yaptın", + 'HEADER_MESSAGE_ROOT' => 'Kök kullanıcı olarak giriş yaptın', - "LAST_NAME" => "Soyadı", - "LOCALE" => [ - "ACCOUNT" => "Hesabınız için kullanılacak dil ve yerel ayar", - "INVALID" => "{{locale}} geçersiz bir yerel." + 'LAST_NAME' => 'Soyadı', + 'LOCALE' => [ + 'ACCOUNT' => 'Hesabınız için kullanılacak dil ve yerel ayar', + 'INVALID' => '{{locale}} geçersiz bir yerel.' ], - "LOGIN" => [ - "@TRANSLATION" => "Oturum Aç", - "ALREADY_COMPLETE" => "Zaten oturum açtınız!", - "SOCIAL" => "Veya şununla oturum aç", - "REQUIRED" => "Üzgünüm, bu sayfaya ulaşmak için oturum açmalısın." + 'LOGIN' => [ + '@TRANSLATION' => 'Oturum Aç', + 'ALREADY_COMPLETE' => 'Zaten oturum açtınız!', + 'SOCIAL' => 'Veya şununla oturum aç', + 'REQUIRED' => 'Üzgünüm, bu sayfaya ulaşmak için oturum açmalısın.' ], - "LOGOUT" => "Oturumu kapat", + 'LOGOUT' => 'Oturumu kapat', - "NAME" => "Ad", + 'NAME' => 'Ad', - "NAME_AND_EMAIL" => "Ad ve e-posta", + 'NAME_AND_EMAIL' => 'Ad ve e-posta', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "{{site_name}} hesabınız ile giriş yapın ya da yeni bir hesap oluşturun.", - "SUBTITLE" => "Ücretsiz üye ol veya mevcut bir hesap ile giriş yapın.", - "TITLE" => "Hadi başlayalım!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => '{{site_name}} hesabınız ile giriş yapın ya da yeni bir hesap oluşturun.', + 'SUBTITLE' => 'Ücretsiz üye ol veya mevcut bir hesap ile giriş yapın.', + 'TITLE' => 'Hadi başlayalım!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "Parola", + 'PASSWORD' => [ + '@TRANSLATION' => 'Parola', - "BETWEEN" => "{{min}}-{{max}} karakterler arasında", + 'BETWEEN' => '{{min}}-{{max}} karakterler arasında', - "CONFIRM" => "Şifreyi onayla", - "CONFIRM_CURRENT" => "Lütfen şuanki parolanızı giriniz", - "CONFIRM_NEW" => "Yeni parolayı onayla", - "CONFIRM_NEW_EXPLAIN" => "Yeni parolayı tekrar gir", - "CONFIRM_NEW_HELP" => "Sadece yeni bir şifre seçerseniz gerekli", - "CREATE" => [ - "@TRANSLATION" => "Parola Oluştur", - "PAGE" => "Yeni hesabınız için bir şifre belirleyin.", - "SET" => "Parolayı Ayarla ve Giriş Yap" + 'CONFIRM' => 'Şifreyi onayla', + 'CONFIRM_CURRENT' => 'Lütfen şuanki parolanızı giriniz', + 'CONFIRM_NEW' => 'Yeni parolayı onayla', + 'CONFIRM_NEW_EXPLAIN' => 'Yeni parolayı tekrar gir', + 'CONFIRM_NEW_HELP' => 'Sadece yeni bir şifre seçerseniz gerekli', + 'CREATE' => [ + '@TRANSLATION' => 'Parola Oluştur', + 'PAGE' => 'Yeni hesabınız için bir şifre belirleyin.', + 'SET' => 'Parolayı Ayarla ve Giriş Yap' ], - "CURRENT" => "Şimdiki Parola", - "CURRENT_EXPLAIN" => "Değişiklikler için şimdiki parolanız ile onaylamalısınız", - - "FORGOTTEN" => "Unutulan Şifre", - "FORGET" => [ - "@TRANSLATION" => "Şifremi unuttum", - - "COULD_NOT_UPDATE" => "Şifre güncellenemedi.", - "EMAIL" => "Lütfen kaydolmak için kullandığınız e-posta adresini giriniz. Şifrenizi sıfırlama talimatlarıyla bir bir bağlantı e-postanıza gönderilecektir.", - "EMAIL_SEND" => "E-posta şifre sıfırlama bağlantısı", - "INVALID" => "Bu şifre sıfırlama isteği bulunamadı ya da süresi bitmiş. Lütfen isteğinizi yeniden göndermeyideneyin.", - "PAGE" => "Şifrenizi sıfırlamak için bir bağlantı oluşturun.", - "REQUEST_CANNED" => "Kayıp parola isteği iptal edildi.", - "REQUEST_SENT" => "Eğer e-posta{{email}} sistemdeki bir hesap ile eşleşirse, bir şifre yenileme bağlantısı{{email}} gönderilir." + 'CURRENT' => 'Şimdiki Parola', + 'CURRENT_EXPLAIN' => 'Değişiklikler için şimdiki parolanız ile onaylamalısınız', + + 'FORGOTTEN' => 'Unutulan Şifre', + 'FORGET' => [ + '@TRANSLATION' => 'Şifremi unuttum', + + 'COULD_NOT_UPDATE' => 'Şifre güncellenemedi.', + 'EMAIL' => 'Lütfen kaydolmak için kullandığınız e-posta adresini giriniz. Şifrenizi sıfırlama talimatlarıyla bir bir bağlantı e-postanıza gönderilecektir.', + 'EMAIL_SEND' => 'E-posta şifre sıfırlama bağlantısı', + 'INVALID' => 'Bu şifre sıfırlama isteği bulunamadı ya da süresi bitmiş. Lütfen isteğinizi yeniden göndermeyideneyin.', + 'PAGE' => 'Şifrenizi sıfırlamak için bir bağlantı oluşturun.', + 'REQUEST_CANNED' => 'Kayıp parola isteği iptal edildi.', + 'REQUEST_SENT' => 'Eğer e-posta{{email}} sistemdeki bir hesap ile eşleşirse, bir şifre yenileme bağlantısı{{email}} gönderilir.' ], - "HASH_FAILED" => "Parola karma başarısız oldu. Lütfen bir site yöneticisiyle iletişime geçin.", - "INVALID" => "Şimdiki şifre kayıt edilen şifre ile eşleşmiyor", - "NEW" => "Yeni Şifre", - "NOTHING_TO_UPDATE" => "Aynı şifre ile güncelleyemezsiniz", + 'HASH_FAILED' => 'Parola karma başarısız oldu. Lütfen bir site yöneticisiyle iletişime geçin.', + 'INVALID' => 'Şimdiki şifre kayıt edilen şifre ile eşleşmiyor', + 'NEW' => 'Yeni Şifre', + 'NOTHING_TO_UPDATE' => 'Aynı şifre ile güncelleyemezsiniz', - "RESET" => [ - "@TRANSLATION" => "Şifre sıfırlama", - "CHOOSE" => "Lütfen devam etmek için yeni bir şifre belirleyiniz.", - "PAGE" => "Hesabınız için yeni bir şifre belirleyiniz.", - "SEND" => "Yeni şifre ayarla ve giriş yap" + 'RESET' => [ + '@TRANSLATION' => 'Şifre sıfırlama', + 'CHOOSE' => 'Lütfen devam etmek için yeni bir şifre belirleyiniz.', + 'PAGE' => 'Hesabınız için yeni bir şifre belirleyiniz.', + 'SEND' => 'Yeni şifre ayarla ve giriş yap' ], - "UPDATED" => "Hesap şifresi güncellendi" + 'UPDATED' => 'Hesap şifresi güncellendi' ], - "PROFILE" => [ - "SETTINGS" => "Profil ayarları", - "UPDATED" => "Profil ayarları güncellendi" + 'PROFILE' => [ + 'SETTINGS' => 'Profil ayarları', + 'UPDATED' => 'Profil ayarları güncellendi' ], - "RATE_LIMIT_EXCEEDED" => "Bu işlem için belirlenen son oran aşıldı. Başka bir deneme yapmanıza izin verilene kadar {{delay}} bir süre beklemelisiniz.", - - "REGISTER" => "Kaydol", - "REGISTER_ME" => "Beni kaydet", - "REGISTRATION" => [ - "BROKEN" => "Üzgünüz, hesap kayıt işlemimizde bir sorun var. Lütfen destek almak için doğrudan bizimle iletişime geçin.", - "COMPLETE_TYPE1" => "Kaydınız başarıyla tamamlandı. Şimdi giriş yapabilirsiniz.", - "COMPLETE_TYPE2" => "Kaydınız başarıyla tamamlandı. Hesabınızı aktifleştirmek için bir bağlantı gönderildi{{email}}. Bu adımı tamamlayana kadar oturum açamazsınız.", - "DISABLED" => "Üzgünüz, hesap kaydı devre dışı bırakıldı.", - "LOGOUT" => "Üzgünüm, oturumunuz açıkken yeni bir hesap oluşturamazsınız. Lütfen önce oturumunuzdan çıkış yapınız.", - "WELCOME" => "Kaydolmak hızlı ve basittir." + 'RATE_LIMIT_EXCEEDED' => 'Bu işlem için belirlenen son oran aşıldı. Başka bir deneme yapmanıza izin verilene kadar {{delay}} bir süre beklemelisiniz.', + + 'REGISTER' => 'Kaydol', + 'REGISTER_ME' => 'Beni kaydet', + 'REGISTRATION' => [ + 'BROKEN' => 'Üzgünüz, hesap kayıt işlemimizde bir sorun var. Lütfen destek almak için doğrudan bizimle iletişime geçin.', + 'COMPLETE_TYPE1' => 'Kaydınız başarıyla tamamlandı. Şimdi giriş yapabilirsiniz.', + 'COMPLETE_TYPE2' => 'Kaydınız başarıyla tamamlandı. Hesabınızı aktifleştirmek için bir bağlantı gönderildi{{email}}. Bu adımı tamamlayana kadar oturum açamazsınız.', + 'DISABLED' => 'Üzgünüz, hesap kaydı devre dışı bırakıldı.', + 'LOGOUT' => 'Üzgünüm, oturumunuz açıkken yeni bir hesap oluşturamazsınız. Lütfen önce oturumunuzdan çıkış yapınız.', + 'WELCOME' => 'Kaydolmak hızlı ve basittir.' ], - "REMEMBER_ME" => "Beni hatırla!", - "REMEMBER_ME_ON_COMPUTER" => "Bu bilgisayarda beni hatırla ( genel bilgisayarlar için önerilmez)", + 'REMEMBER_ME' => 'Beni hatırla!', + 'REMEMBER_ME_ON_COMPUTER' => 'Bu bilgisayarda beni hatırla ( genel bilgisayarlar için önerilmez)', - "SIGN_IN_HERE" => "Zaten bir hesaba sahip misiniz?burada giriş yap", - "SIGNIN" => "Giriş yap", - "SIGNIN_OR_REGISTER" => "Giriş yap veya kayıt ol", - "SIGNUP" => "Üye ol", + 'SIGN_IN_HERE' => 'Zaten bir hesaba sahip misiniz?burada giriş yap', + 'SIGNIN' => 'Giriş yap', + 'SIGNIN_OR_REGISTER' => 'Giriş yap veya kayıt ol', + 'SIGNUP' => 'Üye ol', - "TOS" => "Şartlar ve Koşullar", - "TOS_AGREEMENT" => "Bir hesap ile kaydolarak {{site_title}} sen kabul edersin şartlar ve koşulları.", - "TOS_FOR" => "{{title}} için şartlar ve koşullar", + 'TOS' => 'Şartlar ve Koşullar', + 'TOS_AGREEMENT' => 'Bir hesap ile kaydolarak {{site_title}} sen kabul edersin şartlar ve koşulları.', + 'TOS_FOR' => '{{title}} için şartlar ve koşullar', - "USERNAME" => [ - "@TRANSLATION" => "Kullanıcı Adı", + 'USERNAME' => [ + '@TRANSLATION' => 'Kullanıcı Adı', - "CHOOSE" => "Benzersiz bir kullanıcı adı seç", - "INVALID" => "Geçersiz kullanıcı adı", - "IN_USE" => "{{user_name}} kullanıcı adı zaten mevcut.", - "NOT_AVAILABLE" => "{{user_name}} kullanıcı adı kullanılamaz. Farklı bir isim veya 'öneriye' tıklayın." + 'CHOOSE' => 'Benzersiz bir kullanıcı adı seç', + 'INVALID' => 'Geçersiz kullanıcı adı', + 'IN_USE' => '{{user_name}} kullanıcı adı zaten mevcut.', + 'NOT_AVAILABLE' => "{{user_name}} kullanıcı adı kullanılamaz. Farklı bir isim veya 'öneriye' tıklayın." ], - "USER_ID_INVALID" => "İstenen kullanıcı adı mevcut değil.", - "USER_OR_EMAIL_INVALID" => "Kullanıcı adı veya e-posta adresi hatalı.", - "USER_OR_PASS_INVALID" => "Kullanıcı bulunamadı ya da şifre hatalı.", + 'USER_ID_INVALID' => 'İstenen kullanıcı adı mevcut değil.', + 'USER_OR_EMAIL_INVALID' => 'Kullanıcı adı veya e-posta adresi hatalı.', + 'USER_OR_PASS_INVALID' => 'Kullanıcı bulunamadı ya da şifre hatalı.', - "WELCOME" => "Tekrar Hoşgeldiniz.{{first_name}}" + 'WELCOME' => 'Tekrar Hoşgeldiniz.{{first_name}}' ]; diff --git a/app/sprinkles/account/locale/tr/validate.php b/app/sprinkles/account/locale/tr/validate.php index cd4380be4..719578c24 100644 --- a/app/sprinkles/account/locale/tr/validate.php +++ b/app/sprinkles/account/locale/tr/validate.php @@ -4,16 +4,16 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Turkish message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\tr * @author Dumblledore */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "Şifreniz ve onaylama şifreniz eşleşmiyor.", - "USERNAME" => "Kullanıcı adınız sadece küçük harfler, sayılar, '.', '-', ve '_' içerebilir." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => 'Şifreniz ve onaylama şifreniz eşleşmiyor.', + 'USERNAME' => "Kullanıcı adınız sadece küçük harfler, sayılar, '.', '-', ve '_' içerebilir." ] ]; diff --git a/app/sprinkles/account/locale/zh_CN/messages.php b/app/sprinkles/account/locale/zh_CN/messages.php index 60adcf05b..f47aba332 100644 --- a/app/sprinkles/account/locale/zh_CN/messages.php +++ b/app/sprinkles/account/locale/zh_CN/messages.php @@ -4,174 +4,174 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Chinese message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\zh_CN * @author @BruceGui (https://github.com/BruceGui) */ - return [ - "ACCOUNT" => [ - "@TRANSLATION" => "账户", + 'ACCOUNT' => [ + '@TRANSLATION' => '账户', - "ACCESS_DENIED" => "噢, 你好像没有权限这么做.", + 'ACCESS_DENIED' => '噢, 你好像没有权限这么做.', - "DISABLED" => "这个账户已被禁用. 请联系我们获取更多信息.", + 'DISABLED' => '这个账户已被禁用. 请联系我们获取更多信息.', - "EMAIL_UPDATED" => "账户邮箱更新成功", + 'EMAIL_UPDATED' => '账户邮箱更新成功', - "INVALID" => "此账户不存在. 可能已被删除. 请联系我们获取更多信息.", + 'INVALID' => '此账户不存在. 可能已被删除. 请联系我们获取更多信息.', - "MASTER_NOT_EXISTS" => "在创建超级账户之前你不能注册", - "MY" => "我的账户", + 'MASTER_NOT_EXISTS' => '在创建超级账户之前你不能注册', + 'MY' => '我的账户', - "SESSION_COMPROMISED" => "你的会话已泄露. 你应该在所有的设备上注销, 然后再登陆确保你的数据没被修改.", - "SESSION_COMPROMISED_TITLE" => "你的账户可能被盗用", - "SESSION_EXPIRED" => "会话已过期. 请重新登陆.", + 'SESSION_COMPROMISED' => '你的会话已泄露. 你应该在所有的设备上注销, 然后再登陆确保你的数据没被修改.', + 'SESSION_COMPROMISED_TITLE' => '你的账户可能被盗用', + 'SESSION_EXPIRED' => '会话已过期. 请重新登陆.', - "SETTINGS" => [ - "@TRANSLATION" => "账户设置", - "DESCRIPTION" => "更新你的账户, 包括邮箱、姓名和密码.", - "UPDATED" => "账户更新成功" + 'SETTINGS' => [ + '@TRANSLATION' => '账户设置', + 'DESCRIPTION' => '更新你的账户, 包括邮箱、姓名和密码.', + 'UPDATED' => '账户更新成功' ], - "TOOLS" => "账户工具", + 'TOOLS' => '账户工具', - "UNVERIFIED" => "你的账户还没有验证. 检查你的(垃圾)邮箱文件夹进行验证.", + 'UNVERIFIED' => '你的账户还没有验证. 检查你的(垃圾)邮箱文件夹进行验证.', - "VERIFICATION" => [ - "NEW_LINK_SENT" => "我们发送了新的验证链接 {{email}}. 请检查你的收件箱或垃圾邮件进行验证.", - "RESEND" => "重新发送验证邮件", - "COMPLETE" => "你已成功验证. 现在可以登陆了.", - "EMAIL" => "请输入你登陆时的邮箱, 然后将会发送验证邮件.", - "PAGE" => "重新发送验证邮件给你的新账户.", - "SEND" => "为我的账户发送验证邮件", - "TOKEN_NOT_FOUND" => "验证令牌不存在 / 账户已经验证", + 'VERIFICATION' => [ + 'NEW_LINK_SENT' => '我们发送了新的验证链接 {{email}}. 请检查你的收件箱或垃圾邮件进行验证.', + 'RESEND' => '重新发送验证邮件', + 'COMPLETE' => '你已成功验证. 现在可以登陆了.', + 'EMAIL' => '请输入你登陆时的邮箱, 然后将会发送验证邮件.', + 'PAGE' => '重新发送验证邮件给你的新账户.', + 'SEND' => '为我的账户发送验证邮件', + 'TOKEN_NOT_FOUND' => '验证令牌不存在 / 账户已经验证', ] ], - "EMAIL" => [ - "INVALID" => "{{email}} 没有账户注册.", - "IN_USE" => "邮箱 {{email}} 已被使用.", - "VERIFICATION_REQUIRED" => "邮箱 (需要进行验证 - 请使用一个有效的!)" + 'EMAIL' => [ + 'INVALID' => '{{email}} 没有账户注册.', + 'IN_USE' => '邮箱 {{email}} 已被使用.', + 'VERIFICATION_REQUIRED' => '邮箱 (需要进行验证 - 请使用一个有效的!)' ], - "EMAIL_OR_USERNAME" => "用户名或邮箱地址", + 'EMAIL_OR_USERNAME' => '用户名或邮箱地址', - "FIRST_NAME" => "名字", + 'FIRST_NAME' => '名字', - "HEADER_MESSAGE_ROOT" => "你现在以超级用户登陆", + 'HEADER_MESSAGE_ROOT' => '你现在以超级用户登陆', - "LAST_NAME" => "姓氏", + 'LAST_NAME' => '姓氏', - "LOCALE" => [ - "ACCOUNT" => "设置你账户的地区和语言", - "INVALID" => "{{locale}} 不是一个有效的地区." + 'LOCALE' => [ + 'ACCOUNT' => '设置你账户的地区和语言', + 'INVALID' => '{{locale}} 不是一个有效的地区.' ], - "LOGIN" => [ - "@TRANSLATION" => "登陆", - "ALREADY_COMPLETE" => "你已经登陆!", - "SOCIAL" => "用其他方式登陆", - "REQUIRED" => "对不起, 你需要登陆才能获取资源." + 'LOGIN' => [ + '@TRANSLATION' => '登陆', + 'ALREADY_COMPLETE' => '你已经登陆!', + 'SOCIAL' => '用其他方式登陆', + 'REQUIRED' => '对不起, 你需要登陆才能获取资源.' ], - "LOGOUT" => "注销", + 'LOGOUT' => '注销', - "NAME" => "名字", + 'NAME' => '名字', - "NAME_AND_EMAIL" => "名字和邮箱", + 'NAME_AND_EMAIL' => '名字和邮箱', - "PAGE" => [ - "LOGIN" => [ - "DESCRIPTION" => "用 {{site_name}} 账户登陆, 或者创建新账户.", - "SUBTITLE" => "免费注册, 或用已有账户登陆.", - "TITLE" => "让我们开始吧!", + 'PAGE' => [ + 'LOGIN' => [ + 'DESCRIPTION' => '用 {{site_name}} 账户登陆, 或者创建新账户.', + 'SUBTITLE' => '免费注册, 或用已有账户登陆.', + 'TITLE' => '让我们开始吧!', ] ], - "PASSWORD" => [ - "@TRANSLATION" => "密码", - - "BETWEEN" => "字符长度 {{min}}-{{max}} ", - - "CONFIRM" => "确认密码", - "CONFIRM_CURRENT" => "请确认当前密码", - "CONFIRM_NEW" => "确认新密码", - "CONFIRM_NEW_EXPLAIN" => "重新输入新密码", - "CONFIRM_NEW_HELP" => "选择了新密码时才需要", - "CURRENT" => "密码正确", - "CURRENT_EXPLAIN" => "你必须要确认密码再进行修改", - - "FORGOTTEN" => "忘记密码", - "FORGET" => [ - "@TRANSLATION" => "我忘记了密码", - - "COULD_NOT_UPDATE" => "无法更新密码.", - "EMAIL" => "请输入你登陆时的邮箱. 重置密码的链接将会发送给你.", - "EMAIL_SEND" => "发送重置密码链接", - "INVALID" => "这个重置密码请求无法使用, 或已过期. 请 重新发送请求.", - "PAGE" => "获取重置密码的链接.", - "REQUEST_CANNED" => "取消重置请求.", - "REQUEST_SENT" => "重置密码的链接已经发送 {{email}}." + 'PASSWORD' => [ + '@TRANSLATION' => '密码', + + 'BETWEEN' => '字符长度 {{min}}-{{max}} ', + + 'CONFIRM' => '确认密码', + 'CONFIRM_CURRENT' => '请确认当前密码', + 'CONFIRM_NEW' => '确认新密码', + 'CONFIRM_NEW_EXPLAIN' => '重新输入新密码', + 'CONFIRM_NEW_HELP' => '选择了新密码时才需要', + 'CURRENT' => '密码正确', + 'CURRENT_EXPLAIN' => '你必须要确认密码再进行修改', + + 'FORGOTTEN' => '忘记密码', + 'FORGET' => [ + '@TRANSLATION' => '我忘记了密码', + + 'COULD_NOT_UPDATE' => '无法更新密码.', + 'EMAIL' => '请输入你登陆时的邮箱. 重置密码的链接将会发送给你.', + 'EMAIL_SEND' => '发送重置密码链接', + 'INVALID' => '这个重置密码请求无法使用, 或已过期. 请 重新发送请求.', + 'PAGE' => '获取重置密码的链接.', + 'REQUEST_CANNED' => '取消重置请求.', + 'REQUEST_SENT' => '重置密码的链接已经发送 {{email}}.' ], - "RESET" => [ - "@TRANSLATION" => "重置密码", - "CHOOSE" => "请输入新密码.", - "PAGE" => "为账户设置新密码.", - "SEND" => "设置密码并登陆" + 'RESET' => [ + '@TRANSLATION' => '重置密码', + 'CHOOSE' => '请输入新密码.', + 'PAGE' => '为账户设置新密码.', + 'SEND' => '设置密码并登陆' ], - "HASH_FAILED" => "密码验证失败. 请联系网站管理.", - "INVALID" => "当前密码无法与记录匹配", - "NEW" => "新密码", - "NOTHING_TO_UPDATE" => "新密码不能与旧密码相同", - "UPDATED" => "账户密码更新成功" + 'HASH_FAILED' => '密码验证失败. 请联系网站管理.', + 'INVALID' => '当前密码无法与记录匹配', + 'NEW' => '新密码', + 'NOTHING_TO_UPDATE' => '新密码不能与旧密码相同', + 'UPDATED' => '账户密码更新成功' ], - "PROFILE" => [ - "SETTINGS" => "简介设置", - "UPDATED" => "简介设置成功" + 'PROFILE' => [ + 'SETTINGS' => '简介设置', + 'UPDATED' => '简介设置成功' ], - "REGISTER" => "注册", - "REGISTER_ME" => "注册", + 'REGISTER' => '注册', + 'REGISTER_ME' => '注册', - "REGISTRATION" => [ - "BROKEN" => "抱歉, 账户注册过程发送错误. 请联系我们寻求帮助.", - "COMPLETE_TYPE1" => "你已注册成功. 现在可以登陆了.", - "COMPLETE_TYPE2" => "成功注册. 激活链接已经发送给 {{email}}. 激活之前无法登陆.", - "DISABLED" => "抱歉, 账户注册以禁用.", - "LOGOUT" => "抱歉, 登陆时不能注册. 请先注销.", - "WELCOME" => "注册简单快速." + 'REGISTRATION' => [ + 'BROKEN' => '抱歉, 账户注册过程发送错误. 请联系我们寻求帮助.', + 'COMPLETE_TYPE1' => '你已注册成功. 现在可以登陆了.', + 'COMPLETE_TYPE2' => '成功注册. 激活链接已经发送给 {{email}}. 激活之前无法登陆.', + 'DISABLED' => '抱歉, 账户注册以禁用.', + 'LOGOUT' => '抱歉, 登陆时不能注册. 请先注销.', + 'WELCOME' => '注册简单快速.' ], - "RATE_LIMIT_EXCEEDED" => "行动速度过快. 请等 {{delay}} 秒后再尝试新的操作.", - "REMEMBER_ME" => "记住我!", - "REMEMBER_ME_ON_COMPUTER" => "在此电脑上记住我 (不推荐在公共电脑上)", + 'RATE_LIMIT_EXCEEDED' => '行动速度过快. 请等 {{delay}} 秒后再尝试新的操作.', + 'REMEMBER_ME' => '记住我!', + 'REMEMBER_ME_ON_COMPUTER' => '在此电脑上记住我 (不推荐在公共电脑上)', - "SIGNIN" => "登陆", - "SIGNIN_OR_REGISTER" => "登陆或注册", - "SIGNUP" => "注销", + 'SIGNIN' => '登陆', + 'SIGNIN_OR_REGISTER' => '登陆或注册', + 'SIGNUP' => '注销', - "TOS" => "条款和说明", - "TOS_AGREEMENT" => "在 {{site_title}} 注册, 你需要接收 条款和说明.", - "TOS_FOR" => "{{title}}的条款和说明", + 'TOS' => '条款和说明', + 'TOS_AGREEMENT' => '在 {{site_title}} 注册, 你需要接收 条款和说明.', + 'TOS_FOR' => '{{title}}的条款和说明', - "USERNAME" => [ - "@TRANSLATION" => "用户名", + 'USERNAME' => [ + '@TRANSLATION' => '用户名', - "CHOOSE" => "取一个唯一的用户名", - "INVALID" => "无效的用户名", - "IN_USE" => "用户名 {{user_name}} 已存在.", - "NOT_AVAILABLE" => "用户名 {{user_name}} 不可用. 重新选择用户名, 或者点击 '建议'." + 'CHOOSE' => '取一个唯一的用户名', + 'INVALID' => '无效的用户名', + 'IN_USE' => '用户名 {{user_name}} 已存在.', + 'NOT_AVAILABLE' => "用户名 {{user_name}} 不可用. 重新选择用户名, 或者点击 '建议'." ], - "USER_ID_INVALID" => "请求的用户不存在.", - "USER_OR_EMAIL_INVALID" => "用户名或邮箱无效.", - "USER_OR_PASS_INVALID" => "没有发现用户或密码错误.", + 'USER_ID_INVALID' => '请求的用户不存在.', + 'USER_OR_EMAIL_INVALID' => '用户名或邮箱无效.', + 'USER_OR_PASS_INVALID' => '没有发现用户或密码错误.', - "WELCOME" => "欢迎回来, {{first_name}}" + 'WELCOME' => '欢迎回来, {{first_name}}' ]; diff --git a/app/sprinkles/account/locale/zh_CN/validate.php b/app/sprinkles/account/locale/zh_CN/validate.php index db58c06cf..2e7969c74 100644 --- a/app/sprinkles/account/locale/zh_CN/validate.php +++ b/app/sprinkles/account/locale/zh_CN/validate.php @@ -4,16 +4,16 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Chinese message token translations for the 'account' sprinkle. * - * @package userfrosting\i18n\zh_CN * @author @BruceGui (https://github.com/BruceGui) */ - return [ - "VALIDATE" => [ - "PASSWORD_MISMATCH" => "密码不一致.", - "USERNAME" => "用户名必须以小写字母, 数字, '.', '-', 和 '_'组成." + 'VALIDATE' => [ + 'PASSWORD_MISMATCH' => '密码不一致.', + 'USERNAME' => "用户名必须以小写字母, 数字, '.', '-', 和 '_'组成." ] ]; diff --git a/app/sprinkles/account/routes/routes.php b/app/sprinkles/account/routes/routes.php index 8198255e0..617fed20c 100644 --- a/app/sprinkles/account/routes/routes.php +++ b/app/sprinkles/account/routes/routes.php @@ -5,7 +5,6 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ - $app->group('/account', function () { $this->get('/captcha', 'UserFrosting\Sprinkle\Account\Controller\AccountController:imageCaptcha'); diff --git a/app/sprinkles/account/src/Account.php b/app/sprinkles/account/src/Account.php index 99cc8894e..237790a4e 100644 --- a/app/sprinkles/account/src/Account.php +++ b/app/sprinkles/account/src/Account.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account; use UserFrosting\System\Sprinkle\Sprinkle; diff --git a/app/sprinkles/account/src/Account/Registration.php b/app/sprinkles/account/src/Account/Registration.php index acf183da0..f66e7097e 100644 --- a/app/sprinkles/account/src/Account/Registration.php +++ b/app/sprinkles/account/src/Account/Registration.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Account; use Illuminate\Database\Capsule\Manager as Capsule; @@ -118,7 +119,7 @@ public function register() // Create activity record $this->ci->userActivityLogger->info("User {$user->user_name} registered for a new account.", [ - 'type' => 'sign_up', + 'type' => 'sign_up', 'user_id' => $user->id ]); @@ -144,7 +145,7 @@ public function register() * Validate the user name and email is unique * * @throws HttpException If data doesn't validate - * @return bool Returns true if the data is valid + * @return bool Returns true if the data is valid */ public function validate() { @@ -182,7 +183,7 @@ public function validate() * Make sure the username is not already in use * * @param string $username - * @return bool Return true if username is unique + * @return bool Return true if username is unique */ public function usernameIsUnique($username) { @@ -194,7 +195,7 @@ public function usernameIsUnique($username) * Make sure the email is not already in use * * @param string $email - * @return bool Return true if email is unique + * @return bool Return true if email is unique */ public function emailIsUnique($email) { @@ -223,7 +224,7 @@ protected function setDefaults() /** * Send verification email for specified user * - * @param UserInterface $user The user to send the email for + * @param UserInterface $user The user to send the email for */ protected function sendVerificationEmail(UserInterface $user) { @@ -236,7 +237,7 @@ protected function sendVerificationEmail(UserInterface $user) $message->from($this->ci->config['address_book.admin']) ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) ->addParams([ - 'user' => $user, + 'user' => $user, 'token' => $verification->getToken() ]); @@ -252,12 +253,13 @@ public function getRequireEmailVerification() } /** - * @param bool $requireEmailVerification + * @param bool $requireEmailVerification * @return static */ public function setRequireEmailVerification($requireEmailVerification) { $this->requireEmailVerification = $requireEmailVerification; + return $this; } @@ -270,12 +272,13 @@ public function getDefaultGroup() } /** - * @param string $defaultGroup + * @param string $defaultGroup * @return static */ public function setDefaultGroup($defaultGroup) { $this->defaultGroup = $defaultGroup; + return $this; } @@ -288,12 +291,13 @@ public function getDefaultRoles() } /** - * @param array $defaultRoles + * @param array $defaultRoles * @return static */ public function setDefaultRoles($defaultRoles) { $this->defaultRoles = $defaultRoles; + return $this; } @@ -313,6 +317,7 @@ public function getUserdata() public function setUserdata($userdata) { $this->userdata = $userdata; + return $this; } @@ -320,7 +325,7 @@ public function setUserdata($userdata) * Define a user property * * @param string $property The property to set - * @param mixed $value The property value + * @param mixed $value The property value */ public function setUserProperty($property, $value) { diff --git a/app/sprinkles/account/src/Authenticate/AuthGuard.php b/app/sprinkles/account/src/Authenticate/AuthGuard.php index 1db38ddd1..00921611f 100644 --- a/app/sprinkles/account/src/Authenticate/AuthGuard.php +++ b/app/sprinkles/account/src/Authenticate/AuthGuard.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate; use Psr\Http\Message\ServerRequestInterface as Request; diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index d3e15a539..a7aff94ee 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate; use Birke\Rememberme\Authenticator as RememberMe; @@ -83,9 +84,9 @@ class Authenticator * Create a new Authenticator object. * * @param ClassMapper $classMapper Maps generic class identifiers to specific class names. - * @param Session $session The session wrapper object that will store the user's id. - * @param Config $config Config object that contains authentication settings. - * @param Cache $cache Cache service instance + * @param Session $session The session wrapper object that will store the user's id. + * @param Config $config Config object that contains authentication settings. + * @param Cache $cache Cache service instance */ public function __construct(ClassMapper $classMapper, Session $session, Config $config, Cache $cache) { @@ -126,13 +127,13 @@ public function __construct(ClassMapper $classMapper, Session $session, Config $ * * If successful, the user's id is stored in session. * + * @param string $identityColumn + * @param string $identityValue + * @param string $password + * @param bool $rememberMe * @throws InvalidCredentialsException * @throws AccountDisabledException * @throws AccountNotVerifiedException - * @param string $identityColumn - * @param string $identityValue - * @param string $password - * @param bool $rememberMe * @return UserInterface */ public function attempt($identityColumn, $identityValue, $password, $rememberMe = false) @@ -162,6 +163,7 @@ public function attempt($identityColumn, $identityValue, $password, $rememberMe // Here is my password. May I please assume the identify of this user now? if (Password::verify($password, $user->password)) { $this->login($user, $rememberMe); + return $user; } else { // We know the password is at fault here (as opposed to the identity), but lets not give away the combination in case of someone bruteforcing @@ -193,8 +195,8 @@ public function guest() * Process an account login request. * * This method logs in the specified user, allowing the client to assume the user's identity for the duration of the session. - * @param UserInterface $user The user to log in. - * @param bool $rememberMe Set to true to make this a "persistent session", i.e. one that will re-login even after the session expires. + * @param UserInterface $user The user to log in. + * @param bool $rememberMe Set to true to make this a "persistent session", i.e. one that will re-login even after the session expires. * @todo Figure out a way to update the currentUser service to reflect the logged-in user *immediately* in the service provider. * As it stands, the currentUser service will still reflect a "guest user" for the remainder of the request. */ @@ -272,11 +274,11 @@ public function logout($complete = false) * Try to get the currently authenticated user, returning a guest user if none was found. * * Tries to re-establish a session for "remember-me" users who have been logged out due to an expired session. - * @return UserInterface|null * @throws AuthExpiredException * @throws AuthCompromisedException * @throws AccountInvalidException * @throws AccountDisabledException + * @return UserInterface|null */ public function user() { @@ -323,7 +325,7 @@ public function viaRemember() * Attempt to log in the client from their rememberMe token (in their cookie). * * @throws AuthCompromisedException The client attempted to log in with an invalid rememberMe token. - * @return UserInterface|bool If successful, the User object of the remembered user. Otherwise, return false. + * @return UserInterface|bool If successful, the User object of the remembered user. Otherwise, return false. */ protected function loginRememberedUser() { @@ -350,7 +352,7 @@ protected function loginRememberedUser() * Attempt to log in the client from the session. * * @throws AuthExpiredException The client attempted to use an expired rememberMe token. - * @return UserInterface|null If successful, the User object of the user in session. Otherwise, return null. + * @return UserInterface|null If successful, the User object of the user in session. Otherwise, return null. */ protected function loginSessionUser() { @@ -391,10 +393,10 @@ protected function validateRememberMeCookie() * Tries to load the specified user by id from the database. * * Checks that the account is valid and enabled, throwing an exception if not. - * @param int $userId - * @return UserInterface|null + * @param int $userId * @throws AccountInvalidException * @throws AccountDisabledException + * @return UserInterface|null */ protected function validateUserAccount($userId) { @@ -413,7 +415,7 @@ protected function validateUserAccount($userId) return $user; } else { - return null; + return; } } diff --git a/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php b/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php index e79ceb573..3ad4c5999 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; use UserFrosting\Support\Exception\HttpException; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php b/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php index 607235b54..fb06fae41 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; use UserFrosting\Support\Exception\HttpException; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php b/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php index 7eb56a66d..2a721bb17 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; use UserFrosting\Support\Exception\HttpException; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php b/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php index df3efbeae..52fd5287a 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; use UserFrosting\Support\Exception\ForbiddenException; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php b/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php index 558374661..ab7cbdb90 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; use UserFrosting\Support\Exception\HttpException; diff --git a/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php b/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php index 18d4a5c73..78ea3de03 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; use UserFrosting\Support\Exception\HttpException; diff --git a/app/sprinkles/account/src/Authenticate/Hasher.php b/app/sprinkles/account/src/Authenticate/Hasher.php index 25a09ed48..d03747e22 100644 --- a/app/sprinkles/account/src/Authenticate/Hasher.php +++ b/app/sprinkles/account/src/Authenticate/Hasher.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authenticate; use UserFrosting\Sprinkle\Account\Util\HashFailedException; @@ -27,7 +28,7 @@ class Hasher * Returns the hashing type for a specified password hash. * * Automatically detects the hash type: "sha1" (for UserCake legacy accounts), "legacy" (for 0.1.x accounts), and "modern" (used for new accounts). - * @param string $password the hashed password. + * @param string $password the hashed password. * @return string "sha1"|"legacy"|"modern". */ public function getHashType($password) @@ -45,10 +46,10 @@ public function getHashType($password) /** * Hashes a plaintext password using bcrypt. * + * @param string $password the plaintext password. + * @param array $options * @throws HashFailedException - * @param string $password the plaintext password. - * @param array $options - * @return string the hashed password. + * @return string the hashed password. */ public function hash($password, array $options = []) { @@ -66,10 +67,10 @@ public function hash($password, array $options = []) /** * Verify a plaintext password against the user's hashed password. * - * @param string $password The plaintext password to verify. - * @param string $hash The hash to compare against. - * @param array $options - * @return bool True if the password matches, false otherwise. + * @param string $password The plaintext password to verify. + * @param string $hash The hash to compare against. + * @param array $options + * @return bool True if the password matches, false otherwise. */ public function verify($password, $hash, array $options = []) { @@ -80,7 +81,7 @@ public function verify($password, $hash, array $options = []) $salt = substr($hash, 0, 25); // Extract the salt from the hash $inputHash = $salt . sha1($salt . $password); - return (hash_equals($inputHash, $hash) === true); + return hash_equals($inputHash, $hash) === true; } elseif ($hashType == 'legacy') { // Homegrown implementation (assuming that current install has been using a cost parameter of 12) // Used for manual implementation of bcrypt. @@ -89,7 +90,7 @@ public function verify($password, $hash, array $options = []) $inputHash = crypt($password, '$2y$12$' . $salt); $correctHash = substr($hash, 0, 60); - return (hash_equals($inputHash, $correctHash) === true); + return hash_equals($inputHash, $correctHash) === true; } // Modern implementation @@ -99,7 +100,7 @@ public function verify($password, $hash, array $options = []) /** * Extract the cost value from the options array. * - * @param array $options + * @param array $options * @return int */ protected function cost(array $options = []) diff --git a/app/sprinkles/account/src/Authorize/AccessConditionExpression.php b/app/sprinkles/account/src/Authorize/AccessConditionExpression.php index 6378d271c..55b6090a6 100644 --- a/app/sprinkles/account/src/Authorize/AccessConditionExpression.php +++ b/app/sprinkles/account/src/Authorize/AccessConditionExpression.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authorize; use Monolog\Logger; @@ -64,19 +65,19 @@ class AccessConditionExpression * Create a new AccessConditionExpression object. * * @param ParserNodeFunctionEvaluator $nodeVisitor - * @param UserInterface $user A user object, which for convenience can be referenced as 'self' in access conditions. - * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. - * @param bool $debug Set to true if you want debugging information printed to the auth log. + * @param UserInterface $user A user object, which for convenience can be referenced as 'self' in access conditions. + * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. + * @param bool $debug Set to true if you want debugging information printed to the auth log. */ public function __construct(ParserNodeFunctionEvaluator $nodeVisitor, UserInterface $user, Logger $logger, $debug = false) { - $this->nodeVisitor = $nodeVisitor; - $this->user = $user; - $this->parser = new Parser(new EmulativeLexer); - $this->traverser = new NodeTraverser; + $this->nodeVisitor = $nodeVisitor; + $this->user = $user; + $this->parser = new Parser(new EmulativeLexer()); + $this->traverser = new NodeTraverser(); $this->traverser->addVisitor($nodeVisitor); - $this->prettyPrinter = new StandardPrettyPrinter; - $this->logger = $logger; + $this->prettyPrinter = new StandardPrettyPrinter(); + $this->logger = $logger; $this->debug = $debug; } @@ -85,9 +86,9 @@ public function __construct(ParserNodeFunctionEvaluator $nodeVisitor, UserInterf * * The special parameter `self` is an array of the current user's data. * This get included automatically, and so does not need to be passed in. - * @param string $condition a boolean expression composed of calls to AccessCondition functions. - * @param array[mixed] $params the parameters to be used when evaluating the expression. - * @return bool true if the condition is passed for the given parameters, otherwise returns false. + * @param string $condition a boolean expression composed of calls to AccessCondition functions. + * @param array[mixed] $params the parameters to be used when evaluating the expression. + * @return bool true if the condition is passed for the given parameters, otherwise returns false. */ public function evaluateCondition($condition, $params) { @@ -115,11 +116,11 @@ public function evaluateCondition($condition, $params) // Evaluate boolean statement. It is safe to use eval() here, because our expression has been reduced entirely to a boolean expression. $expr = $this->prettyPrinter->prettyPrintExpr($stmts[0]); - $expr_eval = "return " . $expr . ";\n"; + $expr_eval = 'return ' . $expr . ";\n"; $result = eval($expr_eval); if ($this->debug) { - $this->logger->debug("Expression '$expr' evaluates to " . ($result == true ? "true" : "false")); + $this->logger->debug("Expression '$expr' evaluates to " . ($result == true ? 'true' : 'false')); } return $result; @@ -127,11 +128,13 @@ public function evaluateCondition($condition, $params) if ($this->debug) { $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage()); } + return false; // Access fails if the access condition can't be parsed. } catch (AuthorizationException $e) { if ($this->debug) { $this->logger->debug("Error parsing access condition '$condition':" . $e->getMessage()); } + return false; } } diff --git a/app/sprinkles/account/src/Authorize/AuthorizationException.php b/app/sprinkles/account/src/Authorize/AuthorizationException.php index 8e4d90708..a3341febc 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationException.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authorize; use UserFrosting\Support\Exception\ForbiddenException; diff --git a/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/app/sprinkles/account/src/Authorize/AuthorizationManager.php index 65bea8305..9d5b8bd37 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationManager.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authorize; use Interop\Container\ContainerInterface; @@ -31,8 +32,8 @@ class AuthorizationManager /** * Create a new AuthorizationManager object. * - * @param ContainerInterface $ci The global container object, which holds all your services. - * @param array $callbacks + * @param ContainerInterface $ci The global container object, which holds all your services. + * @param array $callbacks */ public function __construct(ContainerInterface $ci, array $callbacks = []) { @@ -44,12 +45,13 @@ public function __construct(ContainerInterface $ci, array $callbacks = []) * Register an authorization callback, which can then be used in permission conditions. * * To add additional callbacks, simply extend the `authorizer` service in your Sprinkle's service provider. - * @param string $name + * @param string $name * @param callable $callback */ public function addCallback($name, $callback) { $this->callbacks[$name] = $callback; + return $this; } @@ -68,11 +70,11 @@ public function getCallbacks() * * Determine if this user has access to the given $slug under the given $params. * - * @param UserInterface|null $user - * @param string $slug The permission slug to check for access. - * @param array $params An array of field names => values, specifying any additional data to provide the authorization module - * when determining whether or not this user has access. - * @return bool True if the user has access, false otherwise. + * @param UserInterface|null $user + * @param string $slug The permission slug to check for access. + * @param array $params An array of field names => values, specifying any additional data to provide the authorization module + * when determining whether or not this user has access. + * @return bool True if the user has access, false otherwise. */ public function checkAccess($user, $slug, array $params = []) { @@ -80,14 +82,15 @@ public function checkAccess($user, $slug, array $params = []) if (is_null($user) || !($user instanceof UserInterface)) { if ($debug) { - $this->ci->authLogger->debug("No user defined. Access denied."); + $this->ci->authLogger->debug('No user defined. Access denied.'); } + return false; } if ($debug) { $trace = array_slice(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), 1); - $this->ci->authLogger->debug("Authorization check requested at: ", $trace); + $this->ci->authLogger->debug('Authorization check requested at: ', $trace); $this->ci->authLogger->debug("Checking authorization for user {$user->id} ('{$user->user_name}') on permission '$slug'..."); } @@ -95,8 +98,9 @@ public function checkAccess($user, $slug, array $params = []) // Need to use loose comparison for now, because some DBs return `id` as a string. if ($user->id == $this->ci->config['reserved_user_ids.master']) { if ($debug) { - $this->ci->authLogger->debug("User is the master (root) user. Access granted."); + $this->ci->authLogger->debug('User is the master (root) user. Access granted.'); } + return true; } @@ -105,8 +109,9 @@ public function checkAccess($user, $slug, array $params = []) if (empty($permissions) || !isset($permissions[$slug])) { if ($debug) { - $this->ci->authLogger->debug("No matching permissions found. Access denied."); + $this->ci->authLogger->debug('No matching permissions found. Access denied.'); } + return false; } @@ -125,12 +130,13 @@ public function checkAccess($user, $slug, array $params = []) if ($debug) { $this->ci->authLogger->debug("User passed conditions '{$permission->conditions}'. Access granted."); } + return true; } } if ($debug) { - $this->ci->authLogger->debug("User failed to pass any of the matched permissions. Access denied."); + $this->ci->authLogger->debug('User failed to pass any of the matched permissions. Access denied.'); } return false; diff --git a/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php b/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php index b7244c1ce..76c79a99f 100644 --- a/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php +++ b/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Authorize; use Monolog\Logger; @@ -22,7 +23,6 @@ */ class ParserNodeFunctionEvaluator extends NodeVisitorAbstract { - /** * @var array[callable] An array of callback functions to be used when evaluating a condition expression. */ @@ -51,15 +51,15 @@ class ParserNodeFunctionEvaluator extends NodeVisitorAbstract /** * Create a new ParserNodeFunctionEvaluator object. * - * @param array $callbacks The parameters to be used when evaluating the methods in the condition expression, as an array. - * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. - * @param bool $debug Set to true if you want debugging information printed to the auth log. + * @param array $callbacks The parameters to be used when evaluating the methods in the condition expression, as an array. + * @param Logger $logger A Monolog logger, used to dump debugging info for authorization evaluations. + * @param bool $debug Set to true if you want debugging information printed to the auth log. */ public function __construct($callbacks, Logger $logger, $debug = false) { $this->callbacks = $callbacks; - $this->prettyPrinter = new StandardPrettyPrinter; - $this->logger = $logger; + $this->prettyPrinter = new StandardPrettyPrinter(); + $this->logger = $logger; $this->debug = $debug; $this->params = []; } @@ -68,7 +68,7 @@ public function leaveNode(Node $node) { // Look for function calls if ($node instanceof \PhpParser\Node\Expr\FuncCall) { - $eval = new \PhpParser\Node\Scalar\LNumber; + $eval = new \PhpParser\Node\Scalar\LNumber(); // Get the method name $callbackName = $node->name->toString(); @@ -87,31 +87,31 @@ public function leaveNode(Node $node) // Resolve parameter placeholders ('variable' names (either single-word or array-dot identifiers)) if (($arg->value instanceof \PhpParser\Node\Expr\BinaryOp\Concat) || ($arg->value instanceof \PhpParser\Node\Expr\ConstFetch)) { $value = $this->resolveParamPath($argString); - $currentArgInfo['type'] = "parameter"; + $currentArgInfo['type'] = 'parameter'; $currentArgInfo['resolved_value'] = $value; // Resolve arrays } elseif ($arg->value instanceof \PhpParser\Node\Expr\Array_) { $value = $this->resolveArray($arg); - $currentArgInfo['type'] = "array"; + $currentArgInfo['type'] = 'array'; $currentArgInfo['resolved_value'] = print_r($value, true); // Resolve strings } elseif ($arg->value instanceof \PhpParser\Node\Scalar\String_) { $value = $arg->value->value; - $currentArgInfo['type'] = "string"; + $currentArgInfo['type'] = 'string'; $currentArgInfo['resolved_value'] = $value; // Resolve numbers } elseif ($arg->value instanceof \PhpParser\Node\Scalar\DNumber) { $value = $arg->value->value; - $currentArgInfo['type'] = "float"; + $currentArgInfo['type'] = 'float'; $currentArgInfo['resolved_value'] = $value; } elseif ($arg->value instanceof \PhpParser\Node\Scalar\LNumber) { $value = $arg->value->value; - $currentArgInfo['type'] = "integer"; + $currentArgInfo['type'] = 'integer'; $currentArgInfo['resolved_value'] = $value; // Anything else is simply interpreted as its literal string value } else { $value = $argString; - $currentArgInfo['type'] = "unknown"; + $currentArgInfo['type'] = 'unknown'; $currentArgInfo['resolved_value'] = $value; } @@ -135,10 +135,10 @@ public function leaveNode(Node $node) } if ($this->debug) { - $this->logger->debug("Result: " . ($result ? "1" : "0")); + $this->logger->debug('Result: ' . ($result ? '1' : '0')); } - return new \PhpParser\Node\Scalar\LNumber($result ? "1" : "0"); + return new \PhpParser\Node\Scalar\LNumber($result ? '1' : '0'); } } @@ -155,7 +155,7 @@ public function setParams($params) /** * Resolve an array expression in a condition expression into an actual array. * - * @param string $arg the array, represented as a string. + * @param string $arg the array, represented as a string. * @return array[mixed] the array, as a plain ol' PHP array. */ private function resolveArray($arg) @@ -169,19 +169,20 @@ private function resolveArray($arg) $arr[] = $item->value->value; } } + return $arr; } /** * Resolve a parameter path (e.g. "user.id", "post", etc) into its value. * - * @param string $path the name of the parameter to resolve, based on the parameters set in this object. + * @param string $path the name of the parameter to resolve, based on the parameters set in this object. * @throws \Exception the path could not be resolved. Path is malformed or key does not exist. - * @return mixed the value of the specified parameter. + * @return mixed the value of the specified parameter. */ private function resolveParamPath($path) { - $pathTokens = explode(".", $path); + $pathTokens = explode('.', $path); $value = $this->params; foreach ($pathTokens as $token) { $token = trim($token); @@ -195,6 +196,7 @@ private function resolveParamPath($path) throw new AuthorizationException("Cannot resolve the path \"$path\". Error at token \"$token\"."); } } + return $value; } } diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index a88934aff..2a804b094 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Bakery; use Symfony\Component\Console\Input\InputInterface; @@ -136,20 +137,22 @@ protected function askUsername($username = '') while (!isset($username) || !$this->validateUsername($username)) { $username = $this->io->ask('Choose a root username (1-50 characters, no leading or trailing whitespace)'); } + return $username; } /** * Validate the username. * - * @param string $username The input - * @return bool Is the username validated ? + * @param string $username The input + * @return bool Is the username validated ? */ protected function validateUsername($username) { // Validate length if (strlen($username) < 1 || strlen($username) > 50) { $this->io->error('Username must be between 1-50 characters'); + return false; } @@ -162,6 +165,7 @@ protected function validateUsername($username) $validate = filter_var($username, FILTER_VALIDATE_REGEXP, $options); if (!$validate) { $this->io->error("Username can't have any leading or trailing whitespace"); + return false; } @@ -179,26 +183,29 @@ protected function askEmail($email = '') while (!isset($email) || !$this->validateEmail($email)) { $email = $this->io->ask('Enter a valid email address (1-254 characters, must be compatible with FILTER_VALIDATE_EMAIL)'); } + return $email; } /** * Validate the email. * - * @param string $email The input - * @return bool Is the email validated ? + * @param string $email The input + * @return bool Is the email validated ? */ protected function validateEmail($email) { // Validate length if (strlen($email) < 1 || strlen($email) > 254) { $this->io->error('Email must be between 1-254 characters'); + return false; } // Validate format if (!filter_var($email, FILTER_VALIDATE_EMAIL)) { $this->io->error('Email must be compatible with FILTER_VALIDATE_EMAIL'); + return false; } @@ -216,20 +223,22 @@ protected function askFirstName($firstName = '') while (!isset($firstName) || !$this->validateFirstName($firstName)) { $firstName = $this->io->ask('Enter the user first name (1-20 characters)'); } + return $firstName; } /** * Validate the first name * - * @param string $firstName The input - * @return bool Is the input validated ? + * @param string $firstName The input + * @return bool Is the input validated ? */ protected function validateFirstName($firstName) { // Validate length if (strlen($firstName) < 1 || strlen($firstName) > 20) { $this->io->error('First name must be between 1-20 characters'); + return false; } @@ -247,20 +256,22 @@ protected function askLastName($lastName = '') while (!isset($lastName) || !$this->validateLastName($lastName)) { $lastName = $this->io->ask('Enter the user last name (1-30 characters)'); } + return $lastName; } /** * Validate the last name entered is valid * - * @param string $lastName The lastname - * @return bool Input is valid or not + * @param string $lastName The lastname + * @return bool Input is valid or not */ protected function validateLastName($lastName) { // Validate length if (strlen($lastName) < 1 || strlen($lastName) > 30) { $this->io->error('Last name must be between 1-30 characters'); + return false; } @@ -270,8 +281,8 @@ protected function validateLastName($lastName) /** * Ask for the password and return a valid one * - * @param string $password The base/default password - * @param bool $requireConfirmation (default true) + * @param string $password The base/default password + * @param bool $requireConfirmation (default true) * @return string The validated password */ protected function askPassword($password = '', $requireConfirmation = true) @@ -279,20 +290,22 @@ protected function askPassword($password = '', $requireConfirmation = true) while (!isset($password) || !$this->validatePassword($password) || !$this->confirmPassword($password, $requireConfirmation)) { $password = $this->io->askHidden('Enter password (12-255 characters)'); } + return $password; } /** * Validate password input * - * @param string $password The input - * @return bool Is the password valid or not + * @param string $password The input + * @return bool Is the password valid or not */ protected function validatePassword($password) { //TODO Config for this ?? if (strlen($password) < 12 || strlen($password) > 255) { $this->io->error('Password must be between 12-255 characters'); + return false; } @@ -302,9 +315,9 @@ protected function validatePassword($password) /** * Ask for password confirmation * - * @param string $passwordToConfirm - * @param bool $requireConfirmation (default true) - * @return bool Is the password confirmed or not + * @param string $passwordToConfirm + * @param bool $requireConfirmation (default true) + * @return bool Is the password confirmed or not */ protected function confirmPassword($passwordToConfirm, $requireConfirmation = true) { @@ -315,20 +328,22 @@ protected function confirmPassword($passwordToConfirm, $requireConfirmation = tr while (!isset($password)) { $password = $this->io->askHidden('Please re-enter the chosen password'); } + return $this->validatePasswordConfirmation($password, $passwordToConfirm); } /** * Validate the confirmation password * - * @param string $password The confirmation - * @param string $passwordToConfirm The password to confirm - * @return bool Is the confirmation password valid or not + * @param string $password The confirmation + * @param string $passwordToConfirm The password to confirm + * @return bool Is the confirmation password valid or not */ protected function validatePasswordConfirmation($password, $passwordToConfirm) { if ($password != $passwordToConfirm) { $this->io->error('Passwords do not match, please try again.'); + return false; } diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index c4abfadbd..94aae8abd 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Controller; use Carbon\Carbon; @@ -45,10 +46,10 @@ class AccountController extends SimpleController * Route: /account/check-username * Route Name: {none} * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function checkUsername(Request $request, Response $response, $args) { @@ -98,6 +99,7 @@ public function checkUsername(Request $request, Response $response, $args) if ($classMapper->staticMethod('user', 'findUnique', $data['user_name'], 'user_name')) { $message = $translator->translate('USERNAME.NOT_AVAILABLE', $data); + return $response->write($message)->withStatus(200); } else { return $response->write('true')->withStatus(200); @@ -115,9 +117,9 @@ public function checkUsername(Request $request, Response $response, $args) * Route: /account/set-password/deny * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function denyResetPassword(Request $request, Response $response, $args) { @@ -143,6 +145,7 @@ public function denyResetPassword(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); + return $response->withRedirect($loginPage); } @@ -150,10 +153,12 @@ public function denyResetPassword(Request $request, Response $response, $args) if (!$passwordReset) { $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID'); + return $response->withRedirect($loginPage); } $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_CANNED'); + return $response->withRedirect($loginPage); } @@ -174,9 +179,9 @@ public function denyResetPassword(Request $request, Response $response, $args) * Route: /account/forgot-password * Route Name: {none} * Request type: POST - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function forgotPassword(Request $request, Response $response, $args) { @@ -203,6 +208,7 @@ public function forgotPassword(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); + return $response->withJson([], 400); } @@ -218,6 +224,7 @@ public function forgotPassword(Request $request, Response $response, $args) if ($delay > 0) { $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); + return $response->withJson([], 429); } @@ -243,8 +250,8 @@ public function forgotPassword(Request $request, Response $response, $args) $message->from($config['address_book.admin']) ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) ->addParams([ - 'user' => $user, - 'token' => $passwordReset->getToken(), + 'user' => $user, + 'token' => $passwordReset->getToken(), 'request_date' => Carbon::now()->format('Y-m-d H:i:s') ]); @@ -255,6 +262,7 @@ public function forgotPassword(Request $request, Response $response, $args) // TODO: create delay to prevent timing-based attacks $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', ['email' => $data['email']]); + return $response->withJson([], 200); } @@ -267,9 +275,9 @@ public function forgotPassword(Request $request, Response $response, $args) * Route: /modals/account/tos * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function getModalAccountTos(Request $request, Response $response, $args) { @@ -283,9 +291,9 @@ public function getModalAccountTos(Request $request, Response $response, $args) * Route: /account/captcha * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function imageCaptcha(Request $request, Response $response, $args) { @@ -313,9 +321,9 @@ public function imageCaptcha(Request $request, Response $response, $args) * Route: /account/login * Route Name: {none} * Request type: POST - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function login(Request $request, Response $response, $args) { @@ -331,6 +339,7 @@ public function login(Request $request, Response $response, $args) // Return 200 success if user is already logged in if ($authenticator->check()) { $ms->addMessageTranslated('warning', 'LOGIN.ALREADY_COMPLETE'); + return $response->withJson([], 200); } @@ -351,6 +360,7 @@ public function login(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); + return $response->withJson([], 400); } @@ -373,6 +383,7 @@ public function login(Request $request, Response $response, $args) $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', [ 'delay' => $delay ]); + return $response->withJson([], 429); } @@ -383,6 +394,7 @@ public function login(Request $request, Response $response, $args) // Note that we do this after logging throttle event, so this error counts towards throttling limit. if ($isEmail && !$config['site.login.enable_email']) { $ms->addMessageTranslated('danger', 'USER_OR_PASS_INVALID'); + return $response->withJson([], 403); } @@ -407,9 +419,9 @@ public function login(Request $request, Response $response, $args) * Route: /account/logout * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function logout(Request $request, Response $response, $args) { @@ -418,6 +430,7 @@ public function logout(Request $request, Response $response, $args) // Return to home page $config = $this->ci->config; + return $response->withStatus(302)->withHeader('Location', $config['site.uri.public']); } @@ -431,9 +444,9 @@ public function logout(Request $request, Response $response, $args) * Route: /account/forgot-password * Route Name: forgot-password * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageForgotPassword(Request $request, Response $response, $args) { @@ -450,7 +463,6 @@ public function pageForgotPassword(Request $request, Response $response, $args) ]); } - /** * Render the account registration page for UserFrosting. * @@ -462,10 +474,10 @@ public function pageForgotPassword(Request $request, Response $response, $args) * Route: /account/register * Route Name: register * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws NotFoundException If site registration is disabled - * @param Request $request - * @param Response $response - * @param array $args */ public function pageRegister(Request $request, Response $response, $args) { @@ -504,7 +516,7 @@ public function pageRegister(Request $request, Response $response, $args) ], 'locales' => [ 'available' => $config['site.locales.available'], - 'current' => end($currentLocales) + 'current' => end($currentLocales) ] ]); } @@ -519,9 +531,9 @@ public function pageRegister(Request $request, Response $response, $args) * Route: /account/resend-verification * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageResendVerification(Request $request, Response $response, $args) { @@ -547,9 +559,9 @@ public function pageResendVerification(Request $request, Response $response, $ar * Route: /account/set-password/confirm * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageResetPassword(Request $request, Response $response, $args) { @@ -580,9 +592,9 @@ public function pageResetPassword(Request $request, Response $response, $args) * Route: * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageSetPassword(Request $request, Response $response, $args) { @@ -614,10 +626,10 @@ public function pageSetPassword(Request $request, Response $response, $args) * Route: /account/settings * Route Name: {none} * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function pageSettings(Request $request, Response $response, $args) { @@ -647,7 +659,7 @@ public function pageSettings(Request $request, Response $response, $args) return $this->ci->view->render($response, 'pages/account-settings.html.twig', [ 'locales' => $locales, - 'page' => [ + 'page' => [ 'validators' => [ 'account_settings' => $validatorAccountSettings->rules('json', false), 'profile_settings' => $validatorProfileSettings->rules('json', false) @@ -668,9 +680,9 @@ public function pageSettings(Request $request, Response $response, $args) * Route: /account/sign-in * Route Name: login * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageSignIn(Request $request, Response $response, $args) { @@ -712,9 +724,9 @@ public function pageSignIn(Request $request, Response $response, $args) * Route: /account/settings/profile * Route Name: {none} * Request type: POST - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function profile(Request $request, Response $response, $args) { @@ -731,6 +743,7 @@ public function profile(Request $request, Response $response, $args) // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); + return $response->withJson([], 403); } @@ -782,6 +795,7 @@ public function profile(Request $request, Response $response, $args) ]); $ms->addMessageTranslated('success', 'PROFILE.UPDATED'); + return $response->withJson([], 200); } @@ -805,10 +819,10 @@ public function profile(Request $request, Response $response, $args) * Route: /account/register * Route Name: {none} * Request type: POST + * @param Request $request + * @param Response $response + * @param array $args * @throws SpammyRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function register(Request $request, Response $response, $args) { @@ -832,12 +846,14 @@ public function register(Request $request, Response $response, $args) // Security measure: do not allow registering new users until the master account has been created. if (!$classMapper->staticMethod('user', 'find', $config['reserved_user_ids.master'])) { $ms->addMessageTranslated('danger', 'ACCOUNT.MASTER_NOT_EXISTS'); + return $response->withJson([], 403); } // Check if registration is currently enabled if (!$config['site.registration.enabled']) { $ms->addMessageTranslated('danger', 'REGISTRATION.DISABLED'); + return $response->withJson([], 403); } @@ -847,6 +863,7 @@ public function register(Request $request, Response $response, $args) // Prevent the user from registering if he/she is already logged in if ($authenticator->check()) { $ms->addMessageTranslated('danger', 'REGISTRATION.LOGOUT'); + return $response->withJson([], 403); } @@ -928,9 +945,9 @@ public function register(Request $request, Response $response, $args) * Route: /account/resend-verification * Route Name: {none} * Request type: POST - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function resendVerification(Request $request, Response $response, $args) { @@ -957,6 +974,7 @@ public function resendVerification(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); + return $response->withJson([], 400); } @@ -972,6 +990,7 @@ public function resendVerification(Request $request, Response $response, $args) if ($delay > 0) { $ms->addMessageTranslated('danger', 'RATE_LIMIT_EXCEEDED', ['delay' => $delay]); + return $response->withJson([], 429); } @@ -997,7 +1016,7 @@ public function resendVerification(Request $request, Response $response, $args) $message->from($config['address_book.admin']) ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) ->addParams([ - 'user' => $user, + 'user' => $user, 'token' => $verification->getToken() ]); @@ -1006,6 +1025,7 @@ public function resendVerification(Request $request, Response $response, $args) }); $ms->addMessageTranslated('success', 'ACCOUNT.VERIFICATION.NEW_LINK_SENT', ['email' => $data['email']]); + return $response->withJson([], 200); } @@ -1023,9 +1043,9 @@ public function resendVerification(Request $request, Response $response, $args) * Route: /account/set-password * Route Name: {none} * Request type: POST - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function setPassword(Request $request, Response $response, $args) { @@ -1052,6 +1072,7 @@ public function setPassword(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); + return $response->withJson([], 400); } @@ -1064,6 +1085,7 @@ public function setPassword(Request $request, Response $response, $args) if (!$passwordReset) { $ms->addMessageTranslated('danger', 'PASSWORD.FORGET.INVALID', ['url' => $forgotPasswordPage]); + return $response->withJson([], 400); } @@ -1082,6 +1104,7 @@ public function setPassword(Request $request, Response $response, $args) $authenticator->login($user); $ms->addMessageTranslated('success', 'WELCOME', $user->export()); + return $response->withJson([], 200); } @@ -1098,9 +1121,9 @@ public function setPassword(Request $request, Response $response, $args) * Route: /account/settings * Route Name: settings * Request type: POST - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function settings(Request $request, Response $response, $args) { @@ -1117,6 +1140,7 @@ public function settings(Request $request, Response $response, $args) // See recipe "per-field access control" for dynamic fine-grained control over which properties a user can modify. if (!$authorizer->checkAccess($currentUser, 'update_account_settings')) { $ms->addMessageTranslated('danger', 'ACCOUNT.ACCESS_DENIED'); + return $response->withJson([], 403); } @@ -1185,6 +1209,7 @@ public function settings(Request $request, Response $response, $args) ]); $ms->addMessageTranslated('success', 'ACCOUNT.SETTINGS.UPDATED'); + return $response->withJson([], 200); } @@ -1198,9 +1223,9 @@ public function settings(Request $request, Response $response, $args) * Route: /account/suggest-username * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function suggestUsername(Request $request, Response $response, $args) { @@ -1231,9 +1256,9 @@ public function suggestUsername(Request $request, Response $response, $args) * Route: /account/verify * Route Name: {none} * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function verify(Request $request, Response $response, $args) { @@ -1262,6 +1287,7 @@ public function verify(Request $request, Response $response, $args) $validator = new ServerSideValidator($schema, $this->ci->translator); if (!$validator->validate($data)) { $ms->addValidationErrors($validator); + return $response->withRedirect($loginPage); } @@ -1269,6 +1295,7 @@ public function verify(Request $request, Response $response, $args) if (!$verification) { $ms->addMessageTranslated('danger', 'ACCOUNT.VERIFICATION.TOKEN_NOT_FOUND'); + return $response->withRedirect($loginPage); } diff --git a/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php b/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php index 1571763ce..b9afe650c 100644 --- a/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php +++ b/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Controller\Exception; use UserFrosting\Support\Exception\HttpException; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php index c4cdf223f..492754c54 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use UserFrosting\Sprinkle\Core\Database\Migration; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php index aa87b22d3..4b6f37daa 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; @@ -45,22 +46,22 @@ public function up() // Add default groups $groups = [ 'terran' => new Group([ - 'slug' => 'terran', - 'name' => 'Terran', + 'slug' => 'terran', + 'name' => 'Terran', 'description' => 'The terrans are a young species with psionic potential. The terrans of the Koprulu sector descend from the survivors of a disastrous 23rd century colonization mission from Earth.', - 'icon' => 'sc sc-terran' + 'icon' => 'sc sc-terran' ]), 'zerg' => new Group([ - 'slug' => 'zerg', - 'name' => 'Zerg', + 'slug' => 'zerg', + 'name' => 'Zerg', 'description' => 'Dedicated to the pursuit of genetic perfection, the zerg relentlessly hunt down and assimilate advanced species across the galaxy, incorporating useful genetic code into their own.', - 'icon' => 'sc sc-zerg' + 'icon' => 'sc sc-zerg' ]), 'protoss' => new Group([ - 'slug' => 'protoss', - 'name' => 'Protoss', + 'slug' => 'protoss', + 'name' => 'Protoss', 'description' => 'The protoss, a.k.a. the Firstborn, are a sapient humanoid race native to Aiur. Their advanced technology complements and enhances their psionic mastery.', - 'icon' => 'sc sc-protoss' + 'icon' => 'sc sc-protoss' ]) ]; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php index 68518e196..5639d4fed 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; @@ -18,7 +19,7 @@ * See https://laravel.com/docs/5.4/migrations#tables * @author Alex Weissman (https://alexanderweissman.com) */ -class passwordResetsTable extends Migration +class PasswordResetsTable extends Migration { /** * {@inheritdoc} diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php index 238c5fc12..1b02d9176 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php index f0149546e..470a7ad20 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; @@ -54,143 +55,143 @@ public function up() // Skip this if table is not empty if (Permission::count() == 0) { $defaultRoleIds = [ - 'user' => Role::where('slug', 'user')->first()->id, + 'user' => Role::where('slug', 'user')->first()->id, 'group-admin' => Role::where('slug', 'group-admin')->first()->id, - 'site-admin' => Role::where('slug', 'site-admin')->first()->id + 'site-admin' => Role::where('slug', 'site-admin')->first()->id ]; // Add default permissions $permissions = [ 'create_group' => new Permission([ - 'slug' => 'create_group', - 'name' => 'Create group', - 'conditions' => 'always()', + 'slug' => 'create_group', + 'name' => 'Create group', + 'conditions' => 'always()', 'description' => 'Create a new group.' ]), 'create_user' => new Permission([ - 'slug' => 'create_user', - 'name' => 'Create user', - 'conditions' => 'always()', + 'slug' => 'create_user', + 'name' => 'Create user', + 'conditions' => 'always()', 'description' => 'Create a new user in your own group and assign default roles.' ]), 'create_user_field' => new Permission([ - 'slug' => 'create_user_field', - 'name' => 'Set new user group', - 'conditions' => "subset(fields,['group'])", + 'slug' => 'create_user_field', + 'name' => 'Set new user group', + 'conditions' => "subset(fields,['group'])", 'description' => 'Set the group when creating a new user.' ]), 'delete_group' => new Permission([ - 'slug' => 'delete_group', - 'name' => 'Delete group', - 'conditions' => "always()", + 'slug' => 'delete_group', + 'name' => 'Delete group', + 'conditions' => 'always()', 'description' => 'Delete a group.' ]), 'delete_user' => new Permission([ - 'slug' => 'delete_user', - 'name' => 'Delete user', - 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && !is_master(user.id)", + 'slug' => 'delete_user', + 'name' => 'Delete user', + 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && !is_master(user.id)", 'description' => 'Delete users who are not Site Administrators.' ]), 'update_account_settings' => new Permission([ - 'slug' => 'update_account_settings', - 'name' => 'Edit user', - 'conditions' => 'always()', + 'slug' => 'update_account_settings', + 'name' => 'Edit user', + 'conditions' => 'always()', 'description' => 'Edit your own account settings.' ]), 'update_group_field' => new Permission([ - 'slug' => 'update_group_field', - 'name' => 'Edit group', - 'conditions' => 'always()', + 'slug' => 'update_group_field', + 'name' => 'Edit group', + 'conditions' => 'always()', 'description' => 'Edit basic properties of any group.' ]), 'update_user_field' => new Permission([ - 'slug' => 'update_user_field', - 'name' => 'Edit user', - 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && subset(fields,['name','email','locale','group','flag_enabled','flag_verified','password'])", + 'slug' => 'update_user_field', + 'name' => 'Edit user', + 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && subset(fields,['name','email','locale','group','flag_enabled','flag_verified','password'])", 'description' => 'Edit users who are not Site Administrators.' ]), 'update_user_field_group' => new Permission([ - 'slug' => 'update_user_field', - 'name' => 'Edit group user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && subset(fields,['name','email','locale','flag_enabled','flag_verified','password'])", + 'slug' => 'update_user_field', + 'name' => 'Edit group user', + 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && subset(fields,['name','email','locale','flag_enabled','flag_verified','password'])", 'description' => 'Edit users in your own group who are not Site or Group Administrators, except yourself.' ]), 'uri_account_settings' => new Permission([ - 'slug' => 'uri_account_settings', - 'name' => 'Account settings page', - 'conditions' => 'always()', + 'slug' => 'uri_account_settings', + 'name' => 'Account settings page', + 'conditions' => 'always()', 'description' => 'View the account settings page.' ]), 'uri_activities' => new Permission([ - 'slug' => 'uri_activities', - 'name' => 'Activity monitor', - 'conditions' => 'always()', + 'slug' => 'uri_activities', + 'name' => 'Activity monitor', + 'conditions' => 'always()', 'description' => 'View a list of all activities for all users.' ]), 'uri_dashboard' => new Permission([ - 'slug' => 'uri_dashboard', - 'name' => 'Admin dashboard', - 'conditions' => 'always()', + 'slug' => 'uri_dashboard', + 'name' => 'Admin dashboard', + 'conditions' => 'always()', 'description' => 'View the administrative dashboard.' ]), 'uri_group' => new Permission([ - 'slug' => 'uri_group', - 'name' => 'View group', - 'conditions' => 'always()', + 'slug' => 'uri_group', + 'name' => 'View group', + 'conditions' => 'always()', 'description' => 'View the group page of any group.' ]), 'uri_group_own' => new Permission([ - 'slug' => 'uri_group', - 'name' => 'View own group', - 'conditions' => 'equals_num(self.group_id,group.id)', + 'slug' => 'uri_group', + 'name' => 'View own group', + 'conditions' => 'equals_num(self.group_id,group.id)', 'description' => 'View the group page of your own group.' ]), 'uri_groups' => new Permission([ - 'slug' => 'uri_groups', - 'name' => 'Group management page', - 'conditions' => 'always()', + 'slug' => 'uri_groups', + 'name' => 'Group management page', + 'conditions' => 'always()', 'description' => 'View a page containing a list of groups.' ]), 'uri_user' => new Permission([ - 'slug' => 'uri_user', - 'name' => 'View user', - 'conditions' => 'always()', + 'slug' => 'uri_user', + 'name' => 'View user', + 'conditions' => 'always()', 'description' => 'View the user page of any user.' ]), 'uri_user_in_group' => new Permission([ - 'slug' => 'uri_user', - 'name' => 'View user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id))", + 'slug' => 'uri_user', + 'name' => 'View user', + 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id))", 'description' => 'View the user page of any user in your group, except the master user and Site and Group Administrators (except yourself).' ]), 'uri_users' => new Permission([ - 'slug' => 'uri_users', - 'name' => 'User management page', - 'conditions' => 'always()', + 'slug' => 'uri_users', + 'name' => 'User management page', + 'conditions' => 'always()', 'description' => 'View a page containing a table of users.' ]), 'view_group_field' => new Permission([ - 'slug' => 'view_group_field', - 'name' => 'View group', - 'conditions' => "in(property,['name','icon','slug','description','users'])", + 'slug' => 'view_group_field', + 'name' => 'View group', + 'conditions' => "in(property,['name','icon','slug','description','users'])", 'description' => 'View certain properties of any group.' ]), 'view_group_field_own' => new Permission([ - 'slug' => 'view_group_field', - 'name' => 'View group', - 'conditions' => "equals_num(self.group_id,group.id) && in(property,['name','icon','slug','description','users'])", + 'slug' => 'view_group_field', + 'name' => 'View group', + 'conditions' => "equals_num(self.group_id,group.id) && in(property,['name','icon','slug','description','users'])", 'description' => 'View certain properties of your own group.' ]), 'view_user_field' => new Permission([ - 'slug' => 'view_user_field', - 'name' => 'View user', - 'conditions' => "in(property,['user_name','name','email','locale','theme','roles','group','activities'])", + 'slug' => 'view_user_field', + 'name' => 'View user', + 'conditions' => "in(property,['user_name','name','email','locale','theme','roles','group','activities'])", 'description' => 'View certain properties of any user.' ]), 'view_user_field_group' => new Permission([ - 'slug' => 'view_user_field', - 'name' => 'View user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && in(property,['user_name','name','email','locale','roles','group','activities'])", + 'slug' => 'view_user_field', + 'name' => 'View user', + 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && in(property,['user_name','name','email','locale','roles','group','activities'])", 'description' => 'View certain properties of any user in your own group, except the master user and Site and Group Administrators (except yourself).' ]) ]; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php index 07834f3fc..e476ece76 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php index f36ecfc1d..34c06efbc 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php index aecf42654..73bb04f62 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; @@ -44,18 +45,18 @@ public function up() // Add default roles $roles = [ 'user' => new Role([ - 'slug' => 'user', - 'name' => 'User', + 'slug' => 'user', + 'name' => 'User', 'description' => 'This role provides basic user functionality.' ]), 'site-admin' => new Role([ - 'slug' => 'site-admin', - 'name' => 'Site Administrator', + 'slug' => 'site-admin', + 'name' => 'Site Administrator', 'description' => 'This role is meant for "site administrators", who can basically do anything except create, edit, or delete other administrators.' ]), 'group-admin' => new Role([ - 'slug' => 'group-admin', - 'name' => 'Group Administrator', + 'slug' => 'group-admin', + 'name' => 'Group Administrator', 'description' => 'This role is meant for "group administrators", who can basically do anything with users in their own group, except other administrators of that group.' ]) ]; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php b/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php index 4af640e90..e077f49d7 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; @@ -33,11 +34,11 @@ public function up() $table->string('first_name', 20); $table->string('last_name', 30); $table->string('locale', 10)->default('en_US')->comment('The language and locale to use for this user.'); - $table->string('theme', 100)->nullable()->comment("The user theme."); - $table->integer('group_id')->unsigned()->default(1)->comment("The id of the user group."); - $table->boolean('flag_verified')->default(1)->comment("Set to 1 if the user has verified their account via email, 0 otherwise."); - $table->boolean('flag_enabled')->default(1)->comment("Set to 1 if the user account is currently enabled, 0 otherwise. Disabled accounts cannot be logged in to, but they retain all of their data and settings."); - $table->integer('last_activity_id')->unsigned()->nullable()->comment("The id of the last activity performed by this user."); + $table->string('theme', 100)->nullable()->comment('The user theme.'); + $table->integer('group_id')->unsigned()->default(1)->comment('The id of the user group.'); + $table->boolean('flag_verified')->default(1)->comment('Set to 1 if the user has verified their account via email, 0 otherwise.'); + $table->boolean('flag_enabled')->default(1)->comment('Set to 1 if the user account is currently enabled, 0 otherwise. Disabled accounts cannot be logged in to, but they retain all of their data and settings.'); + $table->integer('last_activity_id')->unsigned()->nullable()->comment('The id of the last activity performed by this user.'); $table->string('password', 255); $table->softDeletes(); $table->timestamps(); diff --git a/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php index 54035c85e..9742c9621 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; diff --git a/app/sprinkles/account/src/Database/Models/Activity.php b/app/sprinkles/account/src/Database/Models/Activity.php index 27b8b901a..8ee605f2f 100644 --- a/app/sprinkles/account/src/Database/Models/Activity.php +++ b/app/sprinkles/account/src/Database/Models/Activity.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Models; use Illuminate\Database\Capsule\Manager as Capsule; @@ -27,14 +28,14 @@ class Activity extends Model /** * @var string The name of the table for the current model. */ - protected $table = "activities"; + protected $table = 'activities'; protected $fillable = [ - "ip_address", - "user_id", - "type", - "occurred_at", - "description" + 'ip_address', + 'user_id', + 'type', + 'occurred_at', + 'description' ]; /** @@ -54,7 +55,7 @@ public function scopeJoinUser($query) /** * Add clauses to select the most recent event of each type for each user, to the query. * - * @param Builder $query + * @param Builder $query * @return Builder */ public function scopeMostRecentEvents($query) @@ -67,11 +68,11 @@ public function scopeMostRecentEvents($query) /** * Add clauses to select the most recent event of a given type for each user, to the query. * - * @param Builder $query - * @param string $type The type of event, matching the `event_type` field in the user_event table. + * @param Builder $query + * @param string $type The type of event, matching the `event_type` field in the user_event table. * @return Builder */ - public function scopeMostRecentEventsByType(Builder$query, $type) + public function scopeMostRecentEventsByType(Builder $query, $type) { return $query->select('user_id', Capsule::raw('MAX(occurred_at) as occurred_at')) ->where('type', $type) diff --git a/app/sprinkles/account/src/Database/Models/Group.php b/app/sprinkles/account/src/Database/Models/Group.php index 993c15f79..cc5690b96 100644 --- a/app/sprinkles/account/src/Database/Models/Group.php +++ b/app/sprinkles/account/src/Database/Models/Group.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Models; use UserFrosting\Sprinkle\Core\Database\Models\Model; @@ -14,7 +15,6 @@ * * Represents a group object as stored in the database. * - * @package UserFrosting * @author Alex Weissman * @see http://www.userfrosting.com/tutorials/lesson-3-data-model/ * @@ -28,13 +28,13 @@ class Group extends Model /** * @var string The name of the table for the current model. */ - protected $table = "groups"; + protected $table = 'groups'; protected $fillable = [ - "slug", - "name", - "description", - "icon" + 'slug', + 'name', + 'description', + 'icon' ]; /** diff --git a/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php b/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php index 8d71fbc16..3870afc96 100644 --- a/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php +++ b/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Models\Interfaces; use Illuminate\Database\Eloquent\Builder; @@ -26,7 +27,7 @@ public function activities(); /** * Delete this user from the database, along with any linked roles and activities. * - * @param bool $hardDelete Set to true to completely remove the user and all associated objects. + * @param bool $hardDelete Set to true to completely remove the user and all associated objects. * @return bool true if the deletion was successful, false otherwise. */ public function delete($hardDelete = false); @@ -55,14 +56,14 @@ public function getCachedPermissions(); /** * Retrieve the cached permissions dictionary for this user. * - * @return User + * @return $this */ public function reloadCachedPermissions(); /** * Get the amount of time, in seconds, that has elapsed since the last activity of a certain time for this user. * - * @param string $type The type of activity to search for. + * @param string $type The type of activity to search for. * @return int */ public function getSecondsSinceLastActivity($type); @@ -91,7 +92,7 @@ public function lastActivity(); /** * Find the most recent activity for this user of a particular type. * - * @param string $type + * @param string $type * @return \Illuminate\Database\Eloquent\Builder */ public function lastActivityOfType($type = null); @@ -99,7 +100,7 @@ public function lastActivityOfType($type = null); /** * Get the most recent time for a specified activity type for this user. * - * @param string $type + * @param string $type * @return string|null The last activity time, as a SQL formatted time (YYYY-MM-DD HH:MM:SS), or null if an activity of this type doesn't exist. */ public function lastActivityTime($type); @@ -146,8 +147,8 @@ public function roles(); /** * Query scope to get all users who have a specific role. * - * @param Builder $query - * @param int $roleId + * @param Builder $query + * @param int $roleId * @return Builder */ public function scopeForRole($query, $roleId); @@ -155,7 +156,7 @@ public function scopeForRole($query, $roleId); /** * Joins the user's most recent activity directly, so we can do things like sort, search, paginate, etc. * - * @param Builder $query + * @param Builder $query * @return Builder */ public function scopeJoinLastActivity($query); diff --git a/app/sprinkles/account/src/Database/Models/PasswordReset.php b/app/sprinkles/account/src/Database/Models/PasswordReset.php index 01bb2abc0..bf79826fa 100644 --- a/app/sprinkles/account/src/Database/Models/PasswordReset.php +++ b/app/sprinkles/account/src/Database/Models/PasswordReset.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Models; use UserFrosting\Sprinkle\Core\Database\Models\Model; @@ -25,14 +26,14 @@ class PasswordReset extends Model /** * @var string The name of the table for the current model. */ - protected $table = "password_resets"; + protected $table = 'password_resets'; protected $fillable = [ - "user_id", - "hash", - "completed", - "expires_at", - "completed_at" + 'user_id', + 'hash', + 'completed', + 'expires_at', + 'completed_at' ]; /** @@ -54,12 +55,13 @@ public function getToken() } /** - * @param string $value + * @param string $value * @return self */ public function setToken($value) { $this->token = $value; + return $this; } diff --git a/app/sprinkles/account/src/Database/Models/Permission.php b/app/sprinkles/account/src/Database/Models/Permission.php index c6ced1378..0d72d0dd0 100644 --- a/app/sprinkles/account/src/Database/Models/Permission.php +++ b/app/sprinkles/account/src/Database/Models/Permission.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Models; use Illuminate\Database\Eloquent\Builder; @@ -25,13 +26,13 @@ class Permission extends Model /** * @var string The name of the table for the current model. */ - protected $table = "permissions"; + protected $table = 'permissions'; protected $fillable = [ - "slug", - "name", - "conditions", - "description" + 'slug', + 'name', + 'conditions', + 'description' ]; /** @@ -41,7 +42,6 @@ class Permission extends Model /** * Delete this permission from the database, removing associations with roles. - * */ public function delete() { @@ -70,8 +70,8 @@ public function roles() /** * Query scope to get all permissions assigned to a specific role. * - * @param Builder $query - * @param int $roleId + * @param Builder $query + * @param int $roleId * @return Builder */ public function scopeForRole($query, $roleId) @@ -85,8 +85,8 @@ public function scopeForRole($query, $roleId) /** * Query scope to get all permissions NOT associated with a specific role. * - * @param Builder $query - * @param int $roleId + * @param Builder $query + * @param int $roleId * @return Builder */ public function scopeNotForRole($query, $roleId) diff --git a/app/sprinkles/account/src/Database/Models/Role.php b/app/sprinkles/account/src/Database/Models/Role.php index ec61b14fd..630420d27 100644 --- a/app/sprinkles/account/src/Database/Models/Role.php +++ b/app/sprinkles/account/src/Database/Models/Role.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Models; use Illuminate\Database\Eloquent\Builder; @@ -24,12 +25,12 @@ class Role extends Model /** * @var string The name of the table for the current model. */ - protected $table = "roles"; + protected $table = 'roles'; protected $fillable = [ - "slug", - "name", - "description" + 'slug', + 'name', + 'description' ]; /** @@ -39,7 +40,6 @@ class Role extends Model /** * Delete this role from the database, removing associations with permissions and users. - * */ public function delete() { @@ -80,8 +80,8 @@ public function permissions() /** * Query scope to get all roles assigned to a specific user. * - * @param Builder $query - * @param int $userId + * @param Builder $query + * @param int $userId * @return Builder */ public function scopeForUser($query, $userId) diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index 95b6c13d2..bb98db7fe 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Models; use Carbon\Carbon; @@ -112,8 +113,8 @@ class User extends Model implements UserInterface * See http://stackoverflow.com/questions/29514081/cannot-access-eloquent-attributes-on-twig/35908957#35908957 * Every property in __get must also be implemented here for Twig to recognize it. * - * @param string $name the name of the property to check. - * @return bool true if the property is defined, false otherwise. + * @param string $name the name of the property to check. + * @return bool true if the property is defined, false otherwise. */ public function __isset($name) { @@ -131,9 +132,9 @@ public function __isset($name) /** * Get a property for this object. * + * @param string $name the name of the property to retrieve. * @throws \Exception the property does not exist for this object. - * @param string $name the name of the property to retrieve. - * @return string the associated property. + * @return string the associated property. */ public function __get($name) { @@ -142,6 +143,7 @@ public function __get($name) } elseif ($name == 'avatar') { // Use Gravatar as the user avatar $hash = md5(strtolower(trim($this->email))); + return 'https://www.gravatar.com/avatar/' . $hash . '?d=mm'; } else { return parent::__get($name); @@ -164,7 +166,7 @@ public function activities() /** * Delete this user from the database, along with any linked roles and activities. * - * @param bool $hardDelete Set to true to completely remove the user and all associated objects. + * @param bool $hardDelete Set to true to completely remove the user and all associated objects. * @return bool true if the deletion was successful, false otherwise. */ public function delete($hardDelete = false) @@ -199,9 +201,9 @@ public function delete($hardDelete = false) * Determines whether a user exists, including checking soft-deleted records * * @deprecated since 4.1.7 This method conflicts with and overrides the Builder::exists() method. Use Model::findUnique instead. - * @param mixed $value - * @param string $identifier - * @param bool $checkDeleted set to true to include soft-deleted records + * @param mixed $value + * @param string $identifier + * @param bool $checkDeleted set to true to include soft-deleted records * @return User|null */ public static function exists($value, $identifier = 'user_name', $checkDeleted = true) @@ -258,7 +260,7 @@ public function reloadCachedPermissions() /** * Get the amount of time, in seconds, that has elapsed since the last activity of a certain time for this user. * - * @param string $type The type of activity to search for. + * @param string $type The type of activity to search for. * @return int */ public function getSecondsSinceLastActivity($type) @@ -293,7 +295,7 @@ public function isMaster() $masterId = static::$ci->config['reserved_user_ids.master']; // Need to use loose comparison for now, because some DBs return `id` as a string - return ($this->id == $masterId); + return $this->id == $masterId; } /** @@ -312,7 +314,7 @@ public function lastActivity() /** * Find the most recent activity for this user of a particular type. * - * @param string $type + * @param string $type * @return \Illuminate\Database\Eloquent\Builder */ public function lastActivityOfType($type = null) @@ -332,7 +334,7 @@ public function lastActivityOfType($type = null) /** * Get the most recent time for a specified activity type for this user. * - * @param string $type + * @param string $type * @return string|null The last activity time, as a SQL formatted time (YYYY-MM-DD HH:MM:SS), or null if an activity of this type doesn't exist. */ public function lastActivityTime($type) @@ -340,6 +342,7 @@ public function lastActivityTime($type) $result = $this->activities() ->where('type', $type) ->max('occurred_at'); + return $result ? $result : null; } @@ -448,8 +451,8 @@ public function roles() /** * Query scope to get all users who have a specific role. * - * @param Builder $query - * @param int $roleId + * @param Builder $query + * @param int $roleId * @return Builder */ public function scopeForRole($query, $roleId) @@ -463,7 +466,7 @@ public function scopeForRole($query, $roleId) /** * Joins the user's most recent activity directly, so we can do things like sort, search, paginate, etc. * - * @param Builder $query + * @param Builder $query * @return Builder */ public function scopeJoinLastActivity($query) diff --git a/app/sprinkles/account/src/Database/Models/Verification.php b/app/sprinkles/account/src/Database/Models/Verification.php index 8d03274bf..319d4d4bc 100644 --- a/app/sprinkles/account/src/Database/Models/Verification.php +++ b/app/sprinkles/account/src/Database/Models/Verification.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Database\Models; use UserFrosting\Sprinkle\Core\Database\Models\Model; @@ -25,14 +26,14 @@ class Verification extends Model /** * @var string The name of the table for the current model. */ - protected $table = "verifications"; + protected $table = 'verifications'; protected $fillable = [ - "user_id", - "hash", - "completed", - "expires_at", - "completed_at" + 'user_id', + 'hash', + 'completed', + 'expires_at', + 'completed_at' ]; /** @@ -54,12 +55,13 @@ public function getToken() } /** - * @param string $value + * @param string $value * @return self */ public function setToken($value) { $this->token = $value; + return $this; } diff --git a/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php b/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php index ff7bbc0cd..b2e3f9096 100644 --- a/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php +++ b/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Error\Handler; use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler; diff --git a/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php b/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php index 9ed1de0e9..f796b0ec5 100644 --- a/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php +++ b/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Error\Handler; use Psr\Http\Message\ResponseInterface; diff --git a/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php b/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php index e22f02bf5..9b536e531 100644 --- a/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php +++ b/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Error\Handler; use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler; @@ -25,7 +26,7 @@ class ForbiddenExceptionHandler extends HttpExceptionHandler protected function determineUserMessages() { return [ - new UserMessage("ACCOUNT.ACCESS_DENIED") + new UserMessage('ACCOUNT.ACCESS_DENIED') ]; } } diff --git a/app/sprinkles/account/src/Facades/Password.php b/app/sprinkles/account/src/Facades/Password.php index e5bf9674e..1f1e29278 100644 --- a/app/sprinkles/account/src/Facades/Password.php +++ b/app/sprinkles/account/src/Facades/Password.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Facades; use UserFrosting\System\Facade; diff --git a/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php b/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php index 973d5ccd9..e6a62f80c 100644 --- a/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php +++ b/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Log; use UserFrosting\Sprinkle\Core\Log\DatabaseHandler; diff --git a/app/sprinkles/account/src/Log/UserActivityProcessor.php b/app/sprinkles/account/src/Log/UserActivityProcessor.php index a73530349..9bed6b30a 100644 --- a/app/sprinkles/account/src/Log/UserActivityProcessor.php +++ b/app/sprinkles/account/src/Log/UserActivityProcessor.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Log; /** @@ -28,7 +29,7 @@ public function __construct($userId) } /** - * @param array $record + * @param array $record * @return array */ public function __invoke(array $record) diff --git a/app/sprinkles/account/src/Repository/PasswordResetRepository.php b/app/sprinkles/account/src/Repository/PasswordResetRepository.php index a72446f24..5a4832695 100644 --- a/app/sprinkles/account/src/Repository/PasswordResetRepository.php +++ b/app/sprinkles/account/src/Repository/PasswordResetRepository.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Repository; use UserFrosting\Sprinkle\Account\Facades\Password; diff --git a/app/sprinkles/account/src/Repository/TokenRepository.php b/app/sprinkles/account/src/Repository/TokenRepository.php index 82dc12494..ebe9134ab 100644 --- a/app/sprinkles/account/src/Repository/TokenRepository.php +++ b/app/sprinkles/account/src/Repository/TokenRepository.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Repository; use Carbon\Carbon; @@ -40,7 +41,7 @@ abstract class TokenRepository * Create a new TokenRepository object. * * @param ClassMapper $classMapper Maps generic class identifiers to specific class names. - * @param string $algorithm The hashing algorithm to use when storing generated tokens. + * @param string $algorithm The hashing algorithm to use when storing generated tokens. */ public function __construct(ClassMapper $classMapper, $algorithm = 'sha512') { @@ -51,7 +52,7 @@ public function __construct(ClassMapper $classMapper, $algorithm = 'sha512') /** * Cancels a specified token by removing it from the database. * - * @param int $token The token to remove. + * @param int $token The token to remove. * @return Model|false */ public function cancel($token) @@ -77,8 +78,8 @@ public function cancel($token) /** * Completes a token-based process, invoking updateUser() in the child object to do the actual action. * - * @param int $token The token to complete. - * @param mixed[] $userParams An optional list of parameters to pass to updateUser(). + * @param int $token The token to complete. + * @param mixed[] $userParams An optional list of parameters to pass to updateUser(). * @return Model|false */ public function complete($token, $userParams = []) @@ -119,9 +120,9 @@ public function complete($token, $userParams = []) /** * Create a new token for a specified user. * - * @param UserInterface $user The user object to associate with this token. - * @param int $timeout The time, in seconds, after which this token should expire. - * @return Model The model (PasswordReset, Verification, etc) object that stores the token. + * @param UserInterface $user The user object to associate with this token. + * @param int $timeout The time, in seconds, after which this token should expire. + * @return Model The model (PasswordReset, Verification, etc) object that stores the token. */ public function create(UserInterface $user, $timeout) { @@ -155,8 +156,8 @@ public function create(UserInterface $user, $timeout) /** * Determine if a specified user has an incomplete and unexpired token. * - * @param UserInterface $user The user object to look up. - * @param int $token Optionally, try to match a specific token. + * @param UserInterface $user The user object to look up. + * @param int $token Optionally, try to match a specific token. * @return Model|false */ public function exists(UserInterface $user, $token = null) @@ -178,7 +179,7 @@ public function exists(UserInterface $user, $token = null) /** * Delete all existing tokens from the database for a particular user. * - * @param UserInterface $user + * @param UserInterface $user * @return int */ protected function removeExisting(UserInterface $user) @@ -205,7 +206,7 @@ public function removeExpired() * Generate a new random token for this user. * * This generates a token to use for verifying a new account, resetting a lost password, etc. - * @param string $gen specify an existing token that, if we happen to generate the same value, we should regenerate on. + * @param string $gen specify an existing token that, if we happen to generate the same value, we should regenerate on. * @return string */ protected function generateRandomToken($gen = null) @@ -215,6 +216,7 @@ protected function generateRandomToken($gen = null) } while ($this->classMapper ->staticMethod($this->modelIdentifier, 'where', 'hash', hash($this->algorithm, $gen)) ->first()); + return $gen; } @@ -222,9 +224,9 @@ protected function generateRandomToken($gen = null) * Modify the user during the token completion process. * * This method is called during complete(), and is a way for concrete implementations to modify the user. - * @param UserInterface $user the user object to modify. - * @param mixed[] $args - * @return mixed[] $args the list of parameters that were supplied to the call to `complete()` + * @param UserInterface $user the user object to modify. + * @param mixed[] $args + * @return mixed[] $args the list of parameters that were supplied to the call to `complete()` */ abstract protected function updateUser(UserInterface $user, $args); } diff --git a/app/sprinkles/account/src/Repository/VerificationRepository.php b/app/sprinkles/account/src/Repository/VerificationRepository.php index e461c1a55..26f447f46 100644 --- a/app/sprinkles/account/src/Repository/VerificationRepository.php +++ b/app/sprinkles/account/src/Repository/VerificationRepository.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Repository; /** diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index 97b98a208..45c1c08be 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\ServicesProvider; use Illuminate\Database\Capsule\Manager as Capsule; @@ -67,6 +68,7 @@ public function register(ContainerInterface $container) $classMapper->setClassMapping('activity', 'UserFrosting\Sprinkle\Account\Database\Models\Activity'); $classMapper->setClassMapping('password_reset', 'UserFrosting\Sprinkle\Account\Database\Models\PasswordReset'); $classMapper->setClassMapping('verification', 'UserFrosting\Sprinkle\Account\Database\Models\Verification'); + return $classMapper; }); @@ -84,6 +86,7 @@ public function register(ContainerInterface $container) $handler->registerHandler('\UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthExpiredException', '\UserFrosting\Sprinkle\Account\Error\Handler\AuthExpiredExceptionHandler'); // Register the AuthCompromisedExceptionHandler. $handler->registerHandler('\UserFrosting\Sprinkle\Account\Authenticate\Exception\AuthCompromisedException', '\UserFrosting\Sprinkle\Account\Error\Handler\AuthCompromisedExceptionHandler'); + return $handler; }); @@ -135,7 +138,7 @@ public function register(ContainerInterface $container) // Register user theme template with Twig Loader if ($authenticator->check()) { - $themePath = $c->locator->findResource("templates://", true, false); + $themePath = $c->locator->findResource('templates://', true, false); if ($themePath) { $loader = $twig->getLoader(); $loader->prependPath($themePath); @@ -167,6 +170,7 @@ public function register(ContainerInterface $container) $config['remember_me.table.tableName'] = Capsule::connection()->getTablePrefix() . $config['remember_me.table.tableName']; $authenticator = new Authenticator($classMapper, $session, $config, $cache); + return $authenticator; }; @@ -177,6 +181,7 @@ public function register(ContainerInterface $container) */ $container['authGuard'] = function ($c) { $authenticator = $c->authenticator; + return new AuthGuard($authenticator); }; @@ -224,19 +229,19 @@ public function register(ContainerInterface $container) /** * Check if the specified values are identical to one another (strict comparison). - * @param mixed $val1 the first value to compare. - * @param mixed $val2 the second value to compare. - * @return bool true if the values are strictly equal, false otherwise. + * @param mixed $val1 the first value to compare. + * @param mixed $val2 the second value to compare. + * @return bool true if the values are strictly equal, false otherwise. */ 'equals' => function ($val1, $val2) { - return ($val1 === $val2); + return $val1 === $val2; }, /** * Check if the specified values are numeric, and if so, if they are equal to each other. - * @param mixed $val1 the first value to compare. - * @param mixed $val2 the second value to compare. - * @return bool true if the values are numeric and equal, false otherwise. + * @param mixed $val1 the first value to compare. + * @param mixed $val2 the second value to compare. + * @return bool true if the values are numeric and equal, false otherwise. */ 'equals_num' => function ($val1, $val2) { if (!is_numeric($val1)) { @@ -246,14 +251,14 @@ public function register(ContainerInterface $container) return false; } - return ($val1 == $val2); + return $val1 == $val2; }, /** * Check if the specified user (by user_id) has a particular role. * - * @param int $user_id the id of the user. - * @param int $role_id the id of the role. + * @param int $user_id the id of the user. + * @param int $role_id the id of the role. * @return bool true if the user has the role, false otherwise. */ 'has_role' => function ($user_id, $role_id) { @@ -266,9 +271,9 @@ public function register(ContainerInterface $container) /** * Check if the specified value $needle is in the values of $haystack. * - * @param mixed $needle the value to look for in $haystack - * @param array[mixed] $haystack the array of values to search. - * @return bool true if $needle is present in the values of $haystack, false otherwise. + * @param mixed $needle the value to look for in $haystack + * @param array[mixed] $haystack the array of values to search. + * @return bool true if $needle is present in the values of $haystack, false otherwise. */ 'in' => function ($needle, $haystack) { return in_array($needle, $haystack); @@ -277,32 +282,33 @@ public function register(ContainerInterface $container) /** * Check if the specified user (by user_id) is in a particular group. * - * @param int $user_id the id of the user. - * @param int $group_id the id of the group. + * @param int $user_id the id of the user. + * @param int $group_id the id of the group. * @return bool true if the user is in the group, false otherwise. */ 'in_group' => function ($user_id, $group_id) { $user = User::find($user_id); - return ($user->group_id == $group_id); + + return $user->group_id == $group_id; }, /** * Check if the specified user (by user_id) is the master user. * - * @param int $user_id the id of the user. + * @param int $user_id the id of the user. * @return bool true if the user id is equal to the id of the master account, false otherwise. */ 'is_master' => function ($user_id) use ($config) { // Need to use loose comparison for now, because some DBs return `id` as a string - return ($user_id == $config['reserved_user_ids.master']); + return $user_id == $config['reserved_user_ids.master']; }, /** * Check if all values in the array $needle are present in the values of $haystack. * - * @param array[mixed] $needle the array whose values we should look for in $haystack - * @param array[mixed] $haystack the array of values to search. - * @return bool true if every value in $needle is present in the values of $haystack, false otherwise. + * @param array[mixed] $needle the array whose values we should look for in $haystack + * @param array[mixed] $haystack the array of values to search. + * @return bool true if every value in $needle is present in the values of $haystack, false otherwise. */ 'subset' => function ($needle, $haystack) { return count($needle) == count(array_intersect($needle, $haystack)); @@ -312,9 +318,9 @@ public function register(ContainerInterface $container) * Check if all keys of the array $needle are present in the values of $haystack. * * This function is useful for whitelisting an array of key-value parameters. - * @param array[mixed] $needle the array whose keys we should look for in $haystack - * @param array[mixed] $haystack the array of values to search. - * @return bool true if every key in $needle is present in the values of $haystack, false otherwise. + * @param array[mixed] $needle the array whose keys we should look for in $haystack + * @param array[mixed] $haystack the array of values to search. + * @return bool true if every key in $needle is present in the values of $haystack, false otherwise. */ 'subset_keys' => function ($needle, $haystack) { return count($needle) == count(array_intersect(array_keys($needle), $haystack)); @@ -322,6 +328,7 @@ public function register(ContainerInterface $container) ]; $authorizer = new AuthorizationManager($c, $callbacks); + return $authorizer; }; @@ -349,6 +356,7 @@ public function register(ContainerInterface $container) */ $container['passwordHasher'] = function ($c) { $hasher = new Hasher(); + return $hasher; }; @@ -362,9 +370,9 @@ public function register(ContainerInterface $container) * This method is invoked when a user attempts to perform certain public actions when they are already logged in. * * @todo Forward to user's landing page or last visited page - * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response - * @param array $args + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Message\ResponseInterface $response + * @param array $args * @return \Psr\Http\Message\ResponseInterface */ return function (Request $request, Response $response, array $args) use ($c) { @@ -384,9 +392,9 @@ public function register(ContainerInterface $container) * This method is invoked when a user completes the login process. * * Returns a callback that handles setting the `UF-Redirect` header after a successful login. - * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response - * @param array $args + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Message\ResponseInterface $response + * @param array $args * @return \Psr\Http\Message\ResponseInterface */ return function (Request $request, Response $response, array $args) use ($c) { @@ -420,6 +428,7 @@ public function register(ContainerInterface $container) $config = $c->config; $repo = new PasswordResetRepository($classMapper, $config['password_reset.algorithm']); + return $repo; }; @@ -433,6 +442,7 @@ public function register(ContainerInterface $container) $config = $c->config; $repo = new VerificationRepository($classMapper, $config['verification.algorithm']); + return $repo; }; diff --git a/app/sprinkles/account/src/Twig/AccountExtension.php b/app/sprinkles/account/src/Twig/AccountExtension.php index e74f7991a..1c9dbd003 100644 --- a/app/sprinkles/account/src/Twig/AccountExtension.php +++ b/app/sprinkles/account/src/Twig/AccountExtension.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Twig; use Interop\Container\ContainerInterface; @@ -43,7 +44,7 @@ public function getName() public function getFunctions() { - return array( + return [ // Add Twig function for checking permissions during dynamic menu rendering new \Twig_SimpleFunction('checkAccess', function ($slug, $params = []) { $authorizer = $this->services->authorizer; @@ -53,9 +54,10 @@ public function getFunctions() }), new \Twig_SimpleFunction('checkAuthenticated', function () { $authenticator = $this->services->authenticator; + return $authenticator->check(); }) - ); + ]; } public function getGlobals() diff --git a/app/sprinkles/account/src/Util/HashFailedException.php b/app/sprinkles/account/src/Util/HashFailedException.php index a0b37d173..765096b8b 100644 --- a/app/sprinkles/account/src/Util/HashFailedException.php +++ b/app/sprinkles/account/src/Util/HashFailedException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Util; use UserFrosting\Support\Exception\HttpException; diff --git a/app/sprinkles/account/src/Util/Util.php b/app/sprinkles/account/src/Util/Util.php index 5b9c42301..da1abfd26 100644 --- a/app/sprinkles/account/src/Util/Util.php +++ b/app/sprinkles/account/src/Util/Util.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Util; use UserFrosting\Sprinkle\Core\Util\ClassMapper; @@ -22,9 +23,9 @@ class Util /** * Generate a random, unique username from a list of adjectives and nouns. * - * @param ClassMapper $classMapper - * @param int $maxLength - * @param int $maxTries + * @param ClassMapper $classMapper + * @param int $maxLength + * @param int $maxTries * @return string */ public static function randomUniqueUsername(ClassMapper $classMapper, $maxLength, $maxTries = 10) diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index c45ac1f53..31686ab56 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -1,11 +1,16 @@ getAuthenticator(); $this->assertInstanceOf(Authenticator::class, $authenticator); + return $authenticator; } @@ -263,7 +269,7 @@ public function testAttempt_withFlagEnabledFalse(Authenticator $authenticator) { $password = 'FooBar'; $testUser = $this->createTestUser(false, false, [ - 'password' => Password::hash($password), + 'password' => Password::hash($password), 'flag_enabled' => 0 ]); @@ -280,7 +286,7 @@ public function testAttempt_withFlagVerifiedFalse(Authenticator $authenticator) { $password = 'FooBar'; $testUser = $this->createTestUser(false, false, [ - 'password' => Password::hash($password), + 'password' => Password::hash($password), 'flag_verified' => 0 ]); @@ -302,7 +308,7 @@ public function testAttempt_withFlagVerifiedFalseNoEmailVerification(Authenticat $password = 'FooBar'; $testUser = $this->createTestUser(false, false, [ - 'password' => Password::hash($password), + 'password' => Password::hash($password), 'flag_verified' => 0 ]); diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index 4ec120d2e..f9c46a6a5 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -1,4 +1,10 @@ getManager(); $this->assertInstanceOf(AuthorizationManager::class, $manager); + return $manager; } /** * @depends testConstructor - * @param AuthorizationManager $manager + * @param AuthorizationManager $manager */ public function testAddCallback(AuthorizationManager $manager) { $this->assertEmpty($manager->getCallbacks()); - $this->assertInstanceOf(AuthorizationManager::class, $manager->addCallback('foo', function () {})); + $this->assertInstanceOf(AuthorizationManager::class, $manager->addCallback('foo', function () { + })); $callbacks = $manager->getCallbacks(); $this->assertNotEmpty($callbacks); - $this->assertEquals(['foo' => function () {}], $callbacks); + $this->assertEquals(['foo' => function () { + }], $callbacks); } /** @@ -70,8 +79,8 @@ public function testService() /** * @depends testConstructor * @expectedException \ArgumentCountError - * @param AuthorizationManager $manager - * REQUIRES PHP 7.1 or better + * @param AuthorizationManager $manager + * REQUIRES PHP 7.1 or better */ /*public function testCheckAccess_withOutUser(AuthorizationManager $manager) { @@ -83,7 +92,7 @@ public function testService() */ public function testCheckAccess_withNullUser() { - $this->getMockAuthLogger()->shouldReceive('debug')->once()->with("No user defined. Access denied."); + $this->getMockAuthLogger()->shouldReceive('debug')->once()->with('No user defined. Access denied.'); $this->assertFalse($this->getManager()->checkAccess(null, 'foo')); } @@ -92,18 +101,18 @@ public function testCheckAccess_withNullUser() */ public function testCheckAccess_withBadUserType() { - $this->getMockAuthLogger()->shouldReceive('debug')->once()->with("No user defined. Access denied."); + $this->getMockAuthLogger()->shouldReceive('debug')->once()->with('No user defined. Access denied.'); $this->assertFalse($this->getManager()->checkAccess(123, 'foo')); } /** * By default, `checkAccess` is null. Test to make sure we don't break the - * "current user is guest" thing + * "current user is guest" thing * @depends testCheckAccess_withNullUser */ public function testCheckAccess_withNullCurrentUser() { - $this->getMockAuthLogger()->shouldReceive('debug')->once()->with("No user defined. Access denied."); + $this->getMockAuthLogger()->shouldReceive('debug')->once()->with('No user defined. Access denied.'); $user = $this->ci->currentUser; $this->assertNull($user); $this->assertFalse($this->getManager()->checkAccess($user, 'foo')); @@ -118,7 +127,7 @@ public function testCheckAccess_withNormalUser() // Setup authLogger expectations $authLogger = $this->getMockAuthLogger(); - $authLogger->shouldReceive('debug')->once()->with("No matching permissions found. Access denied."); + $authLogger->shouldReceive('debug')->once()->with('No matching permissions found. Access denied.'); $authLogger->shouldReceive('debug')->times(2); $this->assertFalse($this->getManager()->checkAccess($user, 'foo')); @@ -136,7 +145,7 @@ public function testCheckAccess_withCurrentUser() // Setup authLogger expectations $authLogger = $this->getMockAuthLogger(); - $authLogger->shouldReceive('debug')->once()->with("No matching permissions found. Access denied."); + $authLogger->shouldReceive('debug')->once()->with('No matching permissions found. Access denied.'); $authLogger->shouldReceive('debug')->times(2); $this->assertFalse($this->getManager()->checkAccess($this->ci->currentUser, 'foo')); @@ -152,7 +161,7 @@ public function testCheckAccess_withMasterUser() // Setup authLogger expectations $authLogger = $this->getMockAuthLogger(); - $authLogger->shouldReceive('debug')->once()->with("User is the master (root) user. Access granted."); + $authLogger->shouldReceive('debug')->once()->with('User is the master (root) user. Access granted.'); $authLogger->shouldReceive('debug')->times(2); $this->assertTrue($this->getManager()->checkAccess($user, 'foo')); @@ -187,7 +196,7 @@ public function testCheckAccess_withNormalUserWithFailedPermission() // Setup authLogger expectations $authLogger = $this->getMockAuthLogger(); - $authLogger->shouldReceive('debug')->once()->with("User failed to pass any of the matched permissions. Access denied."); + $authLogger->shouldReceive('debug')->once()->with('User failed to pass any of the matched permissions. Access denied.'); $authLogger->shouldReceive('debug')->times(7); $this->assertFalse($this->ci->authorizer->checkAccess($user, 'foo')); @@ -210,6 +219,7 @@ protected function getMockAuthLogger() { $this->ci->config['debug.auth'] = true; $this->ci->authLogger = m::mock('\Monolog\Logger'); + return $this->ci->authLogger; } } diff --git a/app/sprinkles/account/tests/Unit/FactoriesTest.php b/app/sprinkles/account/tests/Unit/FactoriesTest.php index 7be1843e8..c771058d9 100644 --- a/app/sprinkles/account/tests/Unit/FactoriesTest.php +++ b/app/sprinkles/account/tests/Unit/FactoriesTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Tests\Unit; use UserFrosting\Tests\TestCase; diff --git a/app/sprinkles/account/tests/Unit/HasherTest.php b/app/sprinkles/account/tests/Unit/HasherTest.php index 3f60ec67f..57a444d93 100644 --- a/app/sprinkles/account/tests/Unit/HasherTest.php +++ b/app/sprinkles/account/tests/Unit/HasherTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Unit; use UserFrosting\Sprinkle\Account\Authenticate\Hasher; @@ -40,7 +41,7 @@ class HasherTest extends TestCase */ public function testGetHashType() { - $hasher = new Hasher; + $hasher = new Hasher(); $type = $hasher->getHashType($this->modernHash); @@ -60,7 +61,7 @@ public function testGetHashType() */ public function testVerify() { - $hasher = new Hasher; + $hasher = new Hasher(); $this->assertTrue($hasher->verify($this->plainText, $this->modernHash)); $this->assertTrue($hasher->verify($this->plainText, $this->legacyHash)); @@ -72,7 +73,7 @@ public function testVerify() */ public function testVerifyReject() { - $hasher = new Hasher; + $hasher = new Hasher(); $this->assertFalse($hasher->verify('selleth', $this->modernHash)); $this->assertFalse($hasher->verify('selleth', $this->legacyHash)); diff --git a/app/sprinkles/account/tests/Unit/RegistrationTest.php b/app/sprinkles/account/tests/Unit/RegistrationTest.php index 06cc18f38..ff892a42a 100644 --- a/app/sprinkles/account/tests/Unit/RegistrationTest.php +++ b/app/sprinkles/account/tests/Unit/RegistrationTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Unit; use Mockery as m; diff --git a/app/sprinkles/account/tests/withTestUser.php b/app/sprinkles/account/tests/withTestUser.php index ab0730aac..53a19d00a 100644 --- a/app/sprinkles/account/tests/withTestUser.php +++ b/app/sprinkles/account/tests/withTestUser.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Account\Tests; use UserFrosting\Sprinkle\Account\Database\Models\User; @@ -42,9 +43,9 @@ protected function logoutCurrentUser() /** * Create a test user with no settings/permissions for a controller test - * @param bool $isMaster Does this user have root access? Will bypass all permissions - * @param bool $login Login this user, setting him as the currentUser - * @param array $params User account params + * @param bool $isMaster Does this user have root access? Will bypass all permissions + * @param bool $login Login this user, setting him as the currentUser + * @param array $params User account params * @return User */ protected function createTestUser($isMaster = false, $login = false, array $params = []) @@ -55,7 +56,7 @@ protected function createTestUser($isMaster = false, $login = false, array $para $user_id = rand(0, 1222); } - $params = array_merge(["id" => $user_id], $params); + $params = array_merge(['id' => $user_id], $params); $fm = $this->ci->factory; $user = $fm->create(User::class, $params); @@ -70,17 +71,17 @@ protected function createTestUser($isMaster = false, $login = false, array $para /** * Gives a user a new test permission * @param UserInterface $user - * @param string $slug - * @param string $conditions + * @param string $slug + * @param string $conditions * @return Permission */ - protected function giveUserTestPermission(UserInterface $user, $slug, $conditions = "always()") + protected function giveUserTestPermission(UserInterface $user, $slug, $conditions = 'always()') { - /** @var \League\FactoryMuffin\FactoryMuffin $fm **/ + /** @var \League\FactoryMuffin\FactoryMuffin $fm */ $fm = $this->ci->factory; $permission = $fm->create(Permission::class, [ - 'slug' => $slug, + 'slug' => $slug, 'conditions' => $conditions ]); @@ -98,12 +99,13 @@ protected function giveUserTestPermission(UserInterface $user, $slug, $condition */ protected function giveUserPermission(UserInterface $user, Permission $permission) { - /** @var \League\FactoryMuffin\FactoryMuffin $fm **/ + /** @var \League\FactoryMuffin\FactoryMuffin $fm */ $fm = $this->ci->factory; $role = $fm->create(Role::class); $role->permissions()->attach($permission); $user->roles()->attach($role); + return $role; } } diff --git a/app/sprinkles/admin/locale/ar/messages.php b/app/sprinkles/admin/locale/ar/messages.php index d4a3a446d..0ec2e401a 100644 --- a/app/sprinkles/admin/locale/ar/messages.php +++ b/app/sprinkles/admin/locale/ar/messages.php @@ -4,132 +4,132 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Modern Standard Arabic message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\ar * @author Alexander Weissman and Abdullah Seba */ - return [ - "ACTIVITY" => [ - 1 => "نشاط", - 2 => "أنشطة", + 'ACTIVITY' => [ + 1 => 'نشاط', + 2 => 'أنشطة', - "LAST" => "النشاط الاخير", - "PAGE" => "قائمة من أنشطة المستخدم", - "TIME" => "وقت نشاط" + 'LAST' => 'النشاط الاخير', + 'PAGE' => 'قائمة من أنشطة المستخدم', + 'TIME' => 'وقت نشاط' ], - "CACHE" => [ - "CLEAR" => "مسح ذاكرة التخزين", - "CLEAR_CONFIRM" => "هل أنت متأكد أنك تريد مسح ذاكرة التخزين بالموقع؟", - "CLEAR_CONFIRM_YES" => "نعم، إمسح ذاكرة التخزين", - "CLEARED" => "تم مسح ذاكرة التخزين بنجاح" + 'CACHE' => [ + 'CLEAR' => 'مسح ذاكرة التخزين', + 'CLEAR_CONFIRM' => 'هل أنت متأكد أنك تريد مسح ذاكرة التخزين بالموقع؟', + 'CLEAR_CONFIRM_YES' => 'نعم، إمسح ذاكرة التخزين', + 'CLEARED' => 'تم مسح ذاكرة التخزين بنجاح' ], - "DASHBOARD" => "لوحة القيادة", - "NO_FEATURES_YET" => "لا يبدو أن أي ميزات تم إعدادها لهذا الحساب حتى الآن. ربما لم يتم تنفيذها بعد، أو ربما شخص نسي أن يعطيك الوصول. في كلتا الحالتين، نحن سعداء أن يكون لك على متن!", - "DELETE_MASTER" => "لا يمكنك حذف الحساب الرئيسي", - "DELETION_SUCCESSFUL" => "المستعمل {{user_name}} حذف بنجاح", - "DETAILS_UPDATED" => "جدد تفاصيل الحساب للمستخدم {{user_name}}", - "DISABLE_MASTER" => "لا يمكنك تعطيل الحساب الرئيسي", - "DISABLE_SUCCESSFUL" => "حساب المستخدم {{user_name}} عطيل بنجاح", - - "ENABLE_SUCCESSFUL" => "حساب المستخدم {{user_name}} مكين بنجاح", - - "GROUP" => [ - 1 => "مجموعة", - 2 => "مجموعات", - - "CREATE" => "إنشاء مجموعة", - "DELETE" => "حذف مجموعة", - "DELETE_CONFIRM" => "هل أنت متأكد أنك تريد حذف مجموعة {{name}}?", - "DELETE_YES" => "نعم، إحذف مجموعة", - "EDIT" => "تعديل مجموعة", - "ICON" => "رمز المجموعة", - "ICON_EXPLAIN" => "رمز المستخدمين في المجموعه", - "INFO_PAGE" => "صفحة معلومات المجموعة ل {{name}}", + 'DASHBOARD' => 'لوحة القيادة', + 'NO_FEATURES_YET' => 'لا يبدو أن أي ميزات تم إعدادها لهذا الحساب حتى الآن. ربما لم يتم تنفيذها بعد، أو ربما شخص نسي أن يعطيك الوصول. في كلتا الحالتين، نحن سعداء أن يكون لك على متن!', + 'DELETE_MASTER' => 'لا يمكنك حذف الحساب الرئيسي', + 'DELETION_SUCCESSFUL' => 'المستعمل {{user_name}} حذف بنجاح', + 'DETAILS_UPDATED' => 'جدد تفاصيل الحساب للمستخدم {{user_name}}', + 'DISABLE_MASTER' => 'لا يمكنك تعطيل الحساب الرئيسي', + 'DISABLE_SUCCESSFUL' => 'حساب المستخدم {{user_name}} عطيل بنجاح', + + 'ENABLE_SUCCESSFUL' => 'حساب المستخدم {{user_name}} مكين بنجاح', + + 'GROUP' => [ + 1 => 'مجموعة', + 2 => 'مجموعات', + + 'CREATE' => 'إنشاء مجموعة', + 'DELETE' => 'حذف مجموعة', + 'DELETE_CONFIRM' => 'هل أنت متأكد أنك تريد حذف مجموعة {{name}}?', + 'DELETE_YES' => 'نعم، إحذف مجموعة', + 'EDIT' => 'تعديل مجموعة', + 'ICON' => 'رمز المجموعة', + 'ICON_EXPLAIN' => 'رمز المستخدمين في المجموعه', + 'INFO_PAGE' => 'صفحة معلومات المجموعة ل {{name}}', //"MANAGE" => "Manage group", - "NAME" => "أسم المجموعة", - "NAME_EXPLAIN" => "ادخال اسم للمجموعة", - "PAGE_DESCRIPTION" => "قائمة المجموعات لموقعك يوفر أدوات لإدارة التحرير وحذف مجموعات" + 'NAME' => 'أسم المجموعة', + 'NAME_EXPLAIN' => 'ادخال اسم للمجموعة', + 'PAGE_DESCRIPTION' => 'قائمة المجموعات لموقعك يوفر أدوات لإدارة التحرير وحذف مجموعات' ], - "MANUALLY_ACTIVATED" => "تم تفعيل حساب{{user_name}}", - "MASTER_ACCOUNT_EXISTS" => "الحساب الرئيسي موجود بالفعل", - "MIGRATION" => [ - "REQUIRED" => "تحديث قاعدة البيانات مطلوب" + 'MANUALLY_ACTIVATED' => 'تم تفعيل حساب{{user_name}}', + 'MASTER_ACCOUNT_EXISTS' => 'الحساب الرئيسي موجود بالفعل', + 'MIGRATION' => [ + 'REQUIRED' => 'تحديث قاعدة البيانات مطلوب' ], - "PERMISSION" => [ - 1 => "الإذن", - 2 => "مأذونيات", + 'PERMISSION' => [ + 1 => 'الإذن', + 2 => 'مأذونيات', - "ASSIGN_NEW" => "تعيين إذن جديد", - "HOOK_CONDITION" => "الظروف", - "MANAGE" => "إدارة المأذونات", - "PAGE_DESCRIPTION" => "قائمة المأذونات لموقعك", - "UPDATE" => "تحديث المأذونات" + 'ASSIGN_NEW' => 'تعيين إذن جديد', + 'HOOK_CONDITION' => 'الظروف', + 'MANAGE' => 'إدارة المأذونات', + 'PAGE_DESCRIPTION' => 'قائمة المأذونات لموقعك', + 'UPDATE' => 'تحديث المأذونات' ], - "ROLE" => [ - 1 => "وظيفة", - 2 => "وظائف", - - "ASSIGN_NEW" => "تعيين دور جديد", - "CREATE" => "إنشاء دور", - "DELETE" => "حذف دور", - "DELETE_CONFIRM" => "هل أنت متأكد أنك تريد حذف الدور {{name}}?", - "DELETE_YES" => "نعم، حذف دور", - "EDIT" => "إدارة دور", - "INFO_PAGE" => "صفحة معلومات دور {{name}}", - "MANAGE" => "إدارة الوظائف", - "NAME" => "اسم", - "NAME_EXPLAIN" => "أدخل اسما للدور", - "PAGE_DESCRIPTION" => "قائمة الوظائف لموقعك", - "UPDATED" => "تحديث الوظائف" + 'ROLE' => [ + 1 => 'وظيفة', + 2 => 'وظائف', + + 'ASSIGN_NEW' => 'تعيين دور جديد', + 'CREATE' => 'إنشاء دور', + 'DELETE' => 'حذف دور', + 'DELETE_CONFIRM' => 'هل أنت متأكد أنك تريد حذف الدور {{name}}?', + 'DELETE_YES' => 'نعم، حذف دور', + 'EDIT' => 'إدارة دور', + 'INFO_PAGE' => 'صفحة معلومات دور {{name}}', + 'MANAGE' => 'إدارة الوظائف', + 'NAME' => 'اسم', + 'NAME_EXPLAIN' => 'أدخل اسما للدور', + 'PAGE_DESCRIPTION' => 'قائمة الوظائف لموقعك', + 'UPDATED' => 'تحديث الوظائف' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "معلومات الجهاز", - - "DB_NAME" => "اسم قاعدة البيانات", - "DB_VERSION" => "إصدار قاعدة البيانات", - "DIRECTORY" => "دليل المشروع", - "PHP_VERSION" => "الإصدار PHP", - "SERVER" => "برنامج الخادم", - "SPRINKLES" => "sprinkles المحمل", - "UF_VERSION" => "إصدار UserFrosting", - "URL" => "رابط قاعدة الموقع" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'معلومات الجهاز', + + 'DB_NAME' => 'اسم قاعدة البيانات', + 'DB_VERSION' => 'إصدار قاعدة البيانات', + 'DIRECTORY' => 'دليل المشروع', + 'PHP_VERSION' => 'الإصدار PHP', + 'SERVER' => 'برنامج الخادم', + 'SPRINKLES' => 'sprinkles المحمل', + 'UF_VERSION' => 'إصدار UserFrosting', + 'URL' => 'رابط قاعدة الموقع' ], - "USER" => [ - 1 => "مستخدم", - 2 => "المستخدمين", + 'USER' => [ + 1 => 'مستخدم', + 2 => 'المستخدمين', - "ADMIN" => [ - "CHANGE_PASSWORD" => "تغيير كلمة المرور للمستخدم", - "SEND_PASSWORD_LINK" => "إرسال المستخدم وصلة من شأنها أن تسمح لهم لاختيار كلمة المرور الخاصة بهم", - "SET_PASSWORD" => "تعيين كلمة المرور الخاصة بالمستخدم" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'تغيير كلمة المرور للمستخدم', + 'SEND_PASSWORD_LINK' => 'إرسال المستخدم وصلة من شأنها أن تسمح لهم لاختيار كلمة المرور الخاصة بهم', + 'SET_PASSWORD' => 'تعيين كلمة المرور الخاصة بالمستخدم' ], - "ACTIVATE" => "تفعيل المستخدم", - "CREATE" => "إنشاء مستخدم", - "DELETE" => "مسح المستخدم", - "DELETE_CONFIRM" => "هل أنت متأكد أنك تريد حذف المستخدم {{name}}?", - "DELETE_YES" => "نعم، حذف المستخدم", - "DISABLE" => "تعطيل المستخدم ", - "EDIT" => "إدارة المستخدم", - "ENABLE" => "تمكين المستخدم", - "INFO_PAGE" => "صفحة معلومات المستخدم {{name}}", - "PAGE_DESCRIPTION" => "قائمة المستخدمين لموقعك", - "LATEST" => "أحدث المستخدمين", - "VIEW_ALL" => "عرض جميع المستخدمين" + 'ACTIVATE' => 'تفعيل المستخدم', + 'CREATE' => 'إنشاء مستخدم', + 'DELETE' => 'مسح المستخدم', + 'DELETE_CONFIRM' => 'هل أنت متأكد أنك تريد حذف المستخدم {{name}}?', + 'DELETE_YES' => 'نعم، حذف المستخدم', + 'DISABLE' => 'تعطيل المستخدم ', + 'EDIT' => 'إدارة المستخدم', + 'ENABLE' => 'تمكين المستخدم', + 'INFO_PAGE' => 'صفحة معلومات المستخدم {{name}}', + 'PAGE_DESCRIPTION' => 'قائمة المستخدمين لموقعك', + 'LATEST' => 'أحدث المستخدمين', + 'VIEW_ALL' => 'عرض جميع المستخدمين' ], - "X_USER" => [ - 0 => "لا يوجد اي مستخدمين", - 1 => "{{plural}} مستخدم", - 2 => "{{plural}} المستخدمين" + 'X_USER' => [ + 0 => 'لا يوجد اي مستخدمين', + 1 => '{{plural}} مستخدم', + 2 => '{{plural}} المستخدمين' ] ]; diff --git a/app/sprinkles/admin/locale/de_DE/messages.php b/app/sprinkles/admin/locale/de_DE/messages.php index 6e21ab503..710eb00e3 100644 --- a/app/sprinkles/admin/locale/de_DE/messages.php +++ b/app/sprinkles/admin/locale/de_DE/messages.php @@ -4,158 +4,158 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * German message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\de * @author X-Anonymous-Y * @author kevinrombach * @author splitt3r */ - return [ - "ACTIVITY" => [ - 1 => "Aktivität", - 2 => "Aktivitäten", + 'ACTIVITY' => [ + 1 => 'Aktivität', + 2 => 'Aktivitäten', - "LAST" => "Letzte Aktivität", - "PAGE" => "Eine Auflistung der Benutzeraktivitäten", - "TIME" => "Aktivitätszeit" + 'LAST' => 'Letzte Aktivität', + 'PAGE' => 'Eine Auflistung der Benutzeraktivitäten', + 'TIME' => 'Aktivitätszeit' ], - "CACHE" => [ - "CLEAR" => "Cache löschen", - "CLEAR_CONFIRM" => "Sind Sie sicher, dass Sie den Seiten-Cache löschen möchten?", - "CLEAR_CONFIRM_YES" => "Ja, Cache löschen", - "CLEARED" => "Cache wurde erfolgreich gelöscht!" + 'CACHE' => [ + 'CLEAR' => 'Cache löschen', + 'CLEAR_CONFIRM' => 'Sind Sie sicher, dass Sie den Seiten-Cache löschen möchten?', + 'CLEAR_CONFIRM_YES' => 'Ja, Cache löschen', + 'CLEARED' => 'Cache wurde erfolgreich gelöscht!' ], - "DASHBOARD" => "Übersicht", - "NO_FEATURES_YET" => "Es sieht aus, als wären für Ihren Account noch keine Funktionen aktiviert... bisher. Entweder sie wurden bisher noch nicht implementiert, oder Ihnen fehlen noch die Berechtigungen. Trotzdem ist es schön, dass Sie auf unsere Seite gekommen sind!", - "DELETE_MASTER" => "Sie können das Root-Konto nicht löschen!", - "DELETION_SUCCESSFUL" => "Benutzer {{user_name}} wurde erfolgreich gelöscht.", - "DETAILS_UPDATED" => "Konto-Daten für {{user_name}} aktualisiert.", - "DISABLE_MASTER" => "Sie können das Root-Konto nicht deaktivieren!", - "DISABLE_SELF" => "Sie können Ihr eigenes Konto nicht deaktivieren!", - "DISABLE_SUCCESSFUL" => "Konto von {{user_name}} wurde erfolgreich deaktiviert.", - - "ENABLE_SUCCESSFUL" => "Konto von {{user_name}} wurde erfolgreich aktiviert.", - - "GROUP" => [ - 1 => "Gruppe", - 2 => "Gruppen", - - "CREATE" => "Gruppe erstellen", - "CREATION_SUCCESSFUL" => "Die Gruppe {{name}} wurde erfolgreich erstellt", - "DELETE" => "Gruppe löschen", - "DELETE_CONFIRM" => "Möchten Sie die Gruppe {{name}} wirklich löschen?", - "DELETE_DEFAULT" => "Sie können die Gruppe {{name}} nicht löschen, da es die Standardgruppe für neu registrierte Benutzer ist.", - "DELETE_YES" => "Ja, Gruppe löschen", - "DELETION_SUCCESSFUL" => "Die Gruppe {{name}} wurde erfolgreich gelöscht", - "EDIT" => "Gruppe bearbeiten", - "ICON" => "Gruppensymbol", - "ICON_EXPLAIN" => "Symbol für Gruppenmitglieder", - "INFO_PAGE" => "Gruppeninformationsseite für {{name}}", - "MANAGE" => "Gruppe verwalten", - "NAME" => "Gruppenname", - "NAME_EXPLAIN" => "Geben Sie einen Namen für die Gruppe ein", - "NOT_EMPTY" => "Sie können das nicht tun, denn es sind noch Benutzer mit der Gruppe {{name}} verbunden.", - "PAGE_DESCRIPTION" => "Eine Liste der Gruppen für Ihre Website. Bietet Verwaltungstools für das Bearbeiten und Löschen von Gruppen.", - "SUMMARY" => "Gruppen Zusammenfassung", - "UPDATE" => "Details für die Gruppe {{name}} aktualisiert" + 'DASHBOARD' => 'Übersicht', + 'NO_FEATURES_YET' => 'Es sieht aus, als wären für Ihren Account noch keine Funktionen aktiviert... bisher. Entweder sie wurden bisher noch nicht implementiert, oder Ihnen fehlen noch die Berechtigungen. Trotzdem ist es schön, dass Sie auf unsere Seite gekommen sind!', + 'DELETE_MASTER' => 'Sie können das Root-Konto nicht löschen!', + 'DELETION_SUCCESSFUL' => 'Benutzer {{user_name}} wurde erfolgreich gelöscht.', + 'DETAILS_UPDATED' => 'Konto-Daten für {{user_name}} aktualisiert.', + 'DISABLE_MASTER' => 'Sie können das Root-Konto nicht deaktivieren!', + 'DISABLE_SELF' => 'Sie können Ihr eigenes Konto nicht deaktivieren!', + 'DISABLE_SUCCESSFUL' => 'Konto von {{user_name}} wurde erfolgreich deaktiviert.', + + 'ENABLE_SUCCESSFUL' => 'Konto von {{user_name}} wurde erfolgreich aktiviert.', + + 'GROUP' => [ + 1 => 'Gruppe', + 2 => 'Gruppen', + + 'CREATE' => 'Gruppe erstellen', + 'CREATION_SUCCESSFUL' => 'Die Gruppe {{name}} wurde erfolgreich erstellt', + 'DELETE' => 'Gruppe löschen', + 'DELETE_CONFIRM' => 'Möchten Sie die Gruppe {{name}} wirklich löschen?', + 'DELETE_DEFAULT' => 'Sie können die Gruppe {{name}} nicht löschen, da es die Standardgruppe für neu registrierte Benutzer ist.', + 'DELETE_YES' => 'Ja, Gruppe löschen', + 'DELETION_SUCCESSFUL' => 'Die Gruppe {{name}} wurde erfolgreich gelöscht', + 'EDIT' => 'Gruppe bearbeiten', + 'ICON' => 'Gruppensymbol', + 'ICON_EXPLAIN' => 'Symbol für Gruppenmitglieder', + 'INFO_PAGE' => 'Gruppeninformationsseite für {{name}}', + 'MANAGE' => 'Gruppe verwalten', + 'NAME' => 'Gruppenname', + 'NAME_EXPLAIN' => 'Geben Sie einen Namen für die Gruppe ein', + 'NOT_EMPTY' => 'Sie können das nicht tun, denn es sind noch Benutzer mit der Gruppe {{name}} verbunden.', + 'PAGE_DESCRIPTION' => 'Eine Liste der Gruppen für Ihre Website. Bietet Verwaltungstools für das Bearbeiten und Löschen von Gruppen.', + 'SUMMARY' => 'Gruppen Zusammenfassung', + 'UPDATE' => 'Details für die Gruppe {{name}} aktualisiert' ], - "MANUALLY_ACTIVATED" => "{{user_name}}'s Konto wurde manuell aktiviert.", - "MASTER_ACCOUNT_EXISTS" => "Das Root-Konto existiert bereits!", - "MIGRATION" => [ - "REQUIRED" => "Datenbankaktualisierung erforderlich" + 'MANUALLY_ACTIVATED' => "{{user_name}}'s Konto wurde manuell aktiviert.", + 'MASTER_ACCOUNT_EXISTS' => 'Das Root-Konto existiert bereits!', + 'MIGRATION' => [ + 'REQUIRED' => 'Datenbankaktualisierung erforderlich' ], - "PERMISSION" => [ - 1 => "Berechtigung", - 2 => "Berechtigungen", - - "ASSIGN_NEW" => "Neue Berechtigung zuweisen", - "HOOK_CONDITION" => "Haken/Bedingungen", - "ID" => "Berechtigungs-ID", - "INFO_PAGE" => "Berechtigungs Informationen für '{{name}}'", - "MANAGE" => "Berechtigungen verwalten", - "NOTE_READ_ONLY" => "Bitte beachten Sie: Berechtigungen werden als \"Teil des Quelltexts\" gesehen und können hier nicht bearbeitet werden. Um Berechtigungen hinzuzufügen, zu bearbeiten, oder zu löschen, benutzen Sie bitte folgende Dokumentation zur Datenbank Migration.", - "PAGE_DESCRIPTION" => "Eine Liste der Berechtigungen für Ihre Website. Bietet Verwaltungstools zum Bearbeiten und Löschen von Berechtigungen.", - "SUMMARY" => "Berechtigungs Zusammenfassung", - "UPDATE" => "Berechtigungen aktualisieren", - "VIA_ROLES" => "Besitzt die Berechtigung durch die Rolle" + 'PERMISSION' => [ + 1 => 'Berechtigung', + 2 => 'Berechtigungen', + + 'ASSIGN_NEW' => 'Neue Berechtigung zuweisen', + 'HOOK_CONDITION' => 'Haken/Bedingungen', + 'ID' => 'Berechtigungs-ID', + 'INFO_PAGE' => "Berechtigungs Informationen für '{{name}}'", + 'MANAGE' => 'Berechtigungen verwalten', + 'NOTE_READ_ONLY' => 'Bitte beachten Sie: Berechtigungen werden als "Teil des Quelltexts" gesehen und können hier nicht bearbeitet werden. Um Berechtigungen hinzuzufügen, zu bearbeiten, oder zu löschen, benutzen Sie bitte folgende Dokumentation zur Datenbank Migration.', + 'PAGE_DESCRIPTION' => 'Eine Liste der Berechtigungen für Ihre Website. Bietet Verwaltungstools zum Bearbeiten und Löschen von Berechtigungen.', + 'SUMMARY' => 'Berechtigungs Zusammenfassung', + 'UPDATE' => 'Berechtigungen aktualisieren', + 'VIA_ROLES' => 'Besitzt die Berechtigung durch die Rolle' ], - "ROLE" => [ - 1 => "Rolle", - 2 => "Rollen", - - "ASSIGN_NEW" => "Neue Rolle zuweisen", - "CREATE" => "Rolle erstellen", - "CREATION_SUCCESSFUL" => "Die Rolle {{name}} wurde erfolgreich erstellt", - "DELETE" => "Rolle löschen", - "DELETE_CONFIRM" => "Sind Sie sicher, dass Sie die Rolle {{name}} löschen möchten?", - "DELETE_DEFAULT" => "Sie können die Rolle {{name}} nicht löschen, da es eine Standardrolle für neu registrierte Benutzer ist.", - "DELETE_YES" => "Ja, Rolle löschen", - "DELETION_SUCCESSFUL" => "Die Rolle {{name}} wurde erfolgreich gelöscht", - "EDIT" => "Rolle bearbeiten", - "HAS_USERS" => "Sie können das nicht machen weil es noch Benutzer gibt, die die Rolle {{name}} haben.", - "INFO_PAGE" => "Rolleninformationsseite für {{name}}", - "MANAGE" => "Rollen verwalten", - "NAME" => "Name", - "NAME_EXPLAIN" => "Geben Sie einen Namen für die Rolle ein", - "NAME_IN_USE" => "Eine Rolle mit dem Namen {{name}} existiert bereits", - "PAGE_DESCRIPTION" => "Eine Liste der Rollen für Ihre Website. Bietet Verwaltungstools zum Bearbeiten und Löschen von Rollen.", - "PERMISSIONS_UPDATED" => "Berechtigungen für die Rolle {{name}} aktualisiert", - "SUMMARY" => "Rollen Zusammenfassung", - "UPDATED" => "Rollen aktualisieren" + 'ROLE' => [ + 1 => 'Rolle', + 2 => 'Rollen', + + 'ASSIGN_NEW' => 'Neue Rolle zuweisen', + 'CREATE' => 'Rolle erstellen', + 'CREATION_SUCCESSFUL' => 'Die Rolle {{name}} wurde erfolgreich erstellt', + 'DELETE' => 'Rolle löschen', + 'DELETE_CONFIRM' => 'Sind Sie sicher, dass Sie die Rolle {{name}} löschen möchten?', + 'DELETE_DEFAULT' => 'Sie können die Rolle {{name}} nicht löschen, da es eine Standardrolle für neu registrierte Benutzer ist.', + 'DELETE_YES' => 'Ja, Rolle löschen', + 'DELETION_SUCCESSFUL' => 'Die Rolle {{name}} wurde erfolgreich gelöscht', + 'EDIT' => 'Rolle bearbeiten', + 'HAS_USERS' => 'Sie können das nicht machen weil es noch Benutzer gibt, die die Rolle {{name}} haben.', + 'INFO_PAGE' => 'Rolleninformationsseite für {{name}}', + 'MANAGE' => 'Rollen verwalten', + 'NAME' => 'Name', + 'NAME_EXPLAIN' => 'Geben Sie einen Namen für die Rolle ein', + 'NAME_IN_USE' => 'Eine Rolle mit dem Namen {{name}} existiert bereits', + 'PAGE_DESCRIPTION' => 'Eine Liste der Rollen für Ihre Website. Bietet Verwaltungstools zum Bearbeiten und Löschen von Rollen.', + 'PERMISSIONS_UPDATED' => 'Berechtigungen für die Rolle {{name}} aktualisiert', + 'SUMMARY' => 'Rollen Zusammenfassung', + 'UPDATED' => 'Rollen aktualisieren' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "System Information", - - "DB_NAME" => "Name der Datenbank", - "DB_VERSION" => "Datenbankversion", - "DIRECTORY" => "Projektverzeichnis", - "PHP_VERSION" => "PHP-Version", - "SERVER" => "Web-Server-Software", - "SPRINKLES" => "Geladene Sprinkles", - "UF_VERSION" => "UserFrosting Version", - "URL" => "Website-Stamm-Url" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'System Information', + + 'DB_NAME' => 'Name der Datenbank', + 'DB_VERSION' => 'Datenbankversion', + 'DIRECTORY' => 'Projektverzeichnis', + 'PHP_VERSION' => 'PHP-Version', + 'SERVER' => 'Web-Server-Software', + 'SPRINKLES' => 'Geladene Sprinkles', + 'UF_VERSION' => 'UserFrosting Version', + 'URL' => 'Website-Stamm-Url' ], - "TOGGLE_COLUMNS" => "Spalten anpassen", + 'TOGGLE_COLUMNS' => 'Spalten anpassen', - "USER" => [ - 1 => "Benutzer", - 2 => "Benutzer", + 'USER' => [ + 1 => 'Benutzer', + 2 => 'Benutzer', - "ADMIN" => [ - "CHANGE_PASSWORD" => "Benutzerpasswort ändern", - "SEND_PASSWORD_LINK" => "Senden Sie dem Benutzer einen Link, der ihnen erlaubt, ihr eigenes Passwort zu wählen", - "SET_PASSWORD" => "Setzen Sie das Passwort des Benutzers als" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'Benutzerpasswort ändern', + 'SEND_PASSWORD_LINK' => 'Senden Sie dem Benutzer einen Link, der ihnen erlaubt, ihr eigenes Passwort zu wählen', + 'SET_PASSWORD' => 'Setzen Sie das Passwort des Benutzers als' ], - "ACTIVATE" => "Benutzer aktivieren", - "CREATE" => "Benutzer erstellen", - "CREATED" => "Benutzer {{user_name}} wurde erfolgreich erstellt", - "DELETE" => "Benutzer löschen", - "DELETE_CONFIRM" => "Sind Sie sicher, dass Sie den Benutzer {{name}} löschen möchten?", - "DELETE_YES" => "Ja, Benutzer löschen", - "DISABLE" => "Benutzer deaktivieren", - "EDIT" => "Benutzer bearbeiten", - "ENABLE" => "Benutzer aktivieren", - "INFO_PAGE" => "Benutzerinformationsseite für {{name}}", - "LATEST" => "Neueste Benutzer", - "PAGE_DESCRIPTION" => "Eine Liste der Benutzer für Ihre Website. Bietet Management-Tools, einschließlich der Möglichkeit, Benutzerdaten bearbeiten, manuell aktivieren, Benutzer aktivieren/deaktivieren, und vieles mehr.", - "SUMMARY" => "Benutzer Zusammenfassung", - "VIEW_ALL" => "Alle Benutzer anzeigen", - "WITH_PERMISSION" => "Benutzer mit dieser Berechtigung" + 'ACTIVATE' => 'Benutzer aktivieren', + 'CREATE' => 'Benutzer erstellen', + 'CREATED' => 'Benutzer {{user_name}} wurde erfolgreich erstellt', + 'DELETE' => 'Benutzer löschen', + 'DELETE_CONFIRM' => 'Sind Sie sicher, dass Sie den Benutzer {{name}} löschen möchten?', + 'DELETE_YES' => 'Ja, Benutzer löschen', + 'DISABLE' => 'Benutzer deaktivieren', + 'EDIT' => 'Benutzer bearbeiten', + 'ENABLE' => 'Benutzer aktivieren', + 'INFO_PAGE' => 'Benutzerinformationsseite für {{name}}', + 'LATEST' => 'Neueste Benutzer', + 'PAGE_DESCRIPTION' => 'Eine Liste der Benutzer für Ihre Website. Bietet Management-Tools, einschließlich der Möglichkeit, Benutzerdaten bearbeiten, manuell aktivieren, Benutzer aktivieren/deaktivieren, und vieles mehr.', + 'SUMMARY' => 'Benutzer Zusammenfassung', + 'VIEW_ALL' => 'Alle Benutzer anzeigen', + 'WITH_PERMISSION' => 'Benutzer mit dieser Berechtigung' ], - "X_USER" => [ - 0 => "Keine Benutzer", - 1 => "{{plural}} Benutzer", - 2 => "{{plural}} Benutzer" + 'X_USER' => [ + 0 => 'Keine Benutzer', + 1 => '{{plural}} Benutzer', + 2 => '{{plural}} Benutzer' ] ]; diff --git a/app/sprinkles/admin/locale/en_US/messages.php b/app/sprinkles/admin/locale/en_US/messages.php index a21e32525..ce3de1c34 100644 --- a/app/sprinkles/admin/locale/en_US/messages.php +++ b/app/sprinkles/admin/locale/en_US/messages.php @@ -4,157 +4,157 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * US English message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\en_US * @author Alexander Weissman */ - return [ - "ACTIVITY" => [ - 1 => "Activity", - 2 => "Activities", + 'ACTIVITY' => [ + 1 => 'Activity', + 2 => 'Activities', - "LAST" => "Last Activity", - "PAGE" => "A listing of user activities", - "TIME" => "Activity Time" + 'LAST' => 'Last Activity', + 'PAGE' => 'A listing of user activities', + 'TIME' => 'Activity Time' ], - "CACHE" => [ - "CLEAR" => "Clear cache", - "CLEAR_CONFIRM" => "Are you sure you want to clear the site cache?", - "CLEAR_CONFIRM_YES" => "Yes, clear cache", - "CLEARED" => "Cache cleared successfully !" + 'CACHE' => [ + 'CLEAR' => 'Clear cache', + 'CLEAR_CONFIRM' => 'Are you sure you want to clear the site cache?', + 'CLEAR_CONFIRM_YES' => 'Yes, clear cache', + 'CLEARED' => 'Cache cleared successfully !' ], - "DASHBOARD" => "Dashboard", - "NO_FEATURES_YET" => "It doesn't look like any features have been set up for this account...yet. Maybe they haven't been implemented yet, or maybe someone forgot to give you access. Either way, we're glad to have you aboard!", - "DELETE_MASTER" => "You cannot delete the master account!", - "DELETION_SUCCESSFUL" => "User {{user_name}} has been successfully deleted.", - "DETAILS_UPDATED" => "Account details updated for user {{user_name}}", - "DISABLE_MASTER" => "You cannot disable the master account!", - "DISABLE_SELF" => "You cannot disable your own account!", - "DISABLE_SUCCESSFUL" => "Account for user {{user_name}} has been successfully disabled.", - - "ENABLE_SUCCESSFUL" => "Account for user {{user_name}} has been successfully enabled.", - - "GROUP" => [ - 1 => "Group", - 2 => "Groups", - - "CREATE" => "Create group", - "CREATION_SUCCESSFUL" => "Successfully created group {{name}}", - "DELETE" => "Delete group", - "DELETE_CONFIRM" => "Are you sure you want to delete the group {{name}}?", - "DELETE_DEFAULT" => "You can't delete the group {{name}} because it is the default group for newly registered users.", - "DELETE_YES" => "Yes, delete group", - "DELETION_SUCCESSFUL" => "Successfully deleted group {{name}}", - "EDIT" => "Edit group", - "ICON" => "Group icon", - "ICON_EXPLAIN" => "Icon for group members", - "INFO_PAGE" => "Group information page for {{name}}", - "MANAGE" => "Manage group", - "NAME" => "Group name", - "NAME_EXPLAIN" => "Please enter a name for the group", - "NOT_EMPTY" => "You can't do that because there are still users associated with the group {{name}}.", - "PAGE_DESCRIPTION" => "A listing of the groups for your site. Provides management tools for editing and deleting groups.", - "SUMMARY" => "Group Summary", - "UPDATE" => "Details updated for group {{name}}" + 'DASHBOARD' => 'Dashboard', + 'NO_FEATURES_YET' => "It doesn't look like any features have been set up for this account...yet. Maybe they haven't been implemented yet, or maybe someone forgot to give you access. Either way, we're glad to have you aboard!", + 'DELETE_MASTER' => 'You cannot delete the master account!', + 'DELETION_SUCCESSFUL' => 'User {{user_name}} has been successfully deleted.', + 'DETAILS_UPDATED' => 'Account details updated for user {{user_name}}', + 'DISABLE_MASTER' => 'You cannot disable the master account!', + 'DISABLE_SELF' => 'You cannot disable your own account!', + 'DISABLE_SUCCESSFUL' => 'Account for user {{user_name}} has been successfully disabled.', + + 'ENABLE_SUCCESSFUL' => 'Account for user {{user_name}} has been successfully enabled.', + + 'GROUP' => [ + 1 => 'Group', + 2 => 'Groups', + + 'CREATE' => 'Create group', + 'CREATION_SUCCESSFUL' => 'Successfully created group {{name}}', + 'DELETE' => 'Delete group', + 'DELETE_CONFIRM' => 'Are you sure you want to delete the group {{name}}?', + 'DELETE_DEFAULT' => "You can't delete the group {{name}} because it is the default group for newly registered users.", + 'DELETE_YES' => 'Yes, delete group', + 'DELETION_SUCCESSFUL' => 'Successfully deleted group {{name}}', + 'EDIT' => 'Edit group', + 'ICON' => 'Group icon', + 'ICON_EXPLAIN' => 'Icon for group members', + 'INFO_PAGE' => 'Group information page for {{name}}', + 'MANAGE' => 'Manage group', + 'NAME' => 'Group name', + 'NAME_EXPLAIN' => 'Please enter a name for the group', + 'NOT_EMPTY' => "You can't do that because there are still users associated with the group {{name}}.", + 'PAGE_DESCRIPTION' => 'A listing of the groups for your site. Provides management tools for editing and deleting groups.', + 'SUMMARY' => 'Group Summary', + 'UPDATE' => 'Details updated for group {{name}}' ], - "MANUALLY_ACTIVATED" => "{{user_name}}'s account has been manually activated", - "MASTER_ACCOUNT_EXISTS" => "The master account already exists!", - "MIGRATION" => [ - "REQUIRED" => "Database update required" + 'MANUALLY_ACTIVATED' => "{{user_name}}'s account has been manually activated", + 'MASTER_ACCOUNT_EXISTS' => 'The master account already exists!', + 'MIGRATION' => [ + 'REQUIRED' => 'Database update required' ], - "PERMISSION" => [ - 1 => "Permission", - 2 => "Permissions", - - "ASSIGN_NEW" => "Assign new permission", - "HOOK_CONDITION" => "Hook/Conditions", - "ID" => "Permission ID", - "INFO_PAGE" => "Permission information page for '{{name}}'", - "MANAGE" => "Manage permissions", - "NOTE_READ_ONLY" => "Please note: permissions are considered \"part of the code\" and cannot be modified through the interface. To add, remove, or modify permissions, the site maintainers will need to use a database migration.", - "PAGE_DESCRIPTION" => "A listing of the permissions for your site. Provides management tools for editing and deleting permissions.", - "SUMMARY" => "Permission Summary", - "UPDATE" => "Update permissions", - "VIA_ROLES" => "Has permission via roles" + 'PERMISSION' => [ + 1 => 'Permission', + 2 => 'Permissions', + + 'ASSIGN_NEW' => 'Assign new permission', + 'HOOK_CONDITION' => 'Hook/Conditions', + 'ID' => 'Permission ID', + 'INFO_PAGE' => "Permission information page for '{{name}}'", + 'MANAGE' => 'Manage permissions', + 'NOTE_READ_ONLY' => 'Please note: permissions are considered "part of the code" and cannot be modified through the interface. To add, remove, or modify permissions, the site maintainers will need to use a database migration.', + 'PAGE_DESCRIPTION' => 'A listing of the permissions for your site. Provides management tools for editing and deleting permissions.', + 'SUMMARY' => 'Permission Summary', + 'UPDATE' => 'Update permissions', + 'VIA_ROLES' => 'Has permission via roles' ], - "ROLE" => [ - 1 => "Role", - 2 => "Roles", - - "ASSIGN_NEW" => "Assign new role", - "CREATE" => "Create role", - "CREATION_SUCCESSFUL" => "Successfully created role {{name}}", - "DELETE" => "Delete role", - "DELETE_CONFIRM" => "Are you sure you want to delete the role {{name}}?", - "DELETE_DEFAULT" => "You can't delete the role {{name}} because it is a default role for newly registered users.", - "DELETE_YES" => "Yes, delete role", - "DELETION_SUCCESSFUL" => "Successfully deleted role {{name}}", - "EDIT" => "Edit role", - "HAS_USERS" => "You can't do that because there are still users who have the role {{name}}.", - "INFO_PAGE" => "Role information page for {{name}}", - "MANAGE" => "Manage Roles", - "NAME" => "Name", - "NAME_EXPLAIN" => "Please enter a name for the role", - "NAME_IN_USE" => "A role named {{name}} already exist", - "PAGE_DESCRIPTION" => "A listing of the roles for your site. Provides management tools for editing and deleting roles.", - "PERMISSIONS_UPDATED" => "Permissions updated for role {{name}}", - "SUMMARY" => "Role Summary", - "UPDATED" => "Details updated for role {{name}}" + 'ROLE' => [ + 1 => 'Role', + 2 => 'Roles', + + 'ASSIGN_NEW' => 'Assign new role', + 'CREATE' => 'Create role', + 'CREATION_SUCCESSFUL' => 'Successfully created role {{name}}', + 'DELETE' => 'Delete role', + 'DELETE_CONFIRM' => 'Are you sure you want to delete the role {{name}}?', + 'DELETE_DEFAULT' => "You can't delete the role {{name}} because it is a default role for newly registered users.", + 'DELETE_YES' => 'Yes, delete role', + 'DELETION_SUCCESSFUL' => 'Successfully deleted role {{name}}', + 'EDIT' => 'Edit role', + 'HAS_USERS' => "You can't do that because there are still users who have the role {{name}}.", + 'INFO_PAGE' => 'Role information page for {{name}}', + 'MANAGE' => 'Manage Roles', + 'NAME' => 'Name', + 'NAME_EXPLAIN' => 'Please enter a name for the role', + 'NAME_IN_USE' => 'A role named {{name}} already exist', + 'PAGE_DESCRIPTION' => 'A listing of the roles for your site. Provides management tools for editing and deleting roles.', + 'PERMISSIONS_UPDATED' => 'Permissions updated for role {{name}}', + 'SUMMARY' => 'Role Summary', + 'UPDATED' => 'Details updated for role {{name}}' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "System information", - - "DB_NAME" => "Database name", - "DB_VERSION" => "Database version", - "DIRECTORY" => "Project directory", - "PHP_VERSION" => "PHP version", - "SERVER" => "Webserver software", - "SPRINKLES" => "Loaded sprinkles", - "UF_VERSION" => "UserFrosting version", - "URL" => "Site root url" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'System information', + + 'DB_NAME' => 'Database name', + 'DB_VERSION' => 'Database version', + 'DIRECTORY' => 'Project directory', + 'PHP_VERSION' => 'PHP version', + 'SERVER' => 'Webserver software', + 'SPRINKLES' => 'Loaded sprinkles', + 'UF_VERSION' => 'UserFrosting version', + 'URL' => 'Site root url' ], - "TOGGLE_COLUMNS" => "Toggle columns", + 'TOGGLE_COLUMNS' => 'Toggle columns', - "USER" => [ - 1 => "User", - 2 => "Users", + 'USER' => [ + 1 => 'User', + 2 => 'Users', - "ADMIN" => [ - "CHANGE_PASSWORD" => "Change User Password", - "SEND_PASSWORD_LINK" => "Send the user a link that will allow them to choose their own password", - "SET_PASSWORD" => "Set the user's password as" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'Change User Password', + 'SEND_PASSWORD_LINK' => 'Send the user a link that will allow them to choose their own password', + 'SET_PASSWORD' => "Set the user's password as" ], - "ACTIVATE" => "Activate user", - "CREATE" => "Create user", - "CREATED" => "User {{user_name}} has been successfully created", - "DELETE" => "Delete user", - "DELETE_CONFIRM" => "Are you sure you want to delete the user {{name}}?", - "DELETE_YES" => "Yes, delete user", - "DELETED" => "User deleted", - "DISABLE" => "Disable user", - "EDIT" => "Edit user", - "ENABLE" => "Enable user", - "INFO_PAGE" => "User information page for {{name}}", - "LATEST" => "Latest Users", - "PAGE_DESCRIPTION" => "A listing of the users for your site. Provides management tools including the ability to edit user details, manually activate users, enable/disable users, and more.", - "SUMMARY" => "Account Summary", - "VIEW_ALL" => "View all users", - "WITH_PERMISSION" => "Users with this permission" + 'ACTIVATE' => 'Activate user', + 'CREATE' => 'Create user', + 'CREATED' => 'User {{user_name}} has been successfully created', + 'DELETE' => 'Delete user', + 'DELETE_CONFIRM' => 'Are you sure you want to delete the user {{name}}?', + 'DELETE_YES' => 'Yes, delete user', + 'DELETED' => 'User deleted', + 'DISABLE' => 'Disable user', + 'EDIT' => 'Edit user', + 'ENABLE' => 'Enable user', + 'INFO_PAGE' => 'User information page for {{name}}', + 'LATEST' => 'Latest Users', + 'PAGE_DESCRIPTION' => 'A listing of the users for your site. Provides management tools including the ability to edit user details, manually activate users, enable/disable users, and more.', + 'SUMMARY' => 'Account Summary', + 'VIEW_ALL' => 'View all users', + 'WITH_PERMISSION' => 'Users with this permission' ], - "X_USER" => [ - 0 => "No users", - 1 => "{{plural}} user", - 2 => "{{plural}} users" + 'X_USER' => [ + 0 => 'No users', + 1 => '{{plural}} user', + 2 => '{{plural}} users' ] ]; diff --git a/app/sprinkles/admin/locale/es_ES/messages.php b/app/sprinkles/admin/locale/es_ES/messages.php index 1f8303fc5..96dd3ec41 100755 --- a/app/sprinkles/admin/locale/es_ES/messages.php +++ b/app/sprinkles/admin/locale/es_ES/messages.php @@ -4,161 +4,161 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Spanish message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\es_ES * @author rafa31gz */ - return [ - "ACTIVITY" => [ - 1 => "Actividad", - 2 => "Actividades", + 'ACTIVITY' => [ + 1 => 'Actividad', + 2 => 'Actividades', - "LAST" => "Última actividad", - "PAGE" => "Una lista de las actividades del usuario", - "TIME" => "Tiempo de Actividad" + 'LAST' => 'Última actividad', + 'PAGE' => 'Una lista de las actividades del usuario', + 'TIME' => 'Tiempo de Actividad' ], - "ADMIN" => [ - "PANEL" => "Panel de administración" + 'ADMIN' => [ + 'PANEL' => 'Panel de administración' ], - "CACHE" => [ - "CLEAR" => "Limpiar cache", - "CLEAR_CONFIRM" => "¿Estás seguro de que deseas borrar la caché del sitio?", - "CLEAR_CONFIRM_YES" => "Sí, borrar caché", - "CLEARED" => "¡Cache borrado correctamente!" + 'CACHE' => [ + 'CLEAR' => 'Limpiar cache', + 'CLEAR_CONFIRM' => '¿Estás seguro de que deseas borrar la caché del sitio?', + 'CLEAR_CONFIRM_YES' => 'Sí, borrar caché', + 'CLEARED' => '¡Cache borrado correctamente!' ], - "DASHBOARD" => "Tablero", - "NO_FEATURES_YET" => "No parece que se hayan configurado funciones para esta cuenta ... todavía. Tal vez no se han implementado todavía, o tal vez alguien se olvidó de darle acceso. De cualquier manera, ¡estamos encantados de tenerte a bordo!", - "DELETE_MASTER" => "¡No puedes eliminar la cuenta principal!", - "DELETION_SUCCESSFUL" => "El usuario {{user_name}} se ha eliminado correctamente.", - "DETAILS_UPDATED" => "Detalles de la cuenta actualizados para el usuario {{user_name}} ", - "DISABLE_MASTER" => "¡No puedes deshabilitar la cuenta principal!", - "DISABLE_SELF" => "¡No puedes inhabilitar tu propia cuenta!", - "DISABLE_SUCCESSFUL" => "La cuenta para el usuario {{user_name}} se ha desactivado correctamente.", - - "ENABLE_SUCCESSFUL" => "La cuenta para el usuario {{user_name}} se ha habilitado correctamente.", - - "GROUP" => [ - 1 => "Grupo", - 2 => "Grupos", - - "CREATE" => "Crear un grupo", - "CREATION_SUCCESSFUL" => "Grupo creado correctamente {{name}} ", - "DELETE" => "Borrar un grupo", - "DELETE_CONFIRM" => "¿Seguro que quieres eliminar el grupo {{name}} ?", - "DELETE_DEFAULT" => "No puedes eliminar el grupo {{name}} porque es el grupo predeterminado para los usuarios recién registrados.", - "DELETE_YES" => "Sí, eliminar grupo", - "DELETION_SUCCESSFUL" => "Grupo eliminado correctamente {{name}} ", - "EDIT" => "Editar grupo", - "ICON" => "Icono de grupo", - "ICON_EXPLAIN" => "Icono para los miembros del grupo", - "INFO_PAGE" => "Página de información de grupo para {{name}}", - "MANAGE" => "Administrar grupo", - "NAME" => "Nombre del grupo", - "NAME_EXPLAIN" => "Introduce un nombre para el grupo", - "NOT_EMPTY" => "No puedes hacerlo porque todavía hay usuarios asociados con el grupo {{name}} .", - "PAGE_DESCRIPTION" => "Un listado de los grupos para tu sitio. Proporciona herramientas de administración para editar y eliminar grupos.", - "SUMMARY" => "Resumen del grupo", - "UPDATE" => "Detalles actualizados para el grupo {{name}} " + 'DASHBOARD' => 'Tablero', + 'NO_FEATURES_YET' => 'No parece que se hayan configurado funciones para esta cuenta ... todavía. Tal vez no se han implementado todavía, o tal vez alguien se olvidó de darle acceso. De cualquier manera, ¡estamos encantados de tenerte a bordo!', + 'DELETE_MASTER' => '¡No puedes eliminar la cuenta principal!', + 'DELETION_SUCCESSFUL' => 'El usuario {{user_name}} se ha eliminado correctamente.', + 'DETAILS_UPDATED' => 'Detalles de la cuenta actualizados para el usuario {{user_name}} ', + 'DISABLE_MASTER' => '¡No puedes deshabilitar la cuenta principal!', + 'DISABLE_SELF' => '¡No puedes inhabilitar tu propia cuenta!', + 'DISABLE_SUCCESSFUL' => 'La cuenta para el usuario {{user_name}} se ha desactivado correctamente.', + + 'ENABLE_SUCCESSFUL' => 'La cuenta para el usuario {{user_name}} se ha habilitado correctamente.', + + 'GROUP' => [ + 1 => 'Grupo', + 2 => 'Grupos', + + 'CREATE' => 'Crear un grupo', + 'CREATION_SUCCESSFUL' => 'Grupo creado correctamente {{name}} ', + 'DELETE' => 'Borrar un grupo', + 'DELETE_CONFIRM' => '¿Seguro que quieres eliminar el grupo {{name}} ?', + 'DELETE_DEFAULT' => 'No puedes eliminar el grupo {{name}} porque es el grupo predeterminado para los usuarios recién registrados.', + 'DELETE_YES' => 'Sí, eliminar grupo', + 'DELETION_SUCCESSFUL' => 'Grupo eliminado correctamente {{name}} ', + 'EDIT' => 'Editar grupo', + 'ICON' => 'Icono de grupo', + 'ICON_EXPLAIN' => 'Icono para los miembros del grupo', + 'INFO_PAGE' => 'Página de información de grupo para {{name}}', + 'MANAGE' => 'Administrar grupo', + 'NAME' => 'Nombre del grupo', + 'NAME_EXPLAIN' => 'Introduce un nombre para el grupo', + 'NOT_EMPTY' => 'No puedes hacerlo porque todavía hay usuarios asociados con el grupo {{name}} .', + 'PAGE_DESCRIPTION' => 'Un listado de los grupos para tu sitio. Proporciona herramientas de administración para editar y eliminar grupos.', + 'SUMMARY' => 'Resumen del grupo', + 'UPDATE' => 'Detalles actualizados para el grupo {{name}} ' ], - "MANUALLY_ACTIVATED" => "La cuenta de {{user_name}} se ha activado manualmente", - "MASTER_ACCOUNT_EXISTS" => "¡La cuenta maestra ya existe!", - "MIGRATION" => [ - "REQUIRED" => "Se requiere actualizar la base de datos" + 'MANUALLY_ACTIVATED' => 'La cuenta de {{user_name}} se ha activado manualmente', + 'MASTER_ACCOUNT_EXISTS' => '¡La cuenta maestra ya existe!', + 'MIGRATION' => [ + 'REQUIRED' => 'Se requiere actualizar la base de datos' ], - "PERMISSION" => [ - 1 => "Permiso", - 2 => "Permisos", - - "ASSIGN_NEW" => "Asignar nuevo permiso", - "HOOK_CONDITION" => "Hook/Condiciones", - "ID" => "ID de permiso", - "INFO_PAGE" => "Página de autor del permiso de '{{name}}'", - "MANAGE" => "Administrar permisos", - "NOTE_READ_ONLY" => " Ten en cuenta: los permisos se consideran \"parte del código\" y no se pueden modificar a través de la interfaz. Para agregar, eliminar o modificar permisos, los mantenedores del sitio necesitarán usar una migración de la base de datos . ", - "PAGE_DESCRIPTION" => "Una lista de los permisos para tu sitio. Proporciona herramientas de administración para editar y eliminar permisos.", - "SUMMARY" => "Resumen del permiso", - "UPDATE" => "Actualizar permisos", - "VIA_ROLES" => "Tiene permiso para los roles" + 'PERMISSION' => [ + 1 => 'Permiso', + 2 => 'Permisos', + + 'ASSIGN_NEW' => 'Asignar nuevo permiso', + 'HOOK_CONDITION' => 'Hook/Condiciones', + 'ID' => 'ID de permiso', + 'INFO_PAGE' => "Página de autor del permiso de '{{name}}'", + 'MANAGE' => 'Administrar permisos', + 'NOTE_READ_ONLY' => ' Ten en cuenta: los permisos se consideran "parte del código" y no se pueden modificar a través de la interfaz. Para agregar, eliminar o modificar permisos, los mantenedores del sitio necesitarán usar una migración de la base de datos . ', + 'PAGE_DESCRIPTION' => 'Una lista de los permisos para tu sitio. Proporciona herramientas de administración para editar y eliminar permisos.', + 'SUMMARY' => 'Resumen del permiso', + 'UPDATE' => 'Actualizar permisos', + 'VIA_ROLES' => 'Tiene permiso para los roles' ], - "ROLE" => [ - 1 => "Rol(funcion)", - 2 => "Roles(funciones)", - - "ASSIGN_NEW" => "Asignar nueva rol", - "CREATE" => "Crear un rol", - "CREATION_SUCCESSFUL" => "Función creada correctamente {{name}} ", - "DELETE" => "Eliminar rol", - "DELETE_CONFIRM" => "¿Seguro que quieres eliminar la función {{name}} ?", - "DELETE_DEFAULT" => "No puedes eliminar el rol {{name}} porque es un rol predeterminado para los usuarios recién registrados.", - "DELETE_YES" => "Sí, borrar función", - "DELETION_SUCCESSFUL" => "Se ha eliminado la función {{nombre}} ", - "EDIT" => "Editar función", - "HAS_USERS" => "No puedes hacerlo porque todavía hay usuarios que tienen el rol {{name}} .", - "INFO_PAGE" => "Página de información de funciones de {{name}}", - "MANAGE" => "Administrar roles", - "NAME" => "Nombre", - "NAME_EXPLAIN" => "Ingresa un nombre para el rol", - "NAME_IN_USE" => "Ya existe un rol denominado {{name}} ", - "PAGE_DESCRIPTION" => "Una lista de las funciones de tu sitio. Proporciona herramientas de administración para editar y eliminar roles.", - "PERMISSIONS_UPDATED" => "Permisos actualizados para el rol {{name}} ", - "SUMMARY" => "Resumen del rol", - "UPDATED" => "Detalles actualizados para el rol {{name}} " + 'ROLE' => [ + 1 => 'Rol(funcion)', + 2 => 'Roles(funciones)', + + 'ASSIGN_NEW' => 'Asignar nueva rol', + 'CREATE' => 'Crear un rol', + 'CREATION_SUCCESSFUL' => 'Función creada correctamente {{name}} ', + 'DELETE' => 'Eliminar rol', + 'DELETE_CONFIRM' => '¿Seguro que quieres eliminar la función {{name}} ?', + 'DELETE_DEFAULT' => 'No puedes eliminar el rol {{name}} porque es un rol predeterminado para los usuarios recién registrados.', + 'DELETE_YES' => 'Sí, borrar función', + 'DELETION_SUCCESSFUL' => 'Se ha eliminado la función {{nombre}} ', + 'EDIT' => 'Editar función', + 'HAS_USERS' => 'No puedes hacerlo porque todavía hay usuarios que tienen el rol {{name}} .', + 'INFO_PAGE' => 'Página de información de funciones de {{name}}', + 'MANAGE' => 'Administrar roles', + 'NAME' => 'Nombre', + 'NAME_EXPLAIN' => 'Ingresa un nombre para el rol', + 'NAME_IN_USE' => 'Ya existe un rol denominado {{name}} ', + 'PAGE_DESCRIPTION' => 'Una lista de las funciones de tu sitio. Proporciona herramientas de administración para editar y eliminar roles.', + 'PERMISSIONS_UPDATED' => 'Permisos actualizados para el rol {{name}} ', + 'SUMMARY' => 'Resumen del rol', + 'UPDATED' => 'Detalles actualizados para el rol {{name}} ' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "Información del sistema", - - "DB_NAME" => "Nombre de la base de datos", - "DB_VERSION" => "Versión de base de datos", - "DIRECTORY" => "Directorio del proyecto", - "PHP_VERSION" => "Versión de PHP", - "SERVER" => "Software de servidor Web", - "SPRINKLES" => "Sprinkles cargados", - "UF_VERSION" => "UserFrosting versión", - "URL" => "URL root del sitio" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'Información del sistema', + + 'DB_NAME' => 'Nombre de la base de datos', + 'DB_VERSION' => 'Versión de base de datos', + 'DIRECTORY' => 'Directorio del proyecto', + 'PHP_VERSION' => 'Versión de PHP', + 'SERVER' => 'Software de servidor Web', + 'SPRINKLES' => 'Sprinkles cargados', + 'UF_VERSION' => 'UserFrosting versión', + 'URL' => 'URL root del sitio' ], - "TOGGLE_COLUMNS" => "Alternar columnas", - "NO_DATA" => "No puede quedar vacio.", + 'TOGGLE_COLUMNS' => 'Alternar columnas', + 'NO_DATA' => 'No puede quedar vacio.', - "USER" => [ - 1 => "Usuario", - 2 => "Usuarios", + 'USER' => [ + 1 => 'Usuario', + 2 => 'Usuarios', - "ADMIN" => [ - "CHANGE_PASSWORD" => "Cambiar contraseña de usuario", - "SEND_PASSWORD_LINK" => "Enviar al usuario un enlace que les permita elegir su propia contraseña", - "SET_PASSWORD" => "Establece la contraseña del usuario como" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'Cambiar contraseña de usuario', + 'SEND_PASSWORD_LINK' => 'Enviar al usuario un enlace que les permita elegir su propia contraseña', + 'SET_PASSWORD' => 'Establece la contraseña del usuario como' ], - "ACTIVATE" => "Activar usuario", - "CREATE" => "Crear usuario", - "CREATED" => "Se ha creado correctamente el usuario {{user_name}} ", - "DELETE" => "Borrar usuario", - "DELETE_CONFIRM" => "¿Seguro que deseas eliminar el usuario {{name}} ?", - "DELETE_YES" => "Sí, eliminar usuario", - "DISABLE" => "Deshabilitar usuario", - "EDIT" => "Editar usuario", - "ENABLE" => "Habilitar usuario", - "INFO_PAGE" => "Página de información de usuario de {{name}}", - "LATEST" => "Usuarios más recientes", - "PAGE_DESCRIPTION" => "Una lista de los usuarios para tu sitio. Proporciona herramientas de administración que incluyen la capacidad de editar detalles de usuario, activar manualmente usuarios, habilitar / deshabilitar usuarios y más.", - "SUMMARY" => "Resumen de la cuenta", - "VIEW_ALL" => "Ver todos los usuarios", - "WITH_PERMISSION" => "Usuarios con este permiso" + 'ACTIVATE' => 'Activar usuario', + 'CREATE' => 'Crear usuario', + 'CREATED' => 'Se ha creado correctamente el usuario {{user_name}} ', + 'DELETE' => 'Borrar usuario', + 'DELETE_CONFIRM' => '¿Seguro que deseas eliminar el usuario {{name}} ?', + 'DELETE_YES' => 'Sí, eliminar usuario', + 'DISABLE' => 'Deshabilitar usuario', + 'EDIT' => 'Editar usuario', + 'ENABLE' => 'Habilitar usuario', + 'INFO_PAGE' => 'Página de información de usuario de {{name}}', + 'LATEST' => 'Usuarios más recientes', + 'PAGE_DESCRIPTION' => 'Una lista de los usuarios para tu sitio. Proporciona herramientas de administración que incluyen la capacidad de editar detalles de usuario, activar manualmente usuarios, habilitar / deshabilitar usuarios y más.', + 'SUMMARY' => 'Resumen de la cuenta', + 'VIEW_ALL' => 'Ver todos los usuarios', + 'WITH_PERMISSION' => 'Usuarios con este permiso' ], - "X_USER" => [ - 0 => "No hay usuarios", - 1 => "{{plural}} usuario", - 2 => "{{plural}} usuarios" + 'X_USER' => [ + 0 => 'No hay usuarios', + 1 => '{{plural}} usuario', + 2 => '{{plural}} usuarios' ] ]; diff --git a/app/sprinkles/admin/locale/fa/messages.php b/app/sprinkles/admin/locale/fa/messages.php index 1299c2c3e..d6915c1cd 100644 --- a/app/sprinkles/admin/locale/fa/messages.php +++ b/app/sprinkles/admin/locale/fa/messages.php @@ -5,154 +5,154 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Standard Farsi/Persian message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\fa * @author aminakbari */ - return [ - "ACTIVITY" => [ - 1 => "فعالیت", - 2 => "فعالیت ها", + 'ACTIVITY' => [ + 1 => 'فعالیت', + 2 => 'فعالیت ها', - "LAST" => "آخرین فعالیت", - "PAGE" => "لیستی از فعالیت های کاربر", - "TIME" => "زمان فعالیت" + 'LAST' => 'آخرین فعالیت', + 'PAGE' => 'لیستی از فعالیت های کاربر', + 'TIME' => 'زمان فعالیت' ], - "CACHE" => [ - "CLEAR" => "پاک سازی کش", - "CLEAR_CONFIRM" => "آیا مطمئن هستید که میخواهید کش سایت را پاک سازی کنید؟", - "CLEAR_CONFIRM_YES" => "بله، کش پاک سازی شود", - "CLEARED" => "کش با موفقیت پاک سازی شد" + 'CACHE' => [ + 'CLEAR' => 'پاک سازی کش', + 'CLEAR_CONFIRM' => 'آیا مطمئن هستید که میخواهید کش سایت را پاک سازی کنید؟', + 'CLEAR_CONFIRM_YES' => 'بله، کش پاک سازی شود', + 'CLEARED' => 'کش با موفقیت پاک سازی شد' ], - "DASHBOARD" => "کارتابل", - "DELETE_MASTER" => "شما نمیتوانید کاربر اصلی را حذف کنید", - "DELETION_SUCCESSFUL" => "{{user_name}} با موفقیت حذف شد.", - "DETAILS_UPDATED" => "جزئیات {{user_name}} با موفقیت ذخیره شد.", - "DISABLE_MASTER" => "شما نمیتوانید کاربر اصلی را غیر فعال کنید.", - "DISABLE_SUCCESSFUL" => "حساب کاربری {{user_name}} با موفقیت غیر فعال شد.", - - "ENABLE_SUCCESSFUL" => "حساب کاربری {{user_name}} با موفقیت فعال شد.", - - "GROUP" => [ - 1 => "گروه", - 2 => "گروه ها", - - "CREATE" => "اضافه کردن گروه", - "CREATION_SUCCESSFUL" => "گروه {{name}} با موفقیت اضافه شد", - "DELETE" => "حذف گروه", - "DELETE_CONFIRM" => "آیا مطمئن هستید که میخواهید گروه {{name}} را حذف کنید؟", - "DELETE_DEFAULT" => "شما نمیتوانید گروه {{name}} را حذف کنید چون به عنوان گروه پیش فرض برای کاربران جدید انتخاب شده است.", - "DELETE_YES" => "بله، گروه حذف شود", - "DELETION_SUCCESSFUL" => "گروه {{name}} با موفقیت حذف شد.", - "EDIT" => "ویرایش گروه", - "ICON" => "آیکن گروه", - "ICON_EXPLAIN" => "آیکن برای اعضای گروه", - "INFO_PAGE" => "صفحه توضیحات گروه برای {{name}}", - "MANAGE" => "مدیریت گروه", - "NAME" => "نام گروه", - "NAME_EXPLAIN" => "لطفا نام گروه را وارد کنید", - "NOT_EMPTY" => "نمیتوان این کار را کرد چون هنوز کاربرانی عضو گروه {{name}} هستند.", - "PAGE_DESCRIPTION" => "لیست گروه های وب سایت شما. امکان مدیریت این گروه ها در این صفحه وجود دارد.", - "SUMMARY" => "توضیحات گروه", - "UPDATE" => "اطلاعات گروه {{name}} به روز رسانی شد." + 'DASHBOARD' => 'کارتابل', + 'DELETE_MASTER' => 'شما نمیتوانید کاربر اصلی را حذف کنید', + 'DELETION_SUCCESSFUL' => '{{user_name}} با موفقیت حذف شد.', + 'DETAILS_UPDATED' => 'جزئیات {{user_name}} با موفقیت ذخیره شد.', + 'DISABLE_MASTER' => 'شما نمیتوانید کاربر اصلی را غیر فعال کنید.', + 'DISABLE_SUCCESSFUL' => 'حساب کاربری {{user_name}} با موفقیت غیر فعال شد.', + + 'ENABLE_SUCCESSFUL' => 'حساب کاربری {{user_name}} با موفقیت فعال شد.', + + 'GROUP' => [ + 1 => 'گروه', + 2 => 'گروه ها', + + 'CREATE' => 'اضافه کردن گروه', + 'CREATION_SUCCESSFUL' => 'گروه {{name}} با موفقیت اضافه شد', + 'DELETE' => 'حذف گروه', + 'DELETE_CONFIRM' => 'آیا مطمئن هستید که میخواهید گروه {{name}} را حذف کنید؟', + 'DELETE_DEFAULT' => 'شما نمیتوانید گروه {{name}} را حذف کنید چون به عنوان گروه پیش فرض برای کاربران جدید انتخاب شده است.', + 'DELETE_YES' => 'بله، گروه حذف شود', + 'DELETION_SUCCESSFUL' => 'گروه {{name}} با موفقیت حذف شد.', + 'EDIT' => 'ویرایش گروه', + 'ICON' => 'آیکن گروه', + 'ICON_EXPLAIN' => 'آیکن برای اعضای گروه', + 'INFO_PAGE' => 'صفحه توضیحات گروه برای {{name}}', + 'MANAGE' => 'مدیریت گروه', + 'NAME' => 'نام گروه', + 'NAME_EXPLAIN' => 'لطفا نام گروه را وارد کنید', + 'NOT_EMPTY' => 'نمیتوان این کار را کرد چون هنوز کاربرانی عضو گروه {{name}} هستند.', + 'PAGE_DESCRIPTION' => 'لیست گروه های وب سایت شما. امکان مدیریت این گروه ها در این صفحه وجود دارد.', + 'SUMMARY' => 'توضیحات گروه', + 'UPDATE' => 'اطلاعات گروه {{name}} به روز رسانی شد.' ], - "MANUALLY_ACTIVATED" => "حساب کاربری {{user_name}} بصورت دستی فعال شد.", - "MASTER_ACCOUNT_EXISTS" => "حساب کاربری اصلی وجود دارد!", - "MIGRATION" => [ - "REQUIRED" => "به روز رسانی پایگاه داده ها باید انجام شود" + 'MANUALLY_ACTIVATED' => 'حساب کاربری {{user_name}} بصورت دستی فعال شد.', + 'MASTER_ACCOUNT_EXISTS' => 'حساب کاربری اصلی وجود دارد!', + 'MIGRATION' => [ + 'REQUIRED' => 'به روز رسانی پایگاه داده ها باید انجام شود' ], - "PERMISSION" => [ - 1 => "دسترسی", - 2 => "دسترسی ها", - - "ASSIGN_NEW" => "دادن دسترسی", - "HOOK_CONDITION" => "قلاب/شرط", - "ID" => "آی دی دسترسی", - "INFO_PAGE" => "توضیحات دسترسی {{name}}", - "MANAGE" => "مدیریت دسترسی ها", - "NOTE_READ_ONLY" => "توجه بفرماییددسترسی ها بخشی از کد میباشند و آن ها را نمیتوان از اینترفیس تغییر داد. برای این تغییرات، مبایستی که مدیر، از دیتابیس مایگریشن استفاده کند. ", - "PAGE_DESCRIPTION" => "لیست دسترسی های وب سایت شما. امکان مدیریت این دسترسی ها در این صفحه وجود دارد.", - "SUMMARY" => "توضیحات دسترسی ها", - "UPDATE" => "به روز رسانی دسترسی ها", - "VIA_ROLES" => "از طریق وظیفه ها دسترسی دارد" + 'PERMISSION' => [ + 1 => 'دسترسی', + 2 => 'دسترسی ها', + + 'ASSIGN_NEW' => 'دادن دسترسی', + 'HOOK_CONDITION' => 'قلاب/شرط', + 'ID' => 'آی دی دسترسی', + 'INFO_PAGE' => 'توضیحات دسترسی {{name}}', + 'MANAGE' => 'مدیریت دسترسی ها', + 'NOTE_READ_ONLY' => 'توجه بفرماییددسترسی ها بخشی از کد میباشند و آن ها را نمیتوان از اینترفیس تغییر داد. برای این تغییرات، مبایستی که مدیر، از دیتابیس مایگریشن استفاده کند. ', + 'PAGE_DESCRIPTION' => 'لیست دسترسی های وب سایت شما. امکان مدیریت این دسترسی ها در این صفحه وجود دارد.', + 'SUMMARY' => 'توضیحات دسترسی ها', + 'UPDATE' => 'به روز رسانی دسترسی ها', + 'VIA_ROLES' => 'از طریق وظیفه ها دسترسی دارد' ], - "ROLE" => [ - 1 => "وظیفه", - 2 => "وظیفه ها", - - "ASSIGN_NEW" => "دادن وظیفه", - "CREATE" => "ساخت وظیفه", - "CREATION_SUCCESSFUL" => "وظیفه {{name}} با موفقیت ساخته شد", - "DELETE" => "حذف وظیفه", - "DELETE_CONFIRM" => "اطمینان دارید که میخواهید وظیفه {{name}} را حذف کنید؟", - "DELETE_DEFAULT" => "شما نمیتوانید وظیفه {{name}} را حذف کنید زیرا کاربرانی که تازه ثبت نام کنند، این وظیفه را دریافت خواهند کرد.", - "DELETE_YES" => "بله، وظیفه حذف شود", - "DELETION_SUCCESSFUL" => "وظیفه {{name}} با موفقیت حذف شد", - "EDIT" => "ویرایش وظیفه", - "HAS_USERS" => "نمیتوانید این کار را انجام دهید زیرا کاربرانی وظیفه {{name}} را هنوز دارند.", - "INFO_PAGE" => "صفحه توضیحات وظیفه {{name}}", - "MANAGE" => "مدیریت وظیفه ها", - "NAME" => "نام", - "NAME_EXPLAIN" => "لطفا برای وظیفه نامی انتخاب کنید", - "NAME_IN_USE" => "وظیفه ای با نام {{name}} موجود است", - "PAGE_DESCRIPTION" => "لیست وظیفه های وب سایت شما. امکان مدیریت این وظیفه ها در این صفحه وجود دارد.", - "PERMISSIONS_UPDATED" => "دسترسی ها برای وظیفه {{name}} به روز رسانی شد", - "SUMMARY" => "خلاصه وظیفه", - "UPDATED" => "اطلاعات وظیفه {{name}} به روز رسانی شد" + 'ROLE' => [ + 1 => 'وظیفه', + 2 => 'وظیفه ها', + + 'ASSIGN_NEW' => 'دادن وظیفه', + 'CREATE' => 'ساخت وظیفه', + 'CREATION_SUCCESSFUL' => 'وظیفه {{name}} با موفقیت ساخته شد', + 'DELETE' => 'حذف وظیفه', + 'DELETE_CONFIRM' => 'اطمینان دارید که میخواهید وظیفه {{name}} را حذف کنید؟', + 'DELETE_DEFAULT' => 'شما نمیتوانید وظیفه {{name}} را حذف کنید زیرا کاربرانی که تازه ثبت نام کنند، این وظیفه را دریافت خواهند کرد.', + 'DELETE_YES' => 'بله، وظیفه حذف شود', + 'DELETION_SUCCESSFUL' => 'وظیفه {{name}} با موفقیت حذف شد', + 'EDIT' => 'ویرایش وظیفه', + 'HAS_USERS' => 'نمیتوانید این کار را انجام دهید زیرا کاربرانی وظیفه {{name}} را هنوز دارند.', + 'INFO_PAGE' => 'صفحه توضیحات وظیفه {{name}}', + 'MANAGE' => 'مدیریت وظیفه ها', + 'NAME' => 'نام', + 'NAME_EXPLAIN' => 'لطفا برای وظیفه نامی انتخاب کنید', + 'NAME_IN_USE' => 'وظیفه ای با نام {{name}} موجود است', + 'PAGE_DESCRIPTION' => 'لیست وظیفه های وب سایت شما. امکان مدیریت این وظیفه ها در این صفحه وجود دارد.', + 'PERMISSIONS_UPDATED' => 'دسترسی ها برای وظیفه {{name}} به روز رسانی شد', + 'SUMMARY' => 'خلاصه وظیفه', + 'UPDATED' => 'اطلاعات وظیفه {{name}} به روز رسانی شد' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "توضیحات سیستم", - - "DB_NAME" => "نام پایگاه داده", - "DB_VERSION" => "نسخه پایگاه داده", - "DIRECTORY" => "دایرکتوری پروژه", - "PHP_VERSION" => "نسخه پی اچ پی", - "SERVER" => "نرمافزار وب سرور", - "SPRINKLES" => "اسپرینکل های بارگذاری شده", - "UF_VERSION" => "نسخه یوزرفروستینگ", - "URL" => "آدرس رووت وب سایت" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'توضیحات سیستم', + + 'DB_NAME' => 'نام پایگاه داده', + 'DB_VERSION' => 'نسخه پایگاه داده', + 'DIRECTORY' => 'دایرکتوری پروژه', + 'PHP_VERSION' => 'نسخه پی اچ پی', + 'SERVER' => 'نرمافزار وب سرور', + 'SPRINKLES' => 'اسپرینکل های بارگذاری شده', + 'UF_VERSION' => 'نسخه یوزرفروستینگ', + 'URL' => 'آدرس رووت وب سایت' ], - "TOGGLE_COLUMNS" => "تغییر ستون", + 'TOGGLE_COLUMNS' => 'تغییر ستون', - "USER" => [ - 1 => "کاربر", - 2 => "کاربران", + 'USER' => [ + 1 => 'کاربر', + 2 => 'کاربران', - "ADMIN" => [ - "CHANGE_PASSWORD" => "تغییر گذرواژه کاربر", - "SEND_PASSWORD_LINK" => "برای کاربر ایمیلی ارسال شود تا گذرواژه خود را تغییر دهد", - "SET_PASSWORD" => "گذرواژه کاربر را انتخاب کنید" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'تغییر گذرواژه کاربر', + 'SEND_PASSWORD_LINK' => 'برای کاربر ایمیلی ارسال شود تا گذرواژه خود را تغییر دهد', + 'SET_PASSWORD' => 'گذرواژه کاربر را انتخاب کنید' ], - "ACTIVATE" => "کاربر فعال", - "CREATE" => "اضافه کردن کاربر", - "CREATED" => "کاربر {{user_name}} با موفقیت اضافه شد", - "DELETE" => "حذف کاربر", - "DELETE_CONFIRM" => "آیا اطمینان دارید که میخواهید کاربر {{name}} را حذف کنید؟", - "DELETE_YES" => "بله، کاربر حذف شود", - "DISABLE" => "غیر فعال سازی کاربر", - "EDIT" => "ویرایش کاربر", - "ENABLE" => "فعال سازی کاربر", - "INFO_PAGE" => "صفحه توضیحات کاربر {{name}}", - "LATEST" => "آخرین کاربران", - "PAGE_DESCRIPTION" => "لیستی از کاربران سایت. این صفحه به شما امکان ویرایش، فعال سازی و غیر فعال سازی کاربران را می دهد.", - "SUMMARY" => "خلاصه حساب", - "VIEW_ALL" => "تماشای همه ی کاربران", - "WITH_PERMISSION" => "کاربرانی که این دسترسی را دارند" + 'ACTIVATE' => 'کاربر فعال', + 'CREATE' => 'اضافه کردن کاربر', + 'CREATED' => 'کاربر {{user_name}} با موفقیت اضافه شد', + 'DELETE' => 'حذف کاربر', + 'DELETE_CONFIRM' => 'آیا اطمینان دارید که میخواهید کاربر {{name}} را حذف کنید؟', + 'DELETE_YES' => 'بله، کاربر حذف شود', + 'DISABLE' => 'غیر فعال سازی کاربر', + 'EDIT' => 'ویرایش کاربر', + 'ENABLE' => 'فعال سازی کاربر', + 'INFO_PAGE' => 'صفحه توضیحات کاربر {{name}}', + 'LATEST' => 'آخرین کاربران', + 'PAGE_DESCRIPTION' => 'لیستی از کاربران سایت. این صفحه به شما امکان ویرایش، فعال سازی و غیر فعال سازی کاربران را می دهد.', + 'SUMMARY' => 'خلاصه حساب', + 'VIEW_ALL' => 'تماشای همه ی کاربران', + 'WITH_PERMISSION' => 'کاربرانی که این دسترسی را دارند' ], - "X_USER" => [ - 0 => "هیچ کاربری", - 1 => "{{plural}} کاربر", - 2 => "{{plural}} کاربر" + 'X_USER' => [ + 0 => 'هیچ کاربری', + 1 => '{{plural}} کاربر', + 2 => '{{plural}} کاربر' ] ]; diff --git a/app/sprinkles/admin/locale/fr_FR/messages.php b/app/sprinkles/admin/locale/fr_FR/messages.php index 5020cdf97..c49b839b0 100644 --- a/app/sprinkles/admin/locale/fr_FR/messages.php +++ b/app/sprinkles/admin/locale/fr_FR/messages.php @@ -4,144 +4,145 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * French message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\fr * @author Louis Charette */ - + return [ - "ACTIVITY" => [ - 1 => "Activité", - 2 => "Activités", + 'ACTIVITY' => [ + 1 => 'Activité', + 2 => 'Activités', - "LAST" => "Dernière activité", - "PAGE" => "Une liste des activités des utilisateurs", - "TIME" => "Date de l'activité" + 'LAST' => 'Dernière activité', + 'PAGE' => 'Une liste des activités des utilisateurs', + 'TIME' => "Date de l'activité" ], - "CACHE" => [ - "CLEAR" => "Vider le cache", - "CLEAR_CONFIRM" => "Voulez-vous vraiment supprimer le cache du site?", - "CLEAR_CONFIRM_YES" => "Oui, vider le cache", - "CLEARED" => "Cache effacé avec succès !" + 'CACHE' => [ + 'CLEAR' => 'Vider le cache', + 'CLEAR_CONFIRM' => 'Voulez-vous vraiment supprimer le cache du site?', + 'CLEAR_CONFIRM_YES' => 'Oui, vider le cache', + 'CLEARED' => 'Cache effacé avec succès !' ], - "DASHBOARD" => "Tableau de bord", - "DELETE_MASTER" => "Vous ne pouvez pas supprimer le compte principal !", - "DELETION_SUCCESSFUL" => "L'utilisateur {{user_name}} a été supprimé avec succès.", - "DETAILS_UPDATED" => "Les détails du compte de {{user_name}} ont été mis à jour", - "DISABLE_MASTER" => "Vous ne pouvez pas désactiver le compte principal !", - "DISABLE_SELF" => "Vous ne pouvez pas désactiver votre propre compte !", - "DISABLE_SUCCESSFUL" => "Le compte de l'utilisateur {{user_name}} a été désactivé avec succès.", - - "ENABLE_SUCCESSFUL" => "Le compte de l'utilisateur {{user_name}} a été activé avec succès.", - - "GROUP" => [ - 1 => "Groupe", - 2 => "Groupes", - - "CREATE" => "Créer un groupe", - "CREATION_SUCCESSFUL" => "Successfully created group {{name}}", - "DELETE" => "Supprimer le groupe", - "DELETE_CONFIRM" => "Êtes-vous certain de vouloir supprimer le groupe {{name}}?", - "DELETE_DEFAULT" => "Vous ne pouvez pas supprimer le groupe {{name}} parce que c'est le groupe par défaut pour les utilisateurs nouvellement enregistrés.", - "DELETE_YES" => "Oui, supprimer le groupe", - "DELETION_SUCCESSFUL" => "Groupe {{name}} supprimé avec succès", - "EDIT" => "Modifier le groupe", - "ICON" => "Icône", - "ICON_EXPLAIN" => "Icône des membres du groupe", - "INFO_PAGE" => "Informations sur le groupe {{name}}", - "MANAGE" => "Gérer le groupe", - "NAME" => "Nom du groupe", - "NAME_EXPLAIN" => "Spécifiez le nom du groupe", - "NOT_EMPTY" => "Vous ne pouvez pas le faire car il y a encore des utilisateurs associés au groupe {{name}}.", - "PAGE_DESCRIPTION" => "Une liste des groupes pour votre site. Fournit des outils de gestion pour éditer et supprimer des groupes.", - "UPDATE" => "Les détails du groupe {{name}} ont été enregistrés" + 'DASHBOARD' => 'Tableau de bord', + 'DELETE_MASTER' => 'Vous ne pouvez pas supprimer le compte principal !', + 'DELETION_SUCCESSFUL' => "L'utilisateur {{user_name}} a été supprimé avec succès.", + 'DETAILS_UPDATED' => 'Les détails du compte de {{user_name}} ont été mis à jour', + 'DISABLE_MASTER' => 'Vous ne pouvez pas désactiver le compte principal !', + 'DISABLE_SELF' => 'Vous ne pouvez pas désactiver votre propre compte !', + 'DISABLE_SUCCESSFUL' => "Le compte de l'utilisateur {{user_name}} a été désactivé avec succès.", + + 'ENABLE_SUCCESSFUL' => "Le compte de l'utilisateur {{user_name}} a été activé avec succès.", + + 'GROUP' => [ + 1 => 'Groupe', + 2 => 'Groupes', + + 'CREATE' => 'Créer un groupe', + 'CREATION_SUCCESSFUL' => 'Successfully created group {{name}}', + 'DELETE' => 'Supprimer le groupe', + 'DELETE_CONFIRM' => 'Êtes-vous certain de vouloir supprimer le groupe {{name}}?', + 'DELETE_DEFAULT' => "Vous ne pouvez pas supprimer le groupe {{name}} parce que c'est le groupe par défaut pour les utilisateurs nouvellement enregistrés.", + 'DELETE_YES' => 'Oui, supprimer le groupe', + 'DELETION_SUCCESSFUL' => 'Groupe {{name}} supprimé avec succès', + 'EDIT' => 'Modifier le groupe', + 'ICON' => 'Icône', + 'ICON_EXPLAIN' => 'Icône des membres du groupe', + 'INFO_PAGE' => 'Informations sur le groupe {{name}}', + 'MANAGE' => 'Gérer le groupe', + 'NAME' => 'Nom du groupe', + 'NAME_EXPLAIN' => 'Spécifiez le nom du groupe', + 'NOT_EMPTY' => 'Vous ne pouvez pas le faire car il y a encore des utilisateurs associés au groupe {{name}}.', + 'PAGE_DESCRIPTION' => 'Une liste des groupes pour votre site. Fournit des outils de gestion pour éditer et supprimer des groupes.', + 'UPDATE' => 'Les détails du groupe {{name}} ont été enregistrés' ], - "MANUALLY_ACTIVATED" => "Le compte de {{user_name}} a été activé manuellement", - "MASTER_ACCOUNT_EXISTS" => "Le compte principal existe déjà !", - "MIGRATION" => [ - "REQUIRED" => "Mise à jour de la base de données requise" + 'MANUALLY_ACTIVATED' => 'Le compte de {{user_name}} a été activé manuellement', + 'MASTER_ACCOUNT_EXISTS' => 'Le compte principal existe déjà !', + 'MIGRATION' => [ + 'REQUIRED' => 'Mise à jour de la base de données requise' ], - "PERMISSION" => [ - 1 => "Autorisation", - 2 => "Autorisations", + 'PERMISSION' => [ + 1 => 'Autorisation', + 2 => 'Autorisations', - "ASSIGN_NEW" => "Assigner une nouvelle autorisation", - "HOOK_CONDITION" => "Hook/Conditions", - "MANAGE" => "Gestion des autorisations", - "PAGE_DESCRIPTION" => "Une liste des autorisations pour votre site. Fournit des outils de gestion pour modifier et supprimer des autorisations.", - "UPDATE" => "Mettre à jour les autorisations" + 'ASSIGN_NEW' => 'Assigner une nouvelle autorisation', + 'HOOK_CONDITION' => 'Hook/Conditions', + 'MANAGE' => 'Gestion des autorisations', + 'PAGE_DESCRIPTION' => 'Une liste des autorisations pour votre site. Fournit des outils de gestion pour modifier et supprimer des autorisations.', + 'UPDATE' => 'Mettre à jour les autorisations' ], - "ROLE" => [ - 1 => "Rôle", - 2 => "Rôles", - - "ASSIGN_NEW" => "Assigner un nouveau rôle", - "CREATE" => "Créer un rôle", - "CREATION_SUCCESSFUL" => "Rôle {{name}} créé avec succès", - "DELETE" => "Supprimer le rôle", - "DELETE_CONFIRM" => "Êtes-vous certain de vouloir supprimer le rôle {{name}}?", - "DELETE_DEFAULT" => "Vous ne pouvez pas supprimer le rôle {{name}} parce que c'est un rôle par défaut pour les utilisateurs nouvellement enregistrés.", - "DELETE_YES" => "Oui, supprimer le rôle", - "DELETION_SUCCESSFUL" => "Rôle {{name}} supprimé avec succès", - "EDIT" => "Modifier le rôle", - "HAS_USERS" => "Vous ne pouvez pas le faire parce qu'il y a encore des utilisateurs qui ont le rôle {{name}}.", - "INFO_PAGE" => "Page d'information pour le rôle {{name}}", - "MANAGE" => "Gérer les rôles", - "NAME" => "Nom du rôle", - "NAME_EXPLAIN" => "Spécifiez le nom du rôle", - "NAME_IN_USE" => "Un rôle nommé {{name}} existe déjà", - "PAGE_DESCRIPTION" => "Une liste des rôles de votre site. Fournit des outils de gestion pour modifier et supprimer des rôles.", - "PERMISSIONS_UPDATED" => "Autorisations mises à jour pour le rôle {{name}}", - "UPDATED" => "Détails mis à jour pour le rôle {{name}}" + 'ROLE' => [ + 1 => 'Rôle', + 2 => 'Rôles', + + 'ASSIGN_NEW' => 'Assigner un nouveau rôle', + 'CREATE' => 'Créer un rôle', + 'CREATION_SUCCESSFUL' => 'Rôle {{name}} créé avec succès', + 'DELETE' => 'Supprimer le rôle', + 'DELETE_CONFIRM' => 'Êtes-vous certain de vouloir supprimer le rôle {{name}}?', + 'DELETE_DEFAULT' => "Vous ne pouvez pas supprimer le rôle {{name}} parce que c'est un rôle par défaut pour les utilisateurs nouvellement enregistrés.", + 'DELETE_YES' => 'Oui, supprimer le rôle', + 'DELETION_SUCCESSFUL' => 'Rôle {{name}} supprimé avec succès', + 'EDIT' => 'Modifier le rôle', + 'HAS_USERS' => "Vous ne pouvez pas le faire parce qu'il y a encore des utilisateurs qui ont le rôle {{name}}.", + 'INFO_PAGE' => "Page d'information pour le rôle {{name}}", + 'MANAGE' => 'Gérer les rôles', + 'NAME' => 'Nom du rôle', + 'NAME_EXPLAIN' => 'Spécifiez le nom du rôle', + 'NAME_IN_USE' => 'Un rôle nommé {{name}} existe déjà', + 'PAGE_DESCRIPTION' => 'Une liste des rôles de votre site. Fournit des outils de gestion pour modifier et supprimer des rôles.', + 'PERMISSIONS_UPDATED' => 'Autorisations mises à jour pour le rôle {{name}}', + 'UPDATED' => 'Détails mis à jour pour le rôle {{name}}' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "Informations sur le système", - - "DB_NAME" => "Base de donnée", - "DB_VERSION" => "Version DB", - "DIRECTORY" => "Répertoire du projet", - "PHP_VERSION" => "Version de PHP", - "SERVER" => "Logiciel server", - "SPRINKLES" => "Sprinkles chargés", - "UF_VERSION" => "Version de UserFrosting", - "URL" => "Url racine" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'Informations sur le système', + + 'DB_NAME' => 'Base de donnée', + 'DB_VERSION' => 'Version DB', + 'DIRECTORY' => 'Répertoire du projet', + 'PHP_VERSION' => 'Version de PHP', + 'SERVER' => 'Logiciel server', + 'SPRINKLES' => 'Sprinkles chargés', + 'UF_VERSION' => 'Version de UserFrosting', + 'URL' => 'Url racine' ], - "USER" => [ - 1 => "Utilisateur", - 2 => "Utilisateurs", + 'USER' => [ + 1 => 'Utilisateur', + 2 => 'Utilisateurs', - "ADMIN" => [ - "CHANGE_PASSWORD" => "Changer le mot de passe", - "SEND_PASSWORD_LINK" => "Envoyer à l'utilisateur un lien qui lui permettra de choisir son propre mot de passe", - "SET_PASSWORD" => "Définissez le mot de passe de l'utilisateur comme" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'Changer le mot de passe', + 'SEND_PASSWORD_LINK' => "Envoyer à l'utilisateur un lien qui lui permettra de choisir son propre mot de passe", + 'SET_PASSWORD' => "Définissez le mot de passe de l'utilisateur comme" ], - "ACTIVATE" => "Autoriser l'utilisateur", - "CREATE" => "Créer un utilisateur", - "CREATED" => "L'utilisateur {{user_name}} a été créé avec succès", - "DELETE" => "Supprimer l'utilisateur", - "DELETE_CONFIRM" => "Êtes-vous certain de vouloir supprimer l'utilisateur {{name}}?", - "DELETE_YES" => "Oui, supprimer l'utilisateur", - "DISABLE" => "Désactiver l'utilisateur", - "EDIT" => "Modifier l'utilisateur", - "ENABLE" => "Activer l'utilisateur", - "INFO_PAGE" => "Page d'information de l'utilisateur pour {{name}}", - "PAGE_DESCRIPTION" => "Une liste des utilisateurs de votre site. Fournit des outils de gestion incluant la possibilité de modifier les détails de l'utilisateur, d'activer manuellement les utilisateurs, d'activer / désactiver les utilisateurs et plus.", - "LATEST" => "Derniers utilisateurs", - "VIEW_ALL" => "Voir tous les utilisateurs" + 'ACTIVATE' => "Autoriser l'utilisateur", + 'CREATE' => 'Créer un utilisateur', + 'CREATED' => "L'utilisateur {{user_name}} a été créé avec succès", + 'DELETE' => "Supprimer l'utilisateur", + 'DELETE_CONFIRM' => "Êtes-vous certain de vouloir supprimer l'utilisateur {{name}}?", + 'DELETE_YES' => "Oui, supprimer l'utilisateur", + 'DISABLE' => "Désactiver l'utilisateur", + 'EDIT' => "Modifier l'utilisateur", + 'ENABLE' => "Activer l'utilisateur", + 'INFO_PAGE' => "Page d'information de l'utilisateur pour {{name}}", + 'PAGE_DESCRIPTION' => "Une liste des utilisateurs de votre site. Fournit des outils de gestion incluant la possibilité de modifier les détails de l'utilisateur, d'activer manuellement les utilisateurs, d'activer / désactiver les utilisateurs et plus.", + 'LATEST' => 'Derniers utilisateurs', + 'VIEW_ALL' => 'Voir tous les utilisateurs' ], - "X_USER" => [ - 0 => "Aucun utilisateur", - 1 => "{{plural}} utilisateur", - 2 => "{{plural}} utilisateurs" + 'X_USER' => [ + 0 => 'Aucun utilisateur', + 1 => '{{plural}} utilisateur', + 2 => '{{plural}} utilisateurs' ] ]; diff --git a/app/sprinkles/admin/locale/it_IT/messages.php b/app/sprinkles/admin/locale/it_IT/messages.php index 7d17d8cd3..4a0bbf1c8 100644 --- a/app/sprinkles/admin/locale/it_IT/messages.php +++ b/app/sprinkles/admin/locale/it_IT/messages.php @@ -4,157 +4,157 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Italian message token translations for the 'admin' sprinkle. * This translation was generated with Google translate. Please contribute if you are a native speaker. * - * @package userfrosting\i18n\it * @author Alexander Weissman * @author Pietro Marangon (@Pe46dro) */ - return [ - "ACTIVITY" => [ - 1 => "Attività", - 2 => "Attività", + 'ACTIVITY' => [ + 1 => 'Attività', + 2 => 'Attività', - "LAST" => "Ultima attività", - "PAGE" => "Un elenco delle attività degli utenti", - "TIME" => "Tempo di attività" + 'LAST' => 'Ultima attività', + 'PAGE' => 'Un elenco delle attività degli utenti', + 'TIME' => 'Tempo di attività' ], - "CACHE" => [ - "CLEAR" => "Elimina cache", - "CLEAR_CONFIRM" => "Sei sicuro di voler eliminare la cache del sito?", - "CLEAR_CONFIRM_YES" => "Sì, elimina la cache", - "CLEARED" => "La cache è stata eliminata correttamente!" + 'CACHE' => [ + 'CLEAR' => 'Elimina cache', + 'CLEAR_CONFIRM' => 'Sei sicuro di voler eliminare la cache del sito?', + 'CLEAR_CONFIRM_YES' => 'Sì, elimina la cache', + 'CLEARED' => 'La cache è stata eliminata correttamente!' ], - "DASHBOARD" => "Pannello di Controllo", - "NO_FEATURES_YET" => "Sembra che nessuna funzione sia stata creata per questo account... ancora. Forse non sono ancora state implementate o qualcuno ha dimenticato di dartene accesso. In entrambi i casi, siamo contenti di averti qui!", - "DELETE_MASTER" => "Non puoi eliminare l'account principale!", - "DELETION_SUCCESSFUL" => "Hai eliminato l'utente utente {{user_name}}.", - "DETAILS_UPDATED" => "Dettagli account aggiornati per l'utente {{user_name}}", - "DISABLE_MASTER" => "Non puoi disattivare l'account principale!", - "DISABLE_SELF" => "Non puoi disattivare il tuo account!", - "DISABLE_SUCCESSFUL" => "Account dell'utente {{user_name}} disattivato con successo!", - "ENABLE_SUCCESSFUL" => "Account dell'utente {{user_name}} attivato con successo.", - - "GROUP" => [ - 1 => "Gruppo", - 2 => "Gruppi", - - "CREATE" => "Crea un gruppo", - "CREATION_SUCCESSFUL" => "Gruppo {{name}} creato con successo", - "DELETE" => "Elimina gruppo", - "DELETE_CONFIRM" => "Sei sicuro di voler eliminare il gruppo {{name}}?", - "DELETE_DEFAULT" => "Non puoi eliminare il gruppo {{name}} perché è il gruppo predefinito per gli utenti appena registrati.", - "DELETE_YES" => "Sì, elimina il gruppo", - "DELETION_SUCCESSFUL" => "Gruppo {{name}} eliminato con successo", - "EDIT" => "Modifica gruppo", - "ICON" => "Icona del gruppo", - "ICON_EXPLAIN" => "Icona per i membri del gruppo", - "INFO_PAGE" => "Pagina informazioni del Gruppo per {{name}}", - "MANAGE" => "Gestisci gruppo", - "NAME" => "Nome gruppo", - "NAME_EXPLAIN" => "Inserisci un nome per il gruppo", - "NOT_EMPTY" => "Non puoi farlo perché ci sono ancora utenti associati al gruppo {{name}}.", - "PAGE_DESCRIPTION" => "Un elenco dei gruppi per il tuo sito. Fornisce strumenti di gestione per la modifica e l'eliminazione di gruppi.", - "SUMMARY" => "Riepilogo Gruppo", - "UPDATE" => "Dettagli del gruppo {{name}} aggiornati." + 'DASHBOARD' => 'Pannello di Controllo', + 'NO_FEATURES_YET' => 'Sembra che nessuna funzione sia stata creata per questo account... ancora. Forse non sono ancora state implementate o qualcuno ha dimenticato di dartene accesso. In entrambi i casi, siamo contenti di averti qui!', + 'DELETE_MASTER' => "Non puoi eliminare l'account principale!", + 'DELETION_SUCCESSFUL' => "Hai eliminato l'utente utente {{user_name}}.", + 'DETAILS_UPDATED' => "Dettagli account aggiornati per l'utente {{user_name}}", + 'DISABLE_MASTER' => "Non puoi disattivare l'account principale!", + 'DISABLE_SELF' => 'Non puoi disattivare il tuo account!', + 'DISABLE_SUCCESSFUL' => "Account dell'utente {{user_name}} disattivato con successo!", + 'ENABLE_SUCCESSFUL' => "Account dell'utente {{user_name}} attivato con successo.", + + 'GROUP' => [ + 1 => 'Gruppo', + 2 => 'Gruppi', + + 'CREATE' => 'Crea un gruppo', + 'CREATION_SUCCESSFUL' => 'Gruppo {{name}} creato con successo', + 'DELETE' => 'Elimina gruppo', + 'DELETE_CONFIRM' => 'Sei sicuro di voler eliminare il gruppo {{name}}?', + 'DELETE_DEFAULT' => 'Non puoi eliminare il gruppo {{name}} perché è il gruppo predefinito per gli utenti appena registrati.', + 'DELETE_YES' => 'Sì, elimina il gruppo', + 'DELETION_SUCCESSFUL' => 'Gruppo {{name}} eliminato con successo', + 'EDIT' => 'Modifica gruppo', + 'ICON' => 'Icona del gruppo', + 'ICON_EXPLAIN' => 'Icona per i membri del gruppo', + 'INFO_PAGE' => 'Pagina informazioni del Gruppo per {{name}}', + 'MANAGE' => 'Gestisci gruppo', + 'NAME' => 'Nome gruppo', + 'NAME_EXPLAIN' => 'Inserisci un nome per il gruppo', + 'NOT_EMPTY' => 'Non puoi farlo perché ci sono ancora utenti associati al gruppo {{name}}.', + 'PAGE_DESCRIPTION' => "Un elenco dei gruppi per il tuo sito. Fornisce strumenti di gestione per la modifica e l'eliminazione di gruppi.", + 'SUMMARY' => 'Riepilogo Gruppo', + 'UPDATE' => 'Dettagli del gruppo {{name}} aggiornati.' ], - "MANUALLY_ACTIVATED" => "{{user_name}} è stato attivato manualmente", - "MASTER_ACCOUNT_EXISTS" => "L'account primario esiste già!", - "MIGRATION" => [ - "REQUIRED" => "È necessario aggiornare il database" + 'MANUALLY_ACTIVATED' => '{{user_name}} è stato attivato manualmente', + 'MASTER_ACCOUNT_EXISTS' => "L'account primario esiste già!", + 'MIGRATION' => [ + 'REQUIRED' => 'È necessario aggiornare il database' ], - "PERMISSION" => [ - 1 => "Permesso", - 2 => "Permessi", - - "ASSIGN_NEW" => "Assegna nuovo permesso", - "HOOK_CONDITION" => "Hook/Condizioni", - "ID" => "ID permesso", - "INFO_PAGE" => "Pagina di informazioni sulle autorizzazioni per {{name}}", - "MANAGE" => "Gestione delle autorizzazioni", - "NOTE_READ_ONLY" => "Nota: le autorizzazioni sono considerate \"parte del codice\" e non possono essere modificate tramite l'interfaccia. Per aggiungere, rimuovere o modificare le autorizzazioni, i gestori del sito devono utilizzare migrazione del database.", - "PAGE_DESCRIPTION" => "Un elenco delle autorizzazioni per il tuo sito. Fornisce strumenti di gestione per la modifica e l'eliminazione delle autorizzazioni.", - "SUMMARY" => "Sommario autorizzazioni", - "UPDATE" => "Aggiorna autorizzazioni", - "VIA_ROLES" => "Ha i permessi tramite i ruoli" + 'PERMISSION' => [ + 1 => 'Permesso', + 2 => 'Permessi', + + 'ASSIGN_NEW' => 'Assegna nuovo permesso', + 'HOOK_CONDITION' => 'Hook/Condizioni', + 'ID' => 'ID permesso', + 'INFO_PAGE' => 'Pagina di informazioni sulle autorizzazioni per {{name}}', + 'MANAGE' => 'Gestione delle autorizzazioni', + 'NOTE_READ_ONLY' => "Nota: le autorizzazioni sono considerate \"parte del codice\" e non possono essere modificate tramite l'interfaccia. Per aggiungere, rimuovere o modificare le autorizzazioni, i gestori del sito devono utilizzare migrazione del database.", + 'PAGE_DESCRIPTION' => "Un elenco delle autorizzazioni per il tuo sito. Fornisce strumenti di gestione per la modifica e l'eliminazione delle autorizzazioni.", + 'SUMMARY' => 'Sommario autorizzazioni', + 'UPDATE' => 'Aggiorna autorizzazioni', + 'VIA_ROLES' => 'Ha i permessi tramite i ruoli' ], - "ROLE" => [ - 1 => "Ruolo", - 2 => "Ruoli", - - "ASSIGN_NEW" => "Assegna nuovo ruolo", - "CREATE" => "Crea ruolo", - "CREATION_SUCCESSFUL" => "Creato con successo il ruolo {{name}}", - "DELETE" => "Elimina ruolo", - "DELETE_CONFIRM" => "Sei sicuro di voler eliminare il ruolo {{name}}?", - "DELETE_DEFAULT" => "Non puoi eliminare il ruolo {{name}} perché è un ruolo predefinito per gli utenti appena registrati.", - "DELETE_YES" => "Sì, elimina il ruolo", - "DELETION_SUCCESSFUL" => "Ruolo {{name}} eliminato", - "EDIT" => "Modifica ruolo", - "HAS_USERS" => "Non puoi farlo perché ci sono ancora utenti che hanno il ruolo {{name}}.", - "INFO_PAGE" => "Pagina di informazioni sui ruoli per {{name}}", - "MANAGE" => "Gestisci Ruoli", - "NAME" => "Nome", - "NAME_EXPLAIN" => "Inserisci un nome per il ruolo", - "NAME_IN_USE" => "Esiste già un ruolo denominato {{name}}", - "PAGE_DESCRIPTION" => "Un elenco dei ruoli per il tuo sito. Fornisce strumenti di gestione per la modifica e l'eliminazione di ruoli.", - "PERMISSIONS_UPDATED" => "Autorizzazioni aggiornate per il ruolo {{name}}", - "SUMMARY" => "Riepilogo dei Ruoli", - "UPDATED" => "Dettagli aggiornati per il ruolo {{name}}" + 'ROLE' => [ + 1 => 'Ruolo', + 2 => 'Ruoli', + + 'ASSIGN_NEW' => 'Assegna nuovo ruolo', + 'CREATE' => 'Crea ruolo', + 'CREATION_SUCCESSFUL' => 'Creato con successo il ruolo {{name}}', + 'DELETE' => 'Elimina ruolo', + 'DELETE_CONFIRM' => 'Sei sicuro di voler eliminare il ruolo {{name}}?', + 'DELETE_DEFAULT' => 'Non puoi eliminare il ruolo {{name}} perché è un ruolo predefinito per gli utenti appena registrati.', + 'DELETE_YES' => 'Sì, elimina il ruolo', + 'DELETION_SUCCESSFUL' => 'Ruolo {{name}} eliminato', + 'EDIT' => 'Modifica ruolo', + 'HAS_USERS' => 'Non puoi farlo perché ci sono ancora utenti che hanno il ruolo {{name}}.', + 'INFO_PAGE' => 'Pagina di informazioni sui ruoli per {{name}}', + 'MANAGE' => 'Gestisci Ruoli', + 'NAME' => 'Nome', + 'NAME_EXPLAIN' => 'Inserisci un nome per il ruolo', + 'NAME_IN_USE' => 'Esiste già un ruolo denominato {{name}}', + 'PAGE_DESCRIPTION' => "Un elenco dei ruoli per il tuo sito. Fornisce strumenti di gestione per la modifica e l'eliminazione di ruoli.", + 'PERMISSIONS_UPDATED' => 'Autorizzazioni aggiornate per il ruolo {{name}}', + 'SUMMARY' => 'Riepilogo dei Ruoli', + 'UPDATED' => 'Dettagli aggiornati per il ruolo {{name}}' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "Informazioni sul sistema", - - "DB_NAME" => "Nome del database", - "DB_VERSION" => "Versione del database", - "DIRECTORY" => "Directory del progetto", - "PHP_VERSION" => "Versione PHP", - "SERVER" => "Software Webserver", - "SPRINKLES" => "Sprinkles caricati", - "UF_VERSION" => "Versione UserFrosting", - "URL" => "Url della root del sito" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'Informazioni sul sistema', + + 'DB_NAME' => 'Nome del database', + 'DB_VERSION' => 'Versione del database', + 'DIRECTORY' => 'Directory del progetto', + 'PHP_VERSION' => 'Versione PHP', + 'SERVER' => 'Software Webserver', + 'SPRINKLES' => 'Sprinkles caricati', + 'UF_VERSION' => 'Versione UserFrosting', + 'URL' => 'Url della root del sito' ], - "TOGGLE_COLUMNS" => "Scambia le colonne", + 'TOGGLE_COLUMNS' => 'Scambia le colonne', - "USER" => [ - 1 => "Utente", - 2 => "Utenti", + 'USER' => [ + 1 => 'Utente', + 2 => 'Utenti', - "ADMIN" => [ - "CHANGE_PASSWORD" => "Cambia password utente", - "SEND_PASSWORD_LINK" => "Invia all'utente un link che gli permetterà di scegliere una nuova password.", - "SET_PASSWORD" => "Impostare la password dell'utente come" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'Cambia password utente', + 'SEND_PASSWORD_LINK' => "Invia all'utente un link che gli permetterà di scegliere una nuova password.", + 'SET_PASSWORD' => "Impostare la password dell'utente come" ], - "ACTIVATE" => "Attiva utente", - "CREATE" => "Creare utente", - "CREATED" => "Account utente {{user_name}} creato.", - "DELETE" => "Elimina utente", - "DELETE_CONFIRM" => "Sei sicuro di voler eliminare l'utente {{name}}?", - "DELETE_YES" => "Sì, elimina l'utente", - "DISABLE" => "Disabilita l'utente", - "EDIT" => "Modifica utente", - "ENABLE" => "Abilita utente", - "INFO_PAGE" => "Pagina informazioni utente per {{name}}", - "LATEST" => "Ultimi Utenti", - "PAGE_DESCRIPTION" => "Un elenco degli utenti del tuo sito. Fornisce strumenti di gestione, tra cui la possibilità di modificare i dettagli utente, attivare manualmente gli utenti, abilitare / disabilitare gli utenti e altro ancora.", - "SUMMARY" => "Riepilogo account", - "VIEW_ALL" => "Visualizza tutti gli utenti", - "WITH_PERMISSION" => "Utenti con questa autorizzazione" + 'ACTIVATE' => 'Attiva utente', + 'CREATE' => 'Creare utente', + 'CREATED' => 'Account utente {{user_name}} creato.', + 'DELETE' => 'Elimina utente', + 'DELETE_CONFIRM' => "Sei sicuro di voler eliminare l'utente {{name}}?", + 'DELETE_YES' => "Sì, elimina l'utente", + 'DISABLE' => "Disabilita l'utente", + 'EDIT' => 'Modifica utente', + 'ENABLE' => 'Abilita utente', + 'INFO_PAGE' => 'Pagina informazioni utente per {{name}}', + 'LATEST' => 'Ultimi Utenti', + 'PAGE_DESCRIPTION' => 'Un elenco degli utenti del tuo sito. Fornisce strumenti di gestione, tra cui la possibilità di modificare i dettagli utente, attivare manualmente gli utenti, abilitare / disabilitare gli utenti e altro ancora.', + 'SUMMARY' => 'Riepilogo account', + 'VIEW_ALL' => 'Visualizza tutti gli utenti', + 'WITH_PERMISSION' => 'Utenti con questa autorizzazione' ], - "X_USER" => [ - 0 => "Nessun utente", - 1 => "{{plural}} utente", - 2 => "{{plural}} utenti" + 'X_USER' => [ + 0 => 'Nessun utente', + 1 => '{{plural}} utente', + 2 => '{{plural}} utenti' ] ]; diff --git a/app/sprinkles/admin/locale/pt_PT/messages.php b/app/sprinkles/admin/locale/pt_PT/messages.php index 0faf818d5..7fe951b91 100644 --- a/app/sprinkles/admin/locale/pt_PT/messages.php +++ b/app/sprinkles/admin/locale/pt_PT/messages.php @@ -4,136 +4,136 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Portuguese message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\pt * @author Bruno Silva (brunomnsilva@gmail.com) */ - return [ - "ACTIVITY" => [ - 1 => "Atividade", - 2 => "Atividades", + 'ACTIVITY' => [ + 1 => 'Atividade', + 2 => 'Atividades', - "LAST" => "Última atividade", - "PAGE" => "Lista de atividade dos utilizadores", - "TIME" => "Tempo da Atividade" + 'LAST' => 'Última atividade', + 'PAGE' => 'Lista de atividade dos utilizadores', + 'TIME' => 'Tempo da Atividade' ], - "CACHE" => [ - "CLEAR" => "Limpar cache", - "CLEAR_CONFIRM" => "Tem a certeza que pretende limpar a cache do site?", - "CLEAR_CONFIRM_YES" => "Sim, limpar cache", - "CLEARED" => "Cache limpa com sucesso!" + 'CACHE' => [ + 'CLEAR' => 'Limpar cache', + 'CLEAR_CONFIRM' => 'Tem a certeza que pretende limpar a cache do site?', + 'CLEAR_CONFIRM_YES' => 'Sim, limpar cache', + 'CLEARED' => 'Cache limpa com sucesso!' ], - "DASHBOARD" => "Painel de Controlo", - "DELETE_MASTER" => "Não pode apagar a conta principal!", - "DELETION_SUCCESSFUL" => "Utilizador {{user_name}} foi removido com sucesso.", - "DETAILS_UPDATED" => "Detalhes de conta atualizados para o utilizador {{user_name}}", - "DISABLE_MASTER" => "Não pode desativar a conta principal!", - "DISABLE_SUCCESSFUL" => "Conta do utilizador {{user_name}} foi desativada com sucesso.", - - "ENABLE_SUCCESSFUL" => "Conta do utilizador {{user_name}} foi ativada com sucesso.", - - "GROUP" => [ - 1 => "Grupo", - 2 => "Grupos", - - "CREATE" => "Criar grupo", - "CREATION_SUCCESSFUL" => "Grupo criado com sucesso", - "DELETE" => "Remover grupo", - "DELETION_SUCCESSFUL" => "Grupo removido com sucesso", - "DELETE_CONFIRM" => "Tem a certeza que pretende remover o grupo {{name}}?", - "DELETE_YES" => "Sim, remover grupo", - "EDIT" => "Editar grupo", - "ICON" => "Icon do grupo", - "ICON_EXPLAIN" => "Icon para membros do grupo", - "INFO_PAGE" => "Página informativa do grupo {{name}}", + 'DASHBOARD' => 'Painel de Controlo', + 'DELETE_MASTER' => 'Não pode apagar a conta principal!', + 'DELETION_SUCCESSFUL' => 'Utilizador {{user_name}} foi removido com sucesso.', + 'DETAILS_UPDATED' => 'Detalhes de conta atualizados para o utilizador {{user_name}}', + 'DISABLE_MASTER' => 'Não pode desativar a conta principal!', + 'DISABLE_SUCCESSFUL' => 'Conta do utilizador {{user_name}} foi desativada com sucesso.', + + 'ENABLE_SUCCESSFUL' => 'Conta do utilizador {{user_name}} foi ativada com sucesso.', + + 'GROUP' => [ + 1 => 'Grupo', + 2 => 'Grupos', + + 'CREATE' => 'Criar grupo', + 'CREATION_SUCCESSFUL' => 'Grupo criado com sucesso', + 'DELETE' => 'Remover grupo', + 'DELETION_SUCCESSFUL' => 'Grupo removido com sucesso', + 'DELETE_CONFIRM' => 'Tem a certeza que pretende remover o grupo {{name}}?', + 'DELETE_YES' => 'Sim, remover grupo', + 'EDIT' => 'Editar grupo', + 'ICON' => 'Icon do grupo', + 'ICON_EXPLAIN' => 'Icon para membros do grupo', + 'INFO_PAGE' => 'Página informativa do grupo {{name}}', //"MANAGE" => "Manage group", - "NAME" => "Nome do grupo", - "NAME_EXPLAIN" => "Por favor introduza um nome para o grupo", - "PAGE_DESCRIPTION" => "Lista de grupos do site. Contém opções para editar e remover grupos." + 'NAME' => 'Nome do grupo', + 'NAME_EXPLAIN' => 'Por favor introduza um nome para o grupo', + 'PAGE_DESCRIPTION' => 'Lista de grupos do site. Contém opções para editar e remover grupos.' ], - "MANUALLY_ACTIVATED" => "A conta de {{user_name}} foi ativada manualmente.", - "MASTER_ACCOUNT_EXISTS" => "A contra principal já existe!", - "MIGRATION" => [ - "REQUIRED" => "É necessário uma atualização da base de dados." + 'MANUALLY_ACTIVATED' => 'A conta de {{user_name}} foi ativada manualmente.', + 'MASTER_ACCOUNT_EXISTS' => 'A contra principal já existe!', + 'MIGRATION' => [ + 'REQUIRED' => 'É necessário uma atualização da base de dados.' ], - "PERMISSION" => [ - 1 => "Permissão", - 2 => "Permissões", + 'PERMISSION' => [ + 1 => 'Permissão', + 2 => 'Permissões', - "ASSIGN_NEW" => "Atribuir nova permissão", - "HOOK_CONDITION" => "Hook/Condições", - "MANAGE" => "Gerir permissões", - "PAGE_DESCRIPTION" => "Lista de permissões do site. Contém opções para editar e remover permissões.", - "UPDATE" => "Atualizar permissões" + 'ASSIGN_NEW' => 'Atribuir nova permissão', + 'HOOK_CONDITION' => 'Hook/Condições', + 'MANAGE' => 'Gerir permissões', + 'PAGE_DESCRIPTION' => 'Lista de permissões do site. Contém opções para editar e remover permissões.', + 'UPDATE' => 'Atualizar permissões' ], - "ROLE" => [ - 1 => "Cargo", - 2 => "Cargos", - - "ASSIGN_NEW" => "Atribuir novo cargo", - "CREATE" => "Criar cargo", - "CREATION_SUCCESSFUL" => "Cargo criado com sucesso", - "DELETE" => "Remover cargo", - "DELETION_SUCCESSFUL" => "Cargo removido com sucesso", - "DELETE_CONFIRM" => "Tem a certeza que pretende remover o cargo {{name}}?", - "DELETE_YES" => "Sim, remover cargo", - "EDIT" => "Editar cargo", - "INFO_PAGE" => "Página informativa do cargo {{name}}", - "MANAGE" => "Gerir cargos", - "NAME" => "Nome", - "NAME_EXPLAIN" => "Por favor introduza um nome para o cargo", - "PAGE_DESCRIPTION" => "Lista de cargos do site. Contém opções para editar e remover cargos.", - "UPDATE" => "Atualizar cargos", - "UPDATED" => "Cargo {{name}} atualizado" + 'ROLE' => [ + 1 => 'Cargo', + 2 => 'Cargos', + + 'ASSIGN_NEW' => 'Atribuir novo cargo', + 'CREATE' => 'Criar cargo', + 'CREATION_SUCCESSFUL' => 'Cargo criado com sucesso', + 'DELETE' => 'Remover cargo', + 'DELETION_SUCCESSFUL' => 'Cargo removido com sucesso', + 'DELETE_CONFIRM' => 'Tem a certeza que pretende remover o cargo {{name}}?', + 'DELETE_YES' => 'Sim, remover cargo', + 'EDIT' => 'Editar cargo', + 'INFO_PAGE' => 'Página informativa do cargo {{name}}', + 'MANAGE' => 'Gerir cargos', + 'NAME' => 'Nome', + 'NAME_EXPLAIN' => 'Por favor introduza um nome para o cargo', + 'PAGE_DESCRIPTION' => 'Lista de cargos do site. Contém opções para editar e remover cargos.', + 'UPDATE' => 'Atualizar cargos', + 'UPDATED' => 'Cargo {{name}} atualizado' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "Informação do sistema", - - "DB_NAME" => "Nome da base de dados", - "DB_VERSION" => "Versão da base de dados", - "DIRECTORY" => "Diretório do projeto", - "PHP_VERSION" => "Versão PHP", - "SERVER" => "Software do servidor web", - "SPRINKLES" => "Sprinkles carregados", - "UF_VERSION" => "Versão do UserFrosting", - "URL" => "Raiz (url) do site" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'Informação do sistema', + + 'DB_NAME' => 'Nome da base de dados', + 'DB_VERSION' => 'Versão da base de dados', + 'DIRECTORY' => 'Diretório do projeto', + 'PHP_VERSION' => 'Versão PHP', + 'SERVER' => 'Software do servidor web', + 'SPRINKLES' => 'Sprinkles carregados', + 'UF_VERSION' => 'Versão do UserFrosting', + 'URL' => 'Raiz (url) do site' ], - "USER" => [ - 1 => "Utilizador", - 2 => "Utilizadores", + 'USER' => [ + 1 => 'Utilizador', + 2 => 'Utilizadores', - "ADMIN" => [ - "CHANGE_PASSWORD" => "Alterar password", - "SEND_PASSWORD_LINK" => "Enviar um link ao utilizador que lhe permita escolher a sua password", - "SET_PASSWORD" => "Definir a password do utilizador como" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'Alterar password', + 'SEND_PASSWORD_LINK' => 'Enviar um link ao utilizador que lhe permita escolher a sua password', + 'SET_PASSWORD' => 'Definir a password do utilizador como' ], - "ACTIVATE" => "Ativar utilizador", - "CREATE" => "Criar utilizador", - "DELETE" => "Remover utilizador", - "DELETE_CONFIRM" => "Tem a certeza que pretende remover o utilizador {{name}}?", - "DELETE_YES" => "Sim, remover utilizador", - "DISABLE" => "Desativar utilizador", - "EDIT" => "Editar utilizador", - "ENABLE" => "Ativar utilizador", - "INFO_PAGE" => "Página informativa do utilizador {{name}}", - "PAGE_DESCRIPTION" => "Lista de utilizadores do site. Contém opções para editar detalhes, ativar/desativar utilizadores e outras.", - "LATEST" => "Últimos Utilizadores", - "VIEW_ALL" => "Ver todos os utilizadores" + 'ACTIVATE' => 'Ativar utilizador', + 'CREATE' => 'Criar utilizador', + 'DELETE' => 'Remover utilizador', + 'DELETE_CONFIRM' => 'Tem a certeza que pretende remover o utilizador {{name}}?', + 'DELETE_YES' => 'Sim, remover utilizador', + 'DISABLE' => 'Desativar utilizador', + 'EDIT' => 'Editar utilizador', + 'ENABLE' => 'Ativar utilizador', + 'INFO_PAGE' => 'Página informativa do utilizador {{name}}', + 'PAGE_DESCRIPTION' => 'Lista de utilizadores do site. Contém opções para editar detalhes, ativar/desativar utilizadores e outras.', + 'LATEST' => 'Últimos Utilizadores', + 'VIEW_ALL' => 'Ver todos os utilizadores' ], - "X_USER" => [ - 0 => "Nenhum utilizador", - 1 => "{{plural}} utilizador", - 2 => "{{plural}} utilizadores" + 'X_USER' => [ + 0 => 'Nenhum utilizador', + 1 => '{{plural}} utilizador', + 2 => '{{plural}} utilizadores' ] ]; diff --git a/app/sprinkles/admin/locale/ru_RU/messages.php b/app/sprinkles/admin/locale/ru_RU/messages.php index d6f6e1a8f..d3214e68d 100644 --- a/app/sprinkles/admin/locale/ru_RU/messages.php +++ b/app/sprinkles/admin/locale/ru_RU/messages.php @@ -4,157 +4,157 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Russian message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\ru_RU * @author @rendername */ - return [ - "ACTIVITY" => [ - 1 => "Активность", - 2 => "Активность", + 'ACTIVITY' => [ + 1 => 'Активность', + 2 => 'Активность', - "LAST" => "Последняя активность", - "PAGE" => "Список действий пользователя", - "TIME" => "Время действия" + 'LAST' => 'Последняя активность', + 'PAGE' => 'Список действий пользователя', + 'TIME' => 'Время действия' ], - "CACHE" => [ - "CLEAR" => "Очистить кэш", - "CLEAR_CONFIRM" => "Уверены, что хотите очистить кэш сайта?", - "CLEAR_CONFIRM_YES" => "Да, очистить кэш", - "CLEARED" => "Кэш успешно очищен !" + 'CACHE' => [ + 'CLEAR' => 'Очистить кэш', + 'CLEAR_CONFIRM' => 'Уверены, что хотите очистить кэш сайта?', + 'CLEAR_CONFIRM_YES' => 'Да, очистить кэш', + 'CLEARED' => 'Кэш успешно очищен !' ], - "DASHBOARD" => "Панель управления", - "NO_FEATURES_YET" => "Похоже, некоторые функции не были настроены для этого аккаунта... пока. Возможно, они еще не реализованы, или, может быть, кто-то забыл дать вам доступ. В любом случае, мы рады вас видеть здесь!", - "DELETE_MASTER" => "Нельзя удалить главный аккаунт!", - "DELETION_SUCCESSFUL" => "Пользователь {{user_name}} был успешно удален.", - "DETAILS_UPDATED" => "Данные для аккаунта {{user_name}} обновлены", - "DISABLE_MASTER" => "Нельзя отключить главный аккаунт!", - "DISABLE_SELF" => "Вы не можете отключить собственный аккаунт!", - "DISABLE_SUCCESSFUL" => "Пользователь {{user_name}} был успешно отключен.", - - "ENABLE_SUCCESSFUL" => "Пользователь {{user_name}} был успешно включен.", - - "GROUP" => [ - 1 => "Группа", - 2 => "Группы", - - "CREATE" => "Создать группу", - "CREATION_SUCCESSFUL" => "Успешно создана группа {{name}}", - "DELETE" => "Удалить группу", - "DELETE_CONFIRM" => "Вы уверены, что вы хотите удалить группу {{name}}?", - "DELETE_DEFAULT" => "Нельзя удалить группу {{name}}, потому что это группа по умолчанию для новых пользователей.", - "DELETE_YES" => "Да, удалить группу", - "DELETION_SUCCESSFUL" => "Успешно удалена группа {{name}}", - "EDIT" => "Редактор группы", - "ICON" => "Значок группы", - "ICON_EXPLAIN" => "Значок для членов группы", - "INFO_PAGE" => "Описание группы {{name}}", - "MANAGE" => "Управление группой", - "NAME" => "Имя группы", - "NAME_EXPLAIN" => "Пожалуйста, введите имя группы", - "NOT_EMPTY" => "Вы не можете сделать это, потому что до сих пор есть пользователи, связанные с группой {{name}}.", - "PAGE_DESCRIPTION" => "Список групп для вашего сайта. Предоставляет инструменты управления для редактирования и удаления групп.", - "SUMMARY" => "Резюме группы", - "UPDATE" => "Информация обновлена для группы {{name}}" + 'DASHBOARD' => 'Панель управления', + 'NO_FEATURES_YET' => 'Похоже, некоторые функции не были настроены для этого аккаунта... пока. Возможно, они еще не реализованы, или, может быть, кто-то забыл дать вам доступ. В любом случае, мы рады вас видеть здесь!', + 'DELETE_MASTER' => 'Нельзя удалить главный аккаунт!', + 'DELETION_SUCCESSFUL' => 'Пользователь {{user_name}} был успешно удален.', + 'DETAILS_UPDATED' => 'Данные для аккаунта {{user_name}} обновлены', + 'DISABLE_MASTER' => 'Нельзя отключить главный аккаунт!', + 'DISABLE_SELF' => 'Вы не можете отключить собственный аккаунт!', + 'DISABLE_SUCCESSFUL' => 'Пользователь {{user_name}} был успешно отключен.', + + 'ENABLE_SUCCESSFUL' => 'Пользователь {{user_name}} был успешно включен.', + + 'GROUP' => [ + 1 => 'Группа', + 2 => 'Группы', + + 'CREATE' => 'Создать группу', + 'CREATION_SUCCESSFUL' => 'Успешно создана группа {{name}}', + 'DELETE' => 'Удалить группу', + 'DELETE_CONFIRM' => 'Вы уверены, что вы хотите удалить группу {{name}}?', + 'DELETE_DEFAULT' => 'Нельзя удалить группу {{name}}, потому что это группа по умолчанию для новых пользователей.', + 'DELETE_YES' => 'Да, удалить группу', + 'DELETION_SUCCESSFUL' => 'Успешно удалена группа {{name}}', + 'EDIT' => 'Редактор группы', + 'ICON' => 'Значок группы', + 'ICON_EXPLAIN' => 'Значок для членов группы', + 'INFO_PAGE' => 'Описание группы {{name}}', + 'MANAGE' => 'Управление группой', + 'NAME' => 'Имя группы', + 'NAME_EXPLAIN' => 'Пожалуйста, введите имя группы', + 'NOT_EMPTY' => 'Вы не можете сделать это, потому что до сих пор есть пользователи, связанные с группой {{name}}.', + 'PAGE_DESCRIPTION' => 'Список групп для вашего сайта. Предоставляет инструменты управления для редактирования и удаления групп.', + 'SUMMARY' => 'Резюме группы', + 'UPDATE' => 'Информация обновлена для группы {{name}}' ], - "MANUALLY_ACTIVATED" => "{{user_name}} аккаунт был активирован вручную", - "MASTER_ACCOUNT_EXISTS" => "Мастер-аккаунт уже существует!", - "MIGRATION" => [ - "REQUIRED" => "Необходимо обновление базы данных" + 'MANUALLY_ACTIVATED' => '{{user_name}} аккаунт был активирован вручную', + 'MASTER_ACCOUNT_EXISTS' => 'Мастер-аккаунт уже существует!', + 'MIGRATION' => [ + 'REQUIRED' => 'Необходимо обновление базы данных' ], - "PERMISSION" => [ - 1 => "Доступ", - 2 => "Права доступа", - - "ASSIGN_NEW" => "Назначить новые права", - "HOOK_CONDITION" => "Привязки/Условия", - "ID" => "ID доступа", - "INFO_PAGE" => "Информация о доступах для '{{name}}'", - "MANAGE" => "Управление правами", - "NOTE_READ_ONLY" => "Пожалуйста, обратите внимание: права и доступы считаются \"частью кода\" и не могут быть изменены через интерфейс. Чтобы добавить, удалить или изменить доступы, нужно будет использовать сайт базы данных миграции.", - "PAGE_DESCRIPTION" => "Список прав доступа для вашего сайта. Предоставляет инструменты управления для редактирования и удаления прав.", - "SUMMARY" => "Сводка доступов", - "UPDATE" => "Обновление прав", - "VIA_ROLES" => "Имеет права через роли" + 'PERMISSION' => [ + 1 => 'Доступ', + 2 => 'Права доступа', + + 'ASSIGN_NEW' => 'Назначить новые права', + 'HOOK_CONDITION' => 'Привязки/Условия', + 'ID' => 'ID доступа', + 'INFO_PAGE' => "Информация о доступах для '{{name}}'", + 'MANAGE' => 'Управление правами', + 'NOTE_READ_ONLY' => 'Пожалуйста, обратите внимание: права и доступы считаются "частью кода" и не могут быть изменены через интерфейс. Чтобы добавить, удалить или изменить доступы, нужно будет использовать сайт базы данных миграции.', + 'PAGE_DESCRIPTION' => 'Список прав доступа для вашего сайта. Предоставляет инструменты управления для редактирования и удаления прав.', + 'SUMMARY' => 'Сводка доступов', + 'UPDATE' => 'Обновление прав', + 'VIA_ROLES' => 'Имеет права через роли' ], - "ROLE" => [ - 1 => "Роль", - 2 => "Роли", - - "ASSIGN_NEW" => "Назначение новой роли", - "CREATE" => "Создать роль", - "CREATION_SUCCESSFUL" => "Успешно создана роль {{name}}", - "DELETE" => "Удалить роль", - "DELETE_CONFIRM" => "Вы уверены, что вы хотите удалить роль {{name}}?", - "DELETE_DEFAULT" => "Невозможно удалить роль {{name}}, потому что это роль по умолчанию для новых пользователей.", - "DELETE_YES" => "Да, удалить роль", - "DELETION_SUCCESSFUL" => "Успешно удалена роль {{name}}", - "EDIT" => "Изменить роль", - "HAS_USERS" => "Вы не можете сделать это, потому что до сих пор есть пользователи, имеющие роль {{name}}.", - "INFO_PAGE" => "Информации роли для {{name}}", - "MANAGE" => "Управление ролями", - "NAME" => "Имя", - "NAME_EXPLAIN" => "Пожалуйста, укажите имя для роли", - "NAME_IN_USE" => "Роль с именем {{name}} уже существует", - "PAGE_DESCRIPTION" => "Список ролей для вашего сайта. Предоставляет инструменты управления для редактирования и удаления ролей.", - "PERMISSIONS_UPDATED" => "Права обновлены для роли {{name}}", - "SUMMARY" => "Основная информация", - "UPDATED" => "Информация для роли {{name}}" + 'ROLE' => [ + 1 => 'Роль', + 2 => 'Роли', + + 'ASSIGN_NEW' => 'Назначение новой роли', + 'CREATE' => 'Создать роль', + 'CREATION_SUCCESSFUL' => 'Успешно создана роль {{name}}', + 'DELETE' => 'Удалить роль', + 'DELETE_CONFIRM' => 'Вы уверены, что вы хотите удалить роль {{name}}?', + 'DELETE_DEFAULT' => 'Невозможно удалить роль {{name}}, потому что это роль по умолчанию для новых пользователей.', + 'DELETE_YES' => 'Да, удалить роль', + 'DELETION_SUCCESSFUL' => 'Успешно удалена роль {{name}}', + 'EDIT' => 'Изменить роль', + 'HAS_USERS' => 'Вы не можете сделать это, потому что до сих пор есть пользователи, имеющие роль {{name}}.', + 'INFO_PAGE' => 'Информации роли для {{name}}', + 'MANAGE' => 'Управление ролями', + 'NAME' => 'Имя', + 'NAME_EXPLAIN' => 'Пожалуйста, укажите имя для роли', + 'NAME_IN_USE' => 'Роль с именем {{name}} уже существует', + 'PAGE_DESCRIPTION' => 'Список ролей для вашего сайта. Предоставляет инструменты управления для редактирования и удаления ролей.', + 'PERMISSIONS_UPDATED' => 'Права обновлены для роли {{name}}', + 'SUMMARY' => 'Основная информация', + 'UPDATED' => 'Информация для роли {{name}}' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "Системная информация", - - "DB_NAME" => "Имя базы данных", - "DB_VERSION" => "Версия базы данных", - "DIRECTORY" => "Каталог проекта", - "PHP_VERSION" => "Версия PHP", - "SERVER" => "ПО Сервера", - "SPRINKLES" => "Загружены модули", - "UF_VERSION" => "Версия UserFrosting", - "URL" => "URL-адрес сайта" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'Системная информация', + + 'DB_NAME' => 'Имя базы данных', + 'DB_VERSION' => 'Версия базы данных', + 'DIRECTORY' => 'Каталог проекта', + 'PHP_VERSION' => 'Версия PHP', + 'SERVER' => 'ПО Сервера', + 'SPRINKLES' => 'Загружены модули', + 'UF_VERSION' => 'Версия UserFrosting', + 'URL' => 'URL-адрес сайта' ], - "TOGGLE_COLUMNS" => "Переключатель столбцов", + 'TOGGLE_COLUMNS' => 'Переключатель столбцов', - "USER" => [ - 1 => "Пользователь", - 2 => "Пользователи", + 'USER' => [ + 1 => 'Пользователь', + 2 => 'Пользователи', - "ADMIN" => [ - "CHANGE_PASSWORD" => "Сменить пароль пользователя", - "SEND_PASSWORD_LINK" => "Отправить пользователю ссылку, которая позволит выбрать свой собственный пароль", - "SET_PASSWORD" => "Установите пароль пользователя как" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'Сменить пароль пользователя', + 'SEND_PASSWORD_LINK' => 'Отправить пользователю ссылку, которая позволит выбрать свой собственный пароль', + 'SET_PASSWORD' => 'Установите пароль пользователя как' ], - "ACTIVATE" => "Активировать пользователя", - "CREATE" => "Создать пользователя", - "CREATED" => "Пользователь {{user_name}} был успешно создан", - "DELETE" => "Удалить пользователя", - "DELETE_CONFIRM" => "Вы уверены, что вы хотите удалить пользователя {{name}}?", - "DELETE_YES" => "Да, удалить пользователя", - "DELETED" => "Пользователь удален", - "DISABLE" => "Отключить пользователя", - "EDIT" => "Изменить пользователя", - "ENABLE" => "Включить пользователя", - "INFO_PAGE" => "Информация о пользователе для {{name}}", - "LATEST" => "Последние пользователи", - "PAGE_DESCRIPTION" => "Список пользователей для вашего сайта. Предоставляет средства управления, включая возможность редактирования сведений о пользователях, ручной активации пользователей, включения/отключения пользователей и многое другое.", - "SUMMARY" => "Сводка аккаунта", - "VIEW_ALL" => "Все пользователи", - "WITH_PERMISSION" => "Пользователи с этим доступом" + 'ACTIVATE' => 'Активировать пользователя', + 'CREATE' => 'Создать пользователя', + 'CREATED' => 'Пользователь {{user_name}} был успешно создан', + 'DELETE' => 'Удалить пользователя', + 'DELETE_CONFIRM' => 'Вы уверены, что вы хотите удалить пользователя {{name}}?', + 'DELETE_YES' => 'Да, удалить пользователя', + 'DELETED' => 'Пользователь удален', + 'DISABLE' => 'Отключить пользователя', + 'EDIT' => 'Изменить пользователя', + 'ENABLE' => 'Включить пользователя', + 'INFO_PAGE' => 'Информация о пользователе для {{name}}', + 'LATEST' => 'Последние пользователи', + 'PAGE_DESCRIPTION' => 'Список пользователей для вашего сайта. Предоставляет средства управления, включая возможность редактирования сведений о пользователях, ручной активации пользователей, включения/отключения пользователей и многое другое.', + 'SUMMARY' => 'Сводка аккаунта', + 'VIEW_ALL' => 'Все пользователи', + 'WITH_PERMISSION' => 'Пользователи с этим доступом' ], - "X_USER" => [ - 0 => "Нет пользователей", - 1 => "{{plural}} пользователя", - 2 => "{{plural}} пользователей" + 'X_USER' => [ + 0 => 'Нет пользователей', + 1 => '{{plural}} пользователя', + 2 => '{{plural}} пользователей' ] ]; diff --git a/app/sprinkles/admin/locale/th_TH/messages.php b/app/sprinkles/admin/locale/th_TH/messages.php index e31090ae3..e40b1294a 100644 --- a/app/sprinkles/admin/locale/th_TH/messages.php +++ b/app/sprinkles/admin/locale/th_TH/messages.php @@ -4,131 +4,131 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Thai message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\th * @author Karuhut Komol */ - return [ - "ACTIVITY" => [ - 1 => "กิจกรรม", - 2 => "กิจกรรม", + 'ACTIVITY' => [ + 1 => 'กิจกรรม', + 2 => 'กิจกรรม', - "LAST" => "กิจกรรมล่าสุด", - "PAGE" => "รายการกิจกรรมของผู้ใช้", - "TIME" => "เวลาที่ทำกิจกรรม" + 'LAST' => 'กิจกรรมล่าสุด', + 'PAGE' => 'รายการกิจกรรมของผู้ใช้', + 'TIME' => 'เวลาที่ทำกิจกรรม' ], - "CACHE" => [ - "CLEAR" => "ล้างแคช", - "CLEAR_CONFIRM" => "คุณแน่ใจหรือที่จะล้างแคชของเว็บ?", - "CLEAR_CONFIRM_YES" => "ใช่ ล้างแคชเลย", - "CLEARED" => "ล้างแคชเรียบร้อยแล้ว!" + 'CACHE' => [ + 'CLEAR' => 'ล้างแคช', + 'CLEAR_CONFIRM' => 'คุณแน่ใจหรือที่จะล้างแคชของเว็บ?', + 'CLEAR_CONFIRM_YES' => 'ใช่ ล้างแคชเลย', + 'CLEARED' => 'ล้างแคชเรียบร้อยแล้ว!' ], - "DASHBOARD" => "แผงควบคุม", - "DELETE_MASTER" => "คุณไม่สามารถลบบัญชีหลักได้!", - "DELETION_SUCCESSFUL" => "ลบผู้ใช้ {{user_name}} เรียบร้อยแล้ว", - "DETAILS_UPDATED" => "ปรับปรุงรายระเอียดบัญชีให้กับ {{user_name}} แล้ว", - "DISABLE_MASTER" => "คุณไม่สามารถปิดการใช้งานบัญชีหลัก!", - "DISABLE_SUCCESSFUL" => "ปิดการใช้งานบัญชีของผู้ใช้ {{user_name}} เรียบร้อยแล้ว", - - "ENABLE_SUCCESSFUL" => "เปิดการใช้งานบัญชีของผู้ใช้ {{user_name}} เรียบร้อยแล้ว", - - "GROUP" => [ - 1 => "กลุ่ม", - 2 => "กลุ่ม", - - "CREATE" => "สร้างกลุ่ม", - "DELETE" => "ลบกลุ่ม", - "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบกลุ่ม {{name}}?", - "DELETE_YES" => "ใช่ ลบกลุ่มนี้เลย", - "EDIT" => "แก้ไขกลุ่ม", - "ICON" => "ไอคอนกลุ่ม", - "ICON_EXPLAIN" => "ไอคอนสำหรับสมาชิกกลุ่ม", - "INFO_PAGE" => "หน้าข้อมูลกลุ่มสำหรับ {{name}}", + 'DASHBOARD' => 'แผงควบคุม', + 'DELETE_MASTER' => 'คุณไม่สามารถลบบัญชีหลักได้!', + 'DELETION_SUCCESSFUL' => 'ลบผู้ใช้ {{user_name}} เรียบร้อยแล้ว', + 'DETAILS_UPDATED' => 'ปรับปรุงรายระเอียดบัญชีให้กับ {{user_name}} แล้ว', + 'DISABLE_MASTER' => 'คุณไม่สามารถปิดการใช้งานบัญชีหลัก!', + 'DISABLE_SUCCESSFUL' => 'ปิดการใช้งานบัญชีของผู้ใช้ {{user_name}} เรียบร้อยแล้ว', + + 'ENABLE_SUCCESSFUL' => 'เปิดการใช้งานบัญชีของผู้ใช้ {{user_name}} เรียบร้อยแล้ว', + + 'GROUP' => [ + 1 => 'กลุ่ม', + 2 => 'กลุ่ม', + + 'CREATE' => 'สร้างกลุ่ม', + 'DELETE' => 'ลบกลุ่ม', + 'DELETE_CONFIRM' => 'คุณแน่ใจหรือที่จะลบกลุ่ม {{name}}?', + 'DELETE_YES' => 'ใช่ ลบกลุ่มนี้เลย', + 'EDIT' => 'แก้ไขกลุ่ม', + 'ICON' => 'ไอคอนกลุ่ม', + 'ICON_EXPLAIN' => 'ไอคอนสำหรับสมาชิกกลุ่ม', + 'INFO_PAGE' => 'หน้าข้อมูลกลุ่มสำหรับ {{name}}', //"MANAGE" => "Manage group", - "NAME" => "ชื่อกลุ่ม", - "NAME_EXPLAIN" => "กรุณาตั้งชื่อสำหรับกลุ่มนี้", - "PAGE_DESCRIPTION" => "รายชื่อกลุ่มในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับการแก้ไขและลบกลุ่ม" + 'NAME' => 'ชื่อกลุ่ม', + 'NAME_EXPLAIN' => 'กรุณาตั้งชื่อสำหรับกลุ่มนี้', + 'PAGE_DESCRIPTION' => 'รายชื่อกลุ่มในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับการแก้ไขและลบกลุ่ม' ], - "MANUALLY_ACTIVATED" => "บัญชีของ {{user_name}} ได้เปิดใช้งานเองแล้ว", - "MASTER_ACCOUNT_EXISTS" => "มีบัญชีหลักอยู่แล้ว!", - "MIGRATION" => [ - "REQUIRED" => "ต้องการการปรับปรุงฐานข้อมูล" + 'MANUALLY_ACTIVATED' => 'บัญชีของ {{user_name}} ได้เปิดใช้งานเองแล้ว', + 'MASTER_ACCOUNT_EXISTS' => 'มีบัญชีหลักอยู่แล้ว!', + 'MIGRATION' => [ + 'REQUIRED' => 'ต้องการการปรับปรุงฐานข้อมูล' ], - "PERMISSION" => [ - 1 => "สิทธิการเข้าถึง", - 2 => "สิทธิการเข้าถึง", + 'PERMISSION' => [ + 1 => 'สิทธิการเข้าถึง', + 2 => 'สิทธิการเข้าถึง', - "ASSIGN_NEW" => "กำหนดสิทธิการเข้าถึงใหม่", - "HOOK_CONDITION" => "ข้อกำหนด/เงื่อนไข", - "MANAGE" => "จัดการสิทธิการเข้าถึง", - "PAGE_DESCRIPTION" => "รายการสิทธิการเข้าถึงในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับการแก้ไขและลบสิทธิการเข้าถึง", - "UPDATE" => "ปรับปรุงสิทธิการเข้าถึง" + 'ASSIGN_NEW' => 'กำหนดสิทธิการเข้าถึงใหม่', + 'HOOK_CONDITION' => 'ข้อกำหนด/เงื่อนไข', + 'MANAGE' => 'จัดการสิทธิการเข้าถึง', + 'PAGE_DESCRIPTION' => 'รายการสิทธิการเข้าถึงในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับการแก้ไขและลบสิทธิการเข้าถึง', + 'UPDATE' => 'ปรับปรุงสิทธิการเข้าถึง' ], - "ROLE" => [ - 1 => "ตำแหน่ง", - 2 => "ตำแหน่ง", - - "ASSIGN_NEW" => "กำหนดตำแหน่งใหม่", - "CREATE" => "สร้างตำแหน่ง", - "DELETE" => "ลบตำแหน่ง", - "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบตำแหน่ง {{name}}?", - "DELETE_YES" => "ใช่ ลบตำแหน่งนี้เลย", - "EDIT" => "แก้ไขตำแหน่ง", - "INFO_PAGE" => "หน้าข้อมูลตำแหน่งสำหรับ {{name}}", - "MANAGE" => "จัดการตำแหน่ง", - "NAME" => "ชื่อ", - "NAME_EXPLAIN" => "กรุณาตั้งชื่อสำหรับตำแหน่งนี้", - "PAGE_DESCRIPTION" => "รายชื่อตำแหน่งในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับแก้ไขและลบตำแหน่ง", - "UPDATED" => "ปรับปรุงตำแหน่ง" + 'ROLE' => [ + 1 => 'ตำแหน่ง', + 2 => 'ตำแหน่ง', + + 'ASSIGN_NEW' => 'กำหนดตำแหน่งใหม่', + 'CREATE' => 'สร้างตำแหน่ง', + 'DELETE' => 'ลบตำแหน่ง', + 'DELETE_CONFIRM' => 'คุณแน่ใจหรือที่จะลบตำแหน่ง {{name}}?', + 'DELETE_YES' => 'ใช่ ลบตำแหน่งนี้เลย', + 'EDIT' => 'แก้ไขตำแหน่ง', + 'INFO_PAGE' => 'หน้าข้อมูลตำแหน่งสำหรับ {{name}}', + 'MANAGE' => 'จัดการตำแหน่ง', + 'NAME' => 'ชื่อ', + 'NAME_EXPLAIN' => 'กรุณาตั้งชื่อสำหรับตำแหน่งนี้', + 'PAGE_DESCRIPTION' => 'รายชื่อตำแหน่งในเว็บของคุณ ประกอบไปด้วยเครื่องมือในการจัดการสำหรับแก้ไขและลบตำแหน่ง', + 'UPDATED' => 'ปรับปรุงตำแหน่ง' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "ข้อมูลระบบ", - - "DB_NAME" => "ชื่อฐานข้อมูล", - "DB_VERSION" => "เวอร์ชั่นฐานข้อมูล", - "DIRECTORY" => "ไดเรกทอรีของโปรเจค", - "PHP_VERSION" => "เวอร์ชั่น PHP", - "SERVER" => "ซอฟต์แวร์เว็บเซิร์ฟเวอร์", - "SPRINKLES" => "Sprinkles ที่ถูกโหลด", - "UF_VERSION" => "เวอร์ชั่น UserFrosting", - "URL" => "URL ของรากเว็บไซต์" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'ข้อมูลระบบ', + + 'DB_NAME' => 'ชื่อฐานข้อมูล', + 'DB_VERSION' => 'เวอร์ชั่นฐานข้อมูล', + 'DIRECTORY' => 'ไดเรกทอรีของโปรเจค', + 'PHP_VERSION' => 'เวอร์ชั่น PHP', + 'SERVER' => 'ซอฟต์แวร์เว็บเซิร์ฟเวอร์', + 'SPRINKLES' => 'Sprinkles ที่ถูกโหลด', + 'UF_VERSION' => 'เวอร์ชั่น UserFrosting', + 'URL' => 'URL ของรากเว็บไซต์' ], - "USER" => [ - 1 => "ผู้ใช้", - 2 => "ผู้ใช้", + 'USER' => [ + 1 => 'ผู้ใช้', + 2 => 'ผู้ใช้', - "ADMIN" => [ - "CHANGE_PASSWORD" => "เปลี่ยนรหัสผ่านผู้ใช้", - "SEND_PASSWORD_LINK" => "ส่งลิงก์ที่จะอนุญาตให้ผู้ใช้เลือกรหัสผ่านเองให้กับผู้ใช้", - "SET_PASSWORD" => "ตั้งรหัสผ่านของผู้ใช้เป็น" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'เปลี่ยนรหัสผ่านผู้ใช้', + 'SEND_PASSWORD_LINK' => 'ส่งลิงก์ที่จะอนุญาตให้ผู้ใช้เลือกรหัสผ่านเองให้กับผู้ใช้', + 'SET_PASSWORD' => 'ตั้งรหัสผ่านของผู้ใช้เป็น' ], - "ACTIVATE" => "เปิดใช้งานผู้ใช้", - "CREATE" => "สร้างผู้ใช้", - "DELETE" => "ลบผู้ใช้", - "DELETE_CONFIRM" => "คุณแน่ใจหรือที่จะลบผู้ใช้ {{name}}?", - "DELETE_YES" => "ใช่ ลบผู้ใช้นี้เลย", - "DISABLE" => "ปิดการใช้งานผู้ใช้", - "EDIT" => "แก้ไขผู้ใช้", - "ENABLE" => "เปิดการใช้งานผู้ใช้", - "INFO_PAGE" => "หน้าข้อมูลของผู้ใช้ {{name}}", - "PAGE_DESCRIPTION" => "รายชื่อผู้ใช้ในเว็บของคุณ ประกอบไปด้วยเครื่องมือสำหรับการจัดการ รวมทั้งความสามารถในการแก้ไขรายละเอียดผู้ใช้ การเปิดใช้งานผู้ใช้ การเปิด/ปิดบัญชีผู้ใช้และอื่น ๆ", - "LATEST" => "ผู้ใช้ล่าสุด", - "VIEW_ALL" => "ดูผู้ใช้ทั้งหมด" + 'ACTIVATE' => 'เปิดใช้งานผู้ใช้', + 'CREATE' => 'สร้างผู้ใช้', + 'DELETE' => 'ลบผู้ใช้', + 'DELETE_CONFIRM' => 'คุณแน่ใจหรือที่จะลบผู้ใช้ {{name}}?', + 'DELETE_YES' => 'ใช่ ลบผู้ใช้นี้เลย', + 'DISABLE' => 'ปิดการใช้งานผู้ใช้', + 'EDIT' => 'แก้ไขผู้ใช้', + 'ENABLE' => 'เปิดการใช้งานผู้ใช้', + 'INFO_PAGE' => 'หน้าข้อมูลของผู้ใช้ {{name}}', + 'PAGE_DESCRIPTION' => 'รายชื่อผู้ใช้ในเว็บของคุณ ประกอบไปด้วยเครื่องมือสำหรับการจัดการ รวมทั้งความสามารถในการแก้ไขรายละเอียดผู้ใช้ การเปิดใช้งานผู้ใช้ การเปิด/ปิดบัญชีผู้ใช้และอื่น ๆ', + 'LATEST' => 'ผู้ใช้ล่าสุด', + 'VIEW_ALL' => 'ดูผู้ใช้ทั้งหมด' ], - "X_USER" => [ - 0 => "ไม่มีผู้ใช้", - 1 => "{{plural}} ผู้ใช้", - 2 => "{{plural}} ผู้ใช้" + 'X_USER' => [ + 0 => 'ไม่มีผู้ใช้', + 1 => '{{plural}} ผู้ใช้', + 2 => '{{plural}} ผู้ใช้' ] ]; diff --git a/app/sprinkles/admin/locale/tr/messages.php b/app/sprinkles/admin/locale/tr/messages.php index 25d5633e1..4311727e0 100644 --- a/app/sprinkles/admin/locale/tr/messages.php +++ b/app/sprinkles/admin/locale/tr/messages.php @@ -4,157 +4,157 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Turkish message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\tr * @author Dumblledore */ - return [ - "ACTIVITY" => [ - 1 => "Etkinlik", - 2 => "Etkinlikler", + 'ACTIVITY' => [ + 1 => 'Etkinlik', + 2 => 'Etkinlikler', - "LAST" => "Son Etkinlik", - "PAGE" => "Kullanıcı etkinliklerinin listesi", - "TIME" => "Aktivite zamanı" + 'LAST' => 'Son Etkinlik', + 'PAGE' => 'Kullanıcı etkinliklerinin listesi', + 'TIME' => 'Aktivite zamanı' ], - "CACHE" => [ - "CLEAR" => "Önbelleği temizle", - "CLEAR_CONFIRM" => "Site önbelleğini temizlemek istediğine emin misin?", - "CLEAR_CONFIRM_YES" => "Evet, önbelleği temizle", - "CLEARED" => "Önbellek temizlenmesi başarıyla tamamlandı!" + 'CACHE' => [ + 'CLEAR' => 'Önbelleği temizle', + 'CLEAR_CONFIRM' => 'Site önbelleğini temizlemek istediğine emin misin?', + 'CLEAR_CONFIRM_YES' => 'Evet, önbelleği temizle', + 'CLEARED' => 'Önbellek temizlenmesi başarıyla tamamlandı!' ], - "DASHBOARD" => "Pano", - "NO_FEATURES_YET" => "Bu hesap için herhangi bir özellik ayarlanmış gibi görünmüyor... Henüz. Belki de henüz uygulanmadı, veya belki birisi size erişim vermeyi unutttu. Her iki durumda da sizi aramızda gördüğümüze sevindik!", - "DELETE_MASTER" => "Ana hesabı silemezsiniz!", - "DELETION_SUCCESSFUL" => "Kullanıcı{{user_name}} silme işlemi başarıyla tamamlandı.", - "DETAILS_UPDATED" => "Kullanıcı{{user_name}} için güncel hesap detayları", - "DISABLE_MASTER" => "Ana hesabı devre dışı bırakamazsınız!", - "DISABLE_SELF" => "Kendi hesabınızın etkinliğini sonlandıramazsınız!", - "DISABLE_SUCCESSFUL" => "Kullanıcı hesabın {{user_name}}başarıyla devre dışı bırakıldı.", - - "ENABLE_SUCCESSFUL" => "Kullanıcı hesabın{{user_name}}başarıyla etkinleştirildi.", - - "GROUP" => [ - 1 => "Grup", - 2 => "Grıplar", - - "CREATE" => "Grup oluşturmak", - "CREATION_SUCCESSFUL" => "Grup oluşturma başarılı{{name}}", - "DELETE" => "Grubu sil", - "DELETE_CONFIRM" => "Grubu silmek istediğine emin misin{{name}}?", - "DELETE_DEFAULT" => "Grubu silemezsin{{name}} çünkü o yeni kayıtlanan kullanıcılar için varsayılan grup.", - "DELETE_YES" => "Evet, grubu sil", - "DELETION_SUCCESSFUL" => "Grup silme başarılı{{name}}", - "EDIT" => "Grubu düzenle", - "ICON" => "Grup ikonu", - "ICON_EXPLAIN" => "Grup iyileri için ikon", - "INFO_PAGE" => "Grup bilgisi sayfası {{name}} için", - "MANAGE" => "Grubu yönet", - "NAME" => "Grup adı", - "NAME_EXPLAIN" => "Lütfen grup için bir isim giriniz", - "NOT_EMPTY" => "Bunu yapamazsınız çünkü hala grupla ilişkili kullanıcılar var{{name}}.", - "PAGE_DESCRIPTION" => "Siten için grupların bir listesi. Grupları silmek ve düzenlemek için yönetim araçları sağlar.", - "SUMMARY" => "Grup özeti", - "UPDATE" => "Grup için detaylar güncellendi{{name}}" + 'DASHBOARD' => 'Pano', + 'NO_FEATURES_YET' => 'Bu hesap için herhangi bir özellik ayarlanmış gibi görünmüyor... Henüz. Belki de henüz uygulanmadı, veya belki birisi size erişim vermeyi unutttu. Her iki durumda da sizi aramızda gördüğümüze sevindik!', + 'DELETE_MASTER' => 'Ana hesabı silemezsiniz!', + 'DELETION_SUCCESSFUL' => 'Kullanıcı{{user_name}} silme işlemi başarıyla tamamlandı.', + 'DETAILS_UPDATED' => 'Kullanıcı{{user_name}} için güncel hesap detayları', + 'DISABLE_MASTER' => 'Ana hesabı devre dışı bırakamazsınız!', + 'DISABLE_SELF' => 'Kendi hesabınızın etkinliğini sonlandıramazsınız!', + 'DISABLE_SUCCESSFUL' => 'Kullanıcı hesabın {{user_name}}başarıyla devre dışı bırakıldı.', + + 'ENABLE_SUCCESSFUL' => 'Kullanıcı hesabın{{user_name}}başarıyla etkinleştirildi.', + + 'GROUP' => [ + 1 => 'Grup', + 2 => 'Grıplar', + + 'CREATE' => 'Grup oluşturmak', + 'CREATION_SUCCESSFUL' => 'Grup oluşturma başarılı{{name}}', + 'DELETE' => 'Grubu sil', + 'DELETE_CONFIRM' => 'Grubu silmek istediğine emin misin{{name}}?', + 'DELETE_DEFAULT' => 'Grubu silemezsin{{name}} çünkü o yeni kayıtlanan kullanıcılar için varsayılan grup.', + 'DELETE_YES' => 'Evet, grubu sil', + 'DELETION_SUCCESSFUL' => 'Grup silme başarılı{{name}}', + 'EDIT' => 'Grubu düzenle', + 'ICON' => 'Grup ikonu', + 'ICON_EXPLAIN' => 'Grup iyileri için ikon', + 'INFO_PAGE' => 'Grup bilgisi sayfası {{name}} için', + 'MANAGE' => 'Grubu yönet', + 'NAME' => 'Grup adı', + 'NAME_EXPLAIN' => 'Lütfen grup için bir isim giriniz', + 'NOT_EMPTY' => 'Bunu yapamazsınız çünkü hala grupla ilişkili kullanıcılar var{{name}}.', + 'PAGE_DESCRIPTION' => 'Siten için grupların bir listesi. Grupları silmek ve düzenlemek için yönetim araçları sağlar.', + 'SUMMARY' => 'Grup özeti', + 'UPDATE' => 'Grup için detaylar güncellendi{{name}}' ], - "MANUALLY_ACTIVATED" => "{{user_name}}'ın hesabı el ile aktifleştirildi", - "MASTER_ACCOUNT_EXISTS" => "Ana hesap zaten mevcut!", - "MIGRATION" => [ - "REQUIRED" => "Veritabanını güncellemek gerek" + 'MANUALLY_ACTIVATED' => "{{user_name}}'ın hesabı el ile aktifleştirildi", + 'MASTER_ACCOUNT_EXISTS' => 'Ana hesap zaten mevcut!', + 'MIGRATION' => [ + 'REQUIRED' => 'Veritabanını güncellemek gerek' ], - "PERMISSION" => [ - 1 => "İzin", - 2 => "İzinler", - - "ASSIGN_NEW" => "Yeni izin ata", - "HOOK_CONDITION" => "Kanca/Koşullar", - "ID" => "İzin Kimliği", - "INFO_PAGE" => "{{name}} için izin bilgi sayfası", - "MANAGE" => "İzinleri yönet", - "NOTE_READ_ONLY" => "Lütfen Dikkat izinler ''bir kodun parçası'' olarak kabul edilir ve arayüz aracılığıyla değiştirilemez. İzln eklemek, kaldırmak ya da değiştirmek için site bakımcıları bir veritabanı geçişi kullanmalıdır", - "PAGE_DESCRIPTION" => "Siteniz için izinlerin bir listesi. Düzenleme yapmak ve izinleri kaldırmak yönetim araçları temin eder.", - "SUMMARY" => "İzin Özeti", - "UPDATE" => "İzinlerin Güncellenmesi", - "VIA_ROLES" => "Roller ile izin alımı" + 'PERMISSION' => [ + 1 => 'İzin', + 2 => 'İzinler', + + 'ASSIGN_NEW' => 'Yeni izin ata', + 'HOOK_CONDITION' => 'Kanca/Koşullar', + 'ID' => 'İzin Kimliği', + 'INFO_PAGE' => '{{name}} için izin bilgi sayfası', + 'MANAGE' => 'İzinleri yönet', + 'NOTE_READ_ONLY' => "Lütfen Dikkat izinler ''bir kodun parçası'' olarak kabul edilir ve arayüz aracılığıyla değiştirilemez. İzln eklemek, kaldırmak ya da değiştirmek için site bakımcıları bir veritabanı geçişi kullanmalıdır", + 'PAGE_DESCRIPTION' => 'Siteniz için izinlerin bir listesi. Düzenleme yapmak ve izinleri kaldırmak yönetim araçları temin eder.', + 'SUMMARY' => 'İzin Özeti', + 'UPDATE' => 'İzinlerin Güncellenmesi', + 'VIA_ROLES' => 'Roller ile izin alımı' ], - "ROLE" => [ - 1 => "Rol", - 2 => "Roller", - - "ASSIGN_NEW" => "Yeni rol ata", - "CREATE" => "Rol oluştur", - "CREATION_SUCCESSFUL" => "Rol oluşturma başarılı {{name}}", - "DELETE" => "Rolü sil", - "DELETE_CONFIRM" => "Rolü silmek istediğine emin misin {{name}}?", - "DELETE_DEFAULT" => "Rolü silemezsin {{name}} çünkü o kaydolmuş kullanıcılar için varsayılan bir rol.", - "DELETE_YES" => "Evet, rolü sil", - "DELETION_SUCCESSFUL" => "Rol başarıyla silindi{{name}}", - "EDIT" => "Rolü düzenle", - "HAS_USERS" => "Bunu yapamazsın çünkü hala bu rol ile bağlantılı kullanıcılar var{{name}}.", - "INFO_PAGE" => "{{name}} için rol bilgi sayfası", - "MANAGE" => "Rolleri yönet", - "NAME" => "Ad", - "NAME_EXPLAIN" => "Lütfen rol için bir ad giriniz", - "NAME_IN_USE" => "{{name}} adında bir rol zaten mevcut", - "PAGE_DESCRIPTION" => "Siteniz için rollerin bir listesi. Düzenlemek ve rolleri silmek için yönetim araçları sağlar.", - "PERMISSIONS_UPDATED" => "Rol için izinler güncellendi{{name}}", - "SUMMARY" => "Rol özeti", - "UPDATED" => "Rol için detaylar güncellendi{{name}}" + 'ROLE' => [ + 1 => 'Rol', + 2 => 'Roller', + + 'ASSIGN_NEW' => 'Yeni rol ata', + 'CREATE' => 'Rol oluştur', + 'CREATION_SUCCESSFUL' => 'Rol oluşturma başarılı {{name}}', + 'DELETE' => 'Rolü sil', + 'DELETE_CONFIRM' => 'Rolü silmek istediğine emin misin {{name}}?', + 'DELETE_DEFAULT' => 'Rolü silemezsin {{name}} çünkü o kaydolmuş kullanıcılar için varsayılan bir rol.', + 'DELETE_YES' => 'Evet, rolü sil', + 'DELETION_SUCCESSFUL' => 'Rol başarıyla silindi{{name}}', + 'EDIT' => 'Rolü düzenle', + 'HAS_USERS' => 'Bunu yapamazsın çünkü hala bu rol ile bağlantılı kullanıcılar var{{name}}.', + 'INFO_PAGE' => '{{name}} için rol bilgi sayfası', + 'MANAGE' => 'Rolleri yönet', + 'NAME' => 'Ad', + 'NAME_EXPLAIN' => 'Lütfen rol için bir ad giriniz', + 'NAME_IN_USE' => '{{name}} adında bir rol zaten mevcut', + 'PAGE_DESCRIPTION' => 'Siteniz için rollerin bir listesi. Düzenlemek ve rolleri silmek için yönetim araçları sağlar.', + 'PERMISSIONS_UPDATED' => 'Rol için izinler güncellendi{{name}}', + 'SUMMARY' => 'Rol özeti', + 'UPDATED' => 'Rol için detaylar güncellendi{{name}}' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "Sistem bilgisi", - - "DB_NAME" => "Veritabanı adı", - "DB_VERSION" => "Veritabanı sürümü", - "DIRECTORY" => "Proje dizini", - "PHP_VERSION" => "PHP sürümü", - "SERVER" => "Web sunucu yazılımı", - "SPRINKLES" => "Yüklü serpintiler", - "UF_VERSION" => "UserFrosting sürümü", - "URL" => "Site kök url" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => 'Sistem bilgisi', + + 'DB_NAME' => 'Veritabanı adı', + 'DB_VERSION' => 'Veritabanı sürümü', + 'DIRECTORY' => 'Proje dizini', + 'PHP_VERSION' => 'PHP sürümü', + 'SERVER' => 'Web sunucu yazılımı', + 'SPRINKLES' => 'Yüklü serpintiler', + 'UF_VERSION' => 'UserFrosting sürümü', + 'URL' => 'Site kök url' ], - "TOGGLE_COLUMNS" => "Sütünları değiştirme", + 'TOGGLE_COLUMNS' => 'Sütünları değiştirme', - "USER" => [ - 1 => "Kullanıcı", - 2 => "Kullanıcılar", + 'USER' => [ + 1 => 'Kullanıcı', + 2 => 'Kullanıcılar', - "ADMIN" => [ - "CHANGE_PASSWORD" => "Kullanıcı şifresini değiştir", - "SEND_PASSWORD_LINK" => "Kullanıcıya kendi şifresini seçebileceği bir bağlantı gönder", - "SET_PASSWORD" => "Kullanıcının şifresi olarak ayarla" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => 'Kullanıcı şifresini değiştir', + 'SEND_PASSWORD_LINK' => 'Kullanıcıya kendi şifresini seçebileceği bir bağlantı gönder', + 'SET_PASSWORD' => 'Kullanıcının şifresi olarak ayarla' ], - "ACTIVATE" => "Aktif Kullanıcı", - "CREATE" => "Kullanıcı oluştur", - "CREATED" => "Kullanıcı {{user_name}} başarıyla oluşturuldu", - "DELETE" => "Kullanıcıyı sil", - "DELETE_CONFIRM" => "Kullanıcıyı silmek istediğinden emin misin?{{name}}?", - "DELETE_YES" => "Evet, kullanıcıyı sil", - "DELETED" => "Kullanıcı silindi", - "DISABLE" => "Kullanıcı devre dışı", - "EDIT" => "Kullanıcıyı düzenle", - "ENABLE" => "Kullanıcı etkin", - "INFO_PAGE" => "{{name}} için kullanıcı bilgisi", - "LATEST" => "Son Kullanıcılar", - "PAGE_DESCRIPTION" => "Siten için kullanıcıların listesi. Kullanıcı detaylarını düzenlemek, elle kullanıcıları aktifleştirmek, kullanıcıları etkinleştirme/devre dışı bırakma, ve daha fazlası için yönetimsel araçlar sağlar.", - "SUMMARY" => "Hesap özeti", - "VIEW_ALL" => "Tüm kullanıcıları göster", - "WITH_PERMISSION" => "Bu izni olan kullanıcılar" + 'ACTIVATE' => 'Aktif Kullanıcı', + 'CREATE' => 'Kullanıcı oluştur', + 'CREATED' => 'Kullanıcı {{user_name}} başarıyla oluşturuldu', + 'DELETE' => 'Kullanıcıyı sil', + 'DELETE_CONFIRM' => 'Kullanıcıyı silmek istediğinden emin misin?{{name}}?', + 'DELETE_YES' => 'Evet, kullanıcıyı sil', + 'DELETED' => 'Kullanıcı silindi', + 'DISABLE' => 'Kullanıcı devre dışı', + 'EDIT' => 'Kullanıcıyı düzenle', + 'ENABLE' => 'Kullanıcı etkin', + 'INFO_PAGE' => '{{name}} için kullanıcı bilgisi', + 'LATEST' => 'Son Kullanıcılar', + 'PAGE_DESCRIPTION' => 'Siten için kullanıcıların listesi. Kullanıcı detaylarını düzenlemek, elle kullanıcıları aktifleştirmek, kullanıcıları etkinleştirme/devre dışı bırakma, ve daha fazlası için yönetimsel araçlar sağlar.', + 'SUMMARY' => 'Hesap özeti', + 'VIEW_ALL' => 'Tüm kullanıcıları göster', + 'WITH_PERMISSION' => 'Bu izni olan kullanıcılar' ], - "X_USER" => [ - 0 => "Kullanıcı yok", - 1 => "{{plural}} kullanıcı", - 2 => "{{plural}} kullanıcılar" + 'X_USER' => [ + 0 => 'Kullanıcı yok', + 1 => '{{plural}} kullanıcı', + 2 => '{{plural}} kullanıcılar' ] ]; diff --git a/app/sprinkles/admin/locale/zh_CN/messages.php b/app/sprinkles/admin/locale/zh_CN/messages.php index 2adc8c88b..870422e93 100644 --- a/app/sprinkles/admin/locale/zh_CN/messages.php +++ b/app/sprinkles/admin/locale/zh_CN/messages.php @@ -4,158 +4,158 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Chinese message token translations for the 'admin' sprinkle. * - * @package userfrosting\i18n\zh_CN * @author @BruceGui (https://github.com/BruceGui) */ - return [ - "ACTIVITY" => [ - 1 => "活动", - 2 => "活动", + 'ACTIVITY' => [ + 1 => '活动', + 2 => '活动', - "LAST" => "最后活动", - "PAGE" => "用户活动列表", - "TIME" => "活动时间" + 'LAST' => '最后活动', + 'PAGE' => '用户活动列表', + 'TIME' => '活动时间' ], - "ADMIN" => [ - "PANEL" => "控制台" + 'ADMIN' => [ + 'PANEL' => '控制台' ], - "CACHE" => [ - "CLEAR" => "清除缓存", - "CLEAR_CONFIRM" => "你确定要清除此网站的缓存?", - "CLEAR_CONFIRM_YES" => "是的, 清除缓存", - "CLEARED" => "缓存成功清除 !" + 'CACHE' => [ + 'CLEAR' => '清除缓存', + 'CLEAR_CONFIRM' => '你确定要清除此网站的缓存?', + 'CLEAR_CONFIRM_YES' => '是的, 清除缓存', + 'CLEARED' => '缓存成功清除 !' ], - "DASHBOARD" => "仪表盘", - "DELETE_MASTER" => "你不能删除超级账户!", - "DELETION_SUCCESSFUL" => "用户 {{user_name}} 删除成功.", - "DETAILS_UPDATED" => "用户 {{user_name}} 更新成功", - "DISABLE_MASTER" => "你不能禁用超级用户!", - "DISABLE_SELF" => "不能禁用你自己的账户!", - "DISABLE_SUCCESSFUL" => "用户名{{user_name}} 成功禁用.", - - "ENABLE_SUCCESSFUL" => "用户名 {{user_name}} 启用成功.", - - "GROUP" => [ - 1 => "组", - 2 => "组", - - "CREATE" => "新建组", - "CREATION_SUCCESSFUL" => "成功创建组 {{name}}", - "DELETE" => "删除组", - "DELETE_CONFIRM" => "确定要删除组 {{name}}?", - "DELETE_DEFAULT" => "你无法删除组 {{name}} 因为这是新注册用户的默认组.", - "DELETE_YES" => "是, 删除组", - "DELETION_SUCCESSFUL" => "成功删除组{{name}}", - "EDIT" => "编辑组", - "ICON" => "组图标", - "ICON_EXPLAIN" => "组成员图标", - "INFO_PAGE" => "{{name}} 组的信息页", - "NAME" => "组名", - "NAME_EXPLAIN" => "请为组取一个名字", - "NOT_EMPTY" => "你不能这样做,因为还有用户在组 {{name}}.", - "PAGE_DESCRIPTION" => "网站组列表. 请管理编辑和删除组的工具.", - "SUMMARY" => "组简介", - "UPDATE" => "组{{name}}的信息已经更新" + 'DASHBOARD' => '仪表盘', + 'DELETE_MASTER' => '你不能删除超级账户!', + 'DELETION_SUCCESSFUL' => '用户 {{user_name}} 删除成功.', + 'DETAILS_UPDATED' => '用户 {{user_name}} 更新成功', + 'DISABLE_MASTER' => '你不能禁用超级用户!', + 'DISABLE_SELF' => '不能禁用你自己的账户!', + 'DISABLE_SUCCESSFUL' => '用户名{{user_name}} 成功禁用.', + + 'ENABLE_SUCCESSFUL' => '用户名 {{user_name}} 启用成功.', + + 'GROUP' => [ + 1 => '组', + 2 => '组', + + 'CREATE' => '新建组', + 'CREATION_SUCCESSFUL' => '成功创建组 {{name}}', + 'DELETE' => '删除组', + 'DELETE_CONFIRM' => '确定要删除组 {{name}}?', + 'DELETE_DEFAULT' => '你无法删除组 {{name}} 因为这是新注册用户的默认组.', + 'DELETE_YES' => '是, 删除组', + 'DELETION_SUCCESSFUL' => '成功删除组{{name}}', + 'EDIT' => '编辑组', + 'ICON' => '组图标', + 'ICON_EXPLAIN' => '组成员图标', + 'INFO_PAGE' => '{{name}} 组的信息页', + 'NAME' => '组名', + 'NAME_EXPLAIN' => '请为组取一个名字', + 'NOT_EMPTY' => '你不能这样做,因为还有用户在组 {{name}}.', + 'PAGE_DESCRIPTION' => '网站组列表. 请管理编辑和删除组的工具.', + 'SUMMARY' => '组简介', + 'UPDATE' => '组{{name}}的信息已经更新' ], - "MANUALLY_ACTIVATED" => "{{user_name}} 账户已手动激活", - "MASTER_ACCOUNT_EXISTS" => "超级账户已存在!", - "MIGRATION" => [ - "REQUIRED" => "数据库需要更新" + 'MANUALLY_ACTIVATED' => '{{user_name}} 账户已手动激活', + 'MASTER_ACCOUNT_EXISTS' => '超级账户已存在!', + 'MIGRATION' => [ + 'REQUIRED' => '数据库需要更新' ], - "PERMISSION" => [ - 1 => "权限", - 2 => "权限", - - "ASSIGN_NEW" => "分配新权限", - "HOOK_CONDITION" => "Hook/条件", - "ID" => "权限ID", - "INFO_PAGE" => "用户 '{{name}}' 的权限页", - "MANAGE" => "管理权限", - "NOTE_READ_ONLY" => "请注意: 权限是 \"part of the code\" 不能通过界面修改. 如果要添加、删除、编辑权限, 网站维护者需要 进行数据库迁移.", - "PAGE_DESCRIPTION" => "网站的权限列表. 提供编辑和删除权限的工具.", - "SUMMARY" => "权限概要", - "UPDATE" => "更新权限", - "VIA_ROLES" => "权限通过用户了" + 'PERMISSION' => [ + 1 => '权限', + 2 => '权限', + + 'ASSIGN_NEW' => '分配新权限', + 'HOOK_CONDITION' => 'Hook/条件', + 'ID' => '权限ID', + 'INFO_PAGE' => "用户 '{{name}}' 的权限页", + 'MANAGE' => '管理权限', + 'NOTE_READ_ONLY' => '请注意: 权限是 "part of the code" 不能通过界面修改. 如果要添加、删除、编辑权限, 网站维护者需要 进行数据库迁移.', + 'PAGE_DESCRIPTION' => '网站的权限列表. 提供编辑和删除权限的工具.', + 'SUMMARY' => '权限概要', + 'UPDATE' => '更新权限', + 'VIA_ROLES' => '权限通过用户了' ], - "ROLE" => [ - 1 => "角色", - 2 => "角色", - - "ASSIGN_NEW" => "分配角色", - "CREATE" => "创建角色", - "CREATION_SUCCESSFUL" => "成功创建角色 {{name}}", - "DELETE" => "删除角色", - "DELETE_CONFIRM" => "你确定要删除角色 {{name}}?", - "DELETE_DEFAULT" => "你无法删除角色{{name}} 因为这是新注册用户的默认角色.", - "DELETE_YES" => "是, 删除角色", - "DELETION_SUCCESSFUL" => "成功删除角色 {{name}}", - "EDIT" => "编辑角色", - "HAS_USERS" => "你不能这样做,因为还有用户拥有角色 {{name}}.", - "INFO_PAGE" => "{{name}}角色的权限页", - "MANAGE" => "管理角色", - "NAME" => "名字", - "NAME_EXPLAIN" => "请为角色输入名字", - "NAME_IN_USE" => "角色名 {{name}} 以存在", - "PAGE_DESCRIPTION" => "网站的角色列表. 请管理编辑和删除角色的工具.", - "PERMISSIONS_UPDATED" => "角色 {{name}} 的权限更新成功", - "SUMMARY" => "角色概要", - "UPDATED" => "角色 {{name}} 更新成功" + 'ROLE' => [ + 1 => '角色', + 2 => '角色', + + 'ASSIGN_NEW' => '分配角色', + 'CREATE' => '创建角色', + 'CREATION_SUCCESSFUL' => '成功创建角色 {{name}}', + 'DELETE' => '删除角色', + 'DELETE_CONFIRM' => '你确定要删除角色 {{name}}?', + 'DELETE_DEFAULT' => '你无法删除角色{{name}} 因为这是新注册用户的默认角色.', + 'DELETE_YES' => '是, 删除角色', + 'DELETION_SUCCESSFUL' => '成功删除角色 {{name}}', + 'EDIT' => '编辑角色', + 'HAS_USERS' => '你不能这样做,因为还有用户拥有角色 {{name}}.', + 'INFO_PAGE' => '{{name}}角色的权限页', + 'MANAGE' => '管理角色', + 'NAME' => '名字', + 'NAME_EXPLAIN' => '请为角色输入名字', + 'NAME_IN_USE' => '角色名 {{name}} 以存在', + 'PAGE_DESCRIPTION' => '网站的角色列表. 请管理编辑和删除角色的工具.', + 'PERMISSIONS_UPDATED' => '角色 {{name}} 的权限更新成功', + 'SUMMARY' => '角色概要', + 'UPDATED' => '角色 {{name}} 更新成功' ], - "SYSTEM_INFO" => [ - "@TRANSLATION" => "系统信息", - - "DB_NAME" => "数据库", - "DB_VERSION" => "数据库版本", - "DIRECTORY" => "工程目录", - "PHP_VERSION" => "PHP 版本", - "SERVER" => "网站服务器", - "SPRINKLES" => "加载的 sprinkles", - "UF_VERSION" => "UserFrosting 版本", - "URL" => "网站根目录" + 'SYSTEM_INFO' => [ + '@TRANSLATION' => '系统信息', + + 'DB_NAME' => '数据库', + 'DB_VERSION' => '数据库版本', + 'DIRECTORY' => '工程目录', + 'PHP_VERSION' => 'PHP 版本', + 'SERVER' => '网站服务器', + 'SPRINKLES' => '加载的 sprinkles', + 'UF_VERSION' => 'UserFrosting 版本', + 'URL' => '网站根目录' ], - "TOGGLE_COLUMNS" => "加载列", + 'TOGGLE_COLUMNS' => '加载列', - "USER" => [ - 1 => "用户", - 2 => "用户", + 'USER' => [ + 1 => '用户', + 2 => '用户', - "ADMIN" => [ - "CHANGE_PASSWORD" => "修改用户密码", - "SEND_PASSWORD_LINK" => "发送允许该用户修改密码的链接", - "SET_PASSWORD" => "设置用户的密码为" + 'ADMIN' => [ + 'CHANGE_PASSWORD' => '修改用户密码', + 'SEND_PASSWORD_LINK' => '发送允许该用户修改密码的链接', + 'SET_PASSWORD' => '设置用户的密码为' ], - "ACTIVATE" => "激活用户", - "CREATE" => "新建用户", - "CREATED" => "用户 {{user_name}} 新建成功", - "DELETE" => "删除用户", - "DELETE_CONFIRM" => "确定要删除用户 {{name}}?", - "DELETE_YES" => "是, 删除用户", - "DISABLE" => "禁用用户", - "EDIT" => "编辑用户", - "ENABLE" => "启用用户", - "INFO_PAGE" => "用户 {{name}} 的信息页", - "LATEST" => "最新用户", - "PAGE_DESCRIPTION" => "网站用户列表. 提供编辑用户信息, 手动激活用户, 启用/禁用 用户等工具.", - "SUMMARY" => "账户概要", - "VIEW_ALL" => "浏览所有用户", - "WITH_PERMISSION" => "有此权限的用户" + 'ACTIVATE' => '激活用户', + 'CREATE' => '新建用户', + 'CREATED' => '用户 {{user_name}} 新建成功', + 'DELETE' => '删除用户', + 'DELETE_CONFIRM' => '确定要删除用户 {{name}}?', + 'DELETE_YES' => '是, 删除用户', + 'DISABLE' => '禁用用户', + 'EDIT' => '编辑用户', + 'ENABLE' => '启用用户', + 'INFO_PAGE' => '用户 {{name}} 的信息页', + 'LATEST' => '最新用户', + 'PAGE_DESCRIPTION' => '网站用户列表. 提供编辑用户信息, 手动激活用户, 启用/禁用 用户等工具.', + 'SUMMARY' => '账户概要', + 'VIEW_ALL' => '浏览所有用户', + 'WITH_PERMISSION' => '有此权限的用户' ], - "X_USER" => [ - 0 => "没有用户", - 1 => "{{plural}} 用户", - 2 => "{{plural}} 用户" + 'X_USER' => [ + 0 => '没有用户', + 1 => '{{plural}} 用户', + 2 => '{{plural}} 用户' ] ]; diff --git a/app/sprinkles/admin/src/Admin.php b/app/sprinkles/admin/src/Admin.php index 7f7a5a97c..5547cc91f 100644 --- a/app/sprinkles/admin/src/Admin.php +++ b/app/sprinkles/admin/src/Admin.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin; use UserFrosting\System\Sprinkle\Sprinkle; diff --git a/app/sprinkles/admin/src/Controller/ActivityController.php b/app/sprinkles/admin/src/Controller/ActivityController.php index 5e4d573d1..f8c5e4122 100644 --- a/app/sprinkles/admin/src/Controller/ActivityController.php +++ b/app/sprinkles/admin/src/Controller/ActivityController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Controller; use Psr\Http\Message\ResponseInterface as Response; @@ -25,9 +26,9 @@ class ActivityController extends SimpleController * Generates a list of activities, optionally paginated, sorted and/or filtered. * This page requires authentication. * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function getList(Request $request, Response $response, $args) { @@ -64,9 +65,9 @@ public function getList(Request $request, Response $response, $args) * This page renders a table of user activities. * This page requires authentication. * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageList(Request $request, Response $response, $args) { diff --git a/app/sprinkles/admin/src/Controller/AdminController.php b/app/sprinkles/admin/src/Controller/AdminController.php index 08b00e8c2..75a01b319 100644 --- a/app/sprinkles/admin/src/Controller/AdminController.php +++ b/app/sprinkles/admin/src/Controller/AdminController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Controller; use Carbon\Carbon; @@ -25,9 +26,9 @@ class AdminController extends SimpleController { /** * Renders the admin panel dashboard - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageDashboard(Request $request, Response $response, $args) { @@ -53,6 +54,7 @@ public function pageDashboard(Request $request, Response $response, $args) // Transform the `create_at` date in "x days ago" type of string $users->transform(function ($item, $key) { $item->registered = Carbon::parse($item->created_at)->diffForHumans(); + return $item; }); @@ -67,26 +69,26 @@ public function pageDashboard(Request $request, Response $response, $args) return $this->ci->view->render($response, 'pages/dashboard.html.twig', [ 'counter' => [ - 'users' => $classMapper->staticMethod('user', 'count'), - 'roles' => $classMapper->staticMethod('role', 'count'), + 'users' => $classMapper->staticMethod('user', 'count'), + 'roles' => $classMapper->staticMethod('role', 'count'), 'groups' => $classMapper->staticMethod('group', 'count') ], 'info' => [ 'version' => [ - 'UF' => \UserFrosting\VERSION, - 'php' => phpversion(), + 'UF' => \UserFrosting\VERSION, + 'php' => phpversion(), 'database' => EnvironmentInfo::database() ], 'database' => [ 'name' => $config['db.default.database'] ], 'environment' => $this->ci->environment, - 'path' => [ + 'path' => [ 'project' => \UserFrosting\ROOT_DIR ] ], 'sprinkles' => $sprinkles, - 'users' => $users + 'users' => $users ]); } @@ -95,9 +97,9 @@ public function pageDashboard(Request $request, Response $response, $args) * * This route requires authentication. * Request type: POST - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function clearCache(Request $request, Response $response, $args) { @@ -129,9 +131,9 @@ public function clearCache(Request $request, Response $response, $args) * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function getModalConfirmClearCache(Request $request, Response $response, $args) { diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index 01482a498..c79428988 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Controller; use Illuminate\Database\Capsule\Manager as Capsule; @@ -38,10 +39,10 @@ class GroupController extends SimpleController * * Request type: POST * @see getModalCreateGroup + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function create(Request $request, Response $response, $args) { @@ -110,7 +111,7 @@ public function create(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} created group {$group->name}.", [ - 'type' => 'group_create', + 'type' => 'group_create', 'user_id' => $currentUser->id ]); @@ -132,12 +133,12 @@ public function create(Request $request, Response $response, $args) * This route requires authentication (and should generally be limited to admins or the root user). * * Request type: DELETE - * @throws NotFoundException If group is not found - * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If group is not found + * @throws ForbiddenException If user is not authozied to access page * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function delete(Request $request, Response $response, $args) { @@ -192,7 +193,7 @@ public function delete(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted group {$groupName}.", [ - 'type' => 'group_delete', + 'type' => 'group_delete', 'user_id' => $currentUser->id ]); }); @@ -213,11 +214,11 @@ public function delete(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @throws NotFoundException If group is not found - * @param Request $request - * @param Response $response - * @param array $args + * @throws NotFoundException If group is not found */ public function getInfo(Request $request, Response $response, $args) { @@ -259,10 +260,10 @@ public function getInfo(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getList(Request $request, Response $response, $args) { @@ -293,12 +294,12 @@ public function getList(Request $request, Response $response, $args) /** * Get deletetion confirmation modal * - * @throws NotFoundException If group is not found - * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If group is not found + * @throws ForbiddenException If user is not authozied to access page * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalConfirmDelete(Request $request, Response $response, $args) { @@ -338,7 +339,7 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg return $this->ci->view->render($response, 'modals/confirm-delete-group.html.twig', [ 'group' => $group, - 'form' => [ + 'form' => [ 'action' => "api/groups/g/{$group->slug}", ] ]); @@ -351,10 +352,10 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalCreate(Request $request, Response $response, $args) { @@ -385,7 +386,7 @@ public function getModalCreate(Request $request, Response $response, $args) $fieldNames = ['name', 'slug', 'icon', 'description']; $fields = [ - 'hidden' => [], + 'hidden' => [], 'disabled' => [] ]; @@ -395,10 +396,10 @@ public function getModalCreate(Request $request, Response $response, $args) return $this->ci->view->render($response, 'modals/group.html.twig', [ 'group' => $group, - 'form' => [ - 'action' => 'api/groups', - 'method' => 'POST', - 'fields' => $fields, + 'form' => [ + 'action' => 'api/groups', + 'method' => 'POST', + 'fields' => $fields, 'submit_text' => $translator->translate('CREATE') ], 'page' => [ @@ -414,11 +415,11 @@ public function getModalCreate(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET - * @throws NotFoundException If group is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If group is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalEdit(Request $request, Response $response, $args) { @@ -455,7 +456,7 @@ public function getModalEdit(Request $request, Response $response, $args) // Generate form $fields = [ - 'hidden' => [], + 'hidden' => [], 'disabled' => [] ]; @@ -465,10 +466,10 @@ public function getModalEdit(Request $request, Response $response, $args) return $this->ci->view->render($response, 'modals/group.html.twig', [ 'group' => $group, - 'form' => [ - 'action' => "api/groups/g/{$group->slug}", - 'method' => 'PUT', - 'fields' => $fields, + 'form' => [ + 'action' => "api/groups/g/{$group->slug}", + 'method' => 'PUT', + 'fields' => $fields, 'submit_text' => $translator->translate('UPDATE') ], 'page' => [ @@ -480,11 +481,11 @@ public function getModalEdit(Request $request, Response $response, $args) /** * Users List API * - * @throws NotFoundException If group is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If group is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getUsers(Request $request, Response $response, $args) { @@ -534,10 +535,10 @@ public function getUsers(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function pageInfo(Request $request, Response $response, $args) { @@ -546,6 +547,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the group no longer exists, forward to main group listing page if (!$group) { $redirectPage = $this->ci->router->pathFor('uri_groups'); + return $response->withRedirect($redirectPage); } @@ -598,9 +600,9 @@ public function pageInfo(Request $request, Response $response, $args) } return $this->ci->view->render($response, 'pages/group.html.twig', [ - 'group' => $group, + 'group' => $group, 'fields' => $fields, - 'tools' => $editButtons + 'tools' => $editButtons ]); } @@ -612,10 +614,10 @@ public function pageInfo(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function pageList(Request $request, Response $response, $args) { @@ -644,11 +646,11 @@ public function pageList(Request $request, Response $response, $args) * * Request type: PUT * @see getModalGroupEdit - * @throws NotFoundException If group is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If group is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function updateInfo(Request $request, Response $response, $args) { @@ -743,7 +745,7 @@ public function updateInfo(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated details for group {$group->name}.", [ - 'type' => 'group_update_info', + 'type' => 'group_update_info', 'user_id' => $currentUser->id ]); }); @@ -758,8 +760,8 @@ public function updateInfo(Request $request, Response $response, $args) /** * Get group from params * + * @param array $params * @throws BadRequestException - * @param array $params * @return Group */ protected function getGroupFromParams($params) diff --git a/app/sprinkles/admin/src/Controller/PermissionController.php b/app/sprinkles/admin/src/Controller/PermissionController.php index 0b9490463..670bfe7a0 100644 --- a/app/sprinkles/admin/src/Controller/PermissionController.php +++ b/app/sprinkles/admin/src/Controller/PermissionController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Controller; use Psr\Http\Message\ResponseInterface as Response; @@ -26,11 +27,11 @@ class PermissionController extends SimpleController * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @throws NotFoundException If permission is not found - * @param Request $request - * @param Response $response - * @param array $args + * @throws NotFoundException If permission is not found */ public function getInfo(Request $request, Response $response, $args) { @@ -72,10 +73,10 @@ public function getInfo(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getList(Request $request, Response $response, $args) { @@ -110,10 +111,10 @@ public function getList(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getUsers(Request $request, Response $response, $args) { @@ -154,11 +155,11 @@ public function getUsers(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @throws NotFoundException If permission is not found - * @param Request $request - * @param Response $response - * @param array $args + * @throws NotFoundException If permission is not found */ public function pageInfo(Request $request, Response $response, $args) { @@ -198,10 +199,10 @@ public function pageInfo(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function pageList(Request $request, Response $response, $args) { diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index fe9c6994a..4d140b9b5 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Controller; use Illuminate\Database\Capsule\Manager as Capsule; @@ -38,10 +39,10 @@ class RoleController extends SimpleController * * Request type: POST * @see getModalCreateRole + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function create(Request $request, Response $response, $args) { @@ -110,7 +111,7 @@ public function create(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} created role {$role->name}.", [ - 'type' => 'role_create', + 'type' => 'role_create', 'user_id' => $currentUser->id ]); @@ -132,12 +133,12 @@ public function create(Request $request, Response $response, $args) * This route requires authentication (and should generally be limited to admins or the root user). * * Request type: DELETE - * @throws NotFoundException If role is not found - * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function delete(Request $request, Response $response, $args) { @@ -191,7 +192,7 @@ public function delete(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted role {$roleName}.", [ - 'type' => 'role_delete', + 'type' => 'role_delete', 'user_id' => $currentUser->id ]); }); @@ -212,11 +213,11 @@ public function delete(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @throws NotFoundException If role is not found - * @param Request $request - * @param Response $response - * @param array $args + * @throws NotFoundException If role is not found */ public function getInfo(Request $request, Response $response, $args) { @@ -258,10 +259,10 @@ public function getInfo(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getList(Request $request, Response $response, $args) { @@ -292,12 +293,12 @@ public function getList(Request $request, Response $response, $args) /** * Display deletion confirmation modal * - * @throws NotFoundException If role is not found - * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalConfirmDelete(Request $request, Response $response, $args) { @@ -360,10 +361,10 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalCreate(Request $request, Response $response, $args) { @@ -392,7 +393,7 @@ public function getModalCreate(Request $request, Response $response, $args) $fieldNames = ['name', 'slug', 'description']; $fields = [ - 'hidden' => [], + 'hidden' => [], 'disabled' => [] ]; @@ -403,9 +404,9 @@ public function getModalCreate(Request $request, Response $response, $args) return $this->ci->view->render($response, 'modals/role.html.twig', [ 'role' => $role, 'form' => [ - 'action' => 'api/roles', - 'method' => 'POST', - 'fields' => $fields, + 'action' => 'api/roles', + 'method' => 'POST', + 'fields' => $fields, 'submit_text' => $translator->translate('CREATE') ], 'page' => [ @@ -421,11 +422,11 @@ public function getModalCreate(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET - * @throws NotFoundException If role is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If role is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalEdit(Request $request, Response $response, $args) { @@ -462,7 +463,7 @@ public function getModalEdit(Request $request, Response $response, $args) // Generate form $fields = [ - 'hidden' => [], + 'hidden' => [], 'disabled' => [] ]; @@ -473,9 +474,9 @@ public function getModalEdit(Request $request, Response $response, $args) return $this->ci->view->render($response, 'modals/role.html.twig', [ 'role' => $role, 'form' => [ - 'action' => "api/roles/r/{$role->slug}", - 'method' => 'PUT', - 'fields' => $fields, + 'action' => "api/roles/r/{$role->slug}", + 'method' => 'PUT', + 'fields' => $fields, 'submit_text' => $translator->translate('UPDATE') ], 'page' => [ @@ -491,11 +492,11 @@ public function getModalEdit(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET - * @throws NotFoundException If role is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If role is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalEditPermissions(Request $request, Response $response, $args) { @@ -535,11 +536,11 @@ public function getModalEditPermissions(Request $request, Response $response, $a * This page requires authentication. * * Request type: GET - * @throws NotFoundException If role is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If role is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getPermissions(Request $request, Response $response, $args) { @@ -586,11 +587,11 @@ public function getPermissions(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET - * @throws NotFoundException If role is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If role is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getUsers(Request $request, Response $response, $args) { @@ -640,10 +641,10 @@ public function getUsers(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function pageInfo(Request $request, Response $response, $args) { @@ -652,6 +653,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the role no longer exists, forward to main role listing page if (!$role) { $redirectPage = $this->ci->router->pathFor('uri_roles'); + return $response->withRedirect($redirectPage); } @@ -704,9 +706,9 @@ public function pageInfo(Request $request, Response $response, $args) } return $this->ci->view->render($response, 'pages/role.html.twig', [ - 'role' => $role, + 'role' => $role, 'fields' => $fields, - 'tools' => $editButtons + 'tools' => $editButtons ]); } @@ -718,10 +720,10 @@ public function pageInfo(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function pageList(Request $request, Response $response, $args) { @@ -750,11 +752,11 @@ public function pageList(Request $request, Response $response, $args) * * Request type: PUT * @see getModalRoleEdit - * @throws NotFoundException If role is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If role is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function updateInfo(Request $request, Response $response, $args) { @@ -849,7 +851,7 @@ public function updateInfo(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated details for role {$role->name}.", [ - 'type' => 'role_update_info', + 'type' => 'role_update_info', 'user_id' => $currentUser->id ]); }); @@ -870,12 +872,12 @@ public function updateInfo(Request $request, Response $response, $args) * This route requires authentication. * * Request type: PUT - * @throws NotFoundException If role is not found - * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If role is not found + * @throws ForbiddenException If user is not authozied to access page * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function updateField(Request $request, Response $response, $args) { @@ -957,7 +959,7 @@ public function updateField(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated property '$fieldName' for role {$role->name}.", [ - 'type' => 'role_update_field', + 'type' => 'role_update_field', 'user_id' => $currentUser->id ]); }); @@ -979,8 +981,8 @@ public function updateField(Request $request, Response $response, $args) /** * Get role instance from params * + * @param array $params * @throws BadRequestException - * @param array $params * @return Role */ protected function getRoleFromParams($params) diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index fd1e32757..3e11146cd 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Controller; use Carbon\Carbon; @@ -42,10 +43,10 @@ class UserController extends SimpleController * * Request type: POST * @see getModalCreate + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function create(Request $request, Response $response, $args) { @@ -133,7 +134,7 @@ public function create(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} created a new account for {$user->user_name}.", [ - 'type' => 'account_create', + 'type' => 'account_create', 'user_id' => $currentUser->id ]); @@ -154,9 +155,9 @@ public function create(Request $request, Response $response, $args) $message->from($config['address_book.admin']) ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) ->addParams([ - 'user' => $user, + 'user' => $user, 'create_password_expiration' => $config['password_reset.timeouts.create'] / 3600 . ' hours', - 'token' => $passwordRequest->getToken() + 'token' => $passwordRequest->getToken() ]); $this->ci->mailer->send($message); @@ -178,11 +179,11 @@ public function create(Request $request, Response $response, $args) * This route requires authentication. * * Request type: POST - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function createPasswordReset(Request $request, Response $response, $args) { @@ -225,8 +226,8 @@ public function createPasswordReset(Request $request, Response $response, $args) $message->from($config['address_book.admin']) ->addEmailRecipient(new EmailRecipient($user->email, $user->full_name)) ->addParams([ - 'user' => $user, - 'token' => $passwordReset->getToken(), + 'user' => $user, + 'token' => $passwordReset->getToken(), 'request_date' => Carbon::now()->format('Y-m-d H:i:s') ]); @@ -236,6 +237,7 @@ public function createPasswordReset(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'PASSWORD.FORGET.REQUEST_SENT', [ 'email' => $user->email ]); + return $response->withJson([], 200); } @@ -249,12 +251,12 @@ public function createPasswordReset(Request $request, Response $response, $args) * This route requires authentication (and should generally be limited to admins or the root user). * * Request type: DELETE - * @throws NotFoundException If user is not found - * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function delete(Request $request, Response $response, $args) { @@ -298,7 +300,7 @@ public function delete(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} deleted the account for {$userName}.", [ - 'type' => 'account_delete', + 'type' => 'account_delete', 'user_id' => $currentUser->id ]); }); @@ -318,11 +320,11 @@ public function delete(Request $request, Response $response, $args) * * This page requires authentication. * Request type: GET - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getActivities(Request $request, Response $response, $args) { @@ -369,11 +371,11 @@ public function getActivities(Request $request, Response $response, $args) * * This page requires authentication. * Request type: GET - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getInfo(Request $request, Response $response, $args) { @@ -420,10 +422,10 @@ public function getInfo(Request $request, Response $response, $args) * Generates a list of users, optionally paginated, sorted and/or filtered. * This page requires authentication. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getList(Request $request, Response $response, $args) { @@ -457,12 +459,12 @@ public function getList(Request $request, Response $response, $args) * This does NOT render a complete page. Instead, it renders the HTML for the modal, which can be embedded in other pages. * This page requires authentication. * Request type: GET - * @throws NotFoundException If user is not found - * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalConfirmDelete(Request $request, Response $response, $args) { @@ -517,10 +519,10 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg * * This page requires authentication. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalCreate(Request $request, Response $response, $args) { @@ -550,7 +552,7 @@ public function getModalCreate(Request $request, Response $response, $args) // Determine form fields to hide/disable // TODO: come back to this when we finish implementing theming $fields = [ - 'hidden' => ['theme'], + 'hidden' => ['theme'], 'disabled' => [] ]; @@ -584,13 +586,13 @@ public function getModalCreate(Request $request, Response $response, $args) $validator = new JqueryValidationAdapter($schema, $this->ci->translator); return $this->ci->view->render($response, 'modals/user.html.twig', [ - 'user' => $user, - 'groups' => $groups, + 'user' => $user, + 'groups' => $groups, 'locales' => $locales, - 'form' => [ - 'action' => 'api/users', - 'method' => 'POST', - 'fields' => $fields, + 'form' => [ + 'action' => 'api/users', + 'method' => 'POST', + 'fields' => $fields, 'submit_text' => $translator->translate('CREATE') ], 'page' => [ @@ -606,11 +608,11 @@ public function getModalCreate(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalEdit(Request $request, Response $response, $args) { @@ -658,7 +660,7 @@ public function getModalEdit(Request $request, Response $response, $args) // Generate form $fields = [ - 'hidden' => ['theme'], + 'hidden' => ['theme'], 'disabled' => ['user_name'] ]; @@ -677,13 +679,13 @@ public function getModalEdit(Request $request, Response $response, $args) $translator = $this->ci->translator; return $this->ci->view->render($response, 'modals/user.html.twig', [ - 'user' => $user, - 'groups' => $groups, + 'user' => $user, + 'groups' => $groups, 'locales' => $locales, - 'form' => [ - 'action' => "api/users/u/{$user->user_name}", - 'method' => 'PUT', - 'fields' => $fields, + 'form' => [ + 'action' => "api/users/u/{$user->user_name}", + 'method' => 'PUT', + 'fields' => $fields, 'submit_text' => $translator->translate('UPDATE') ], 'page' => [ @@ -699,11 +701,11 @@ public function getModalEdit(Request $request, Response $response, $args) * This page requires authentication. * * Request type: GET - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalEditPassword(Request $request, Response $response, $args) { @@ -750,11 +752,11 @@ public function getModalEditPassword(Request $request, Response $response, $args * This page requires authentication. * * Request type: GET - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getModalEditRoles(Request $request, Response $response, $args) { @@ -793,11 +795,11 @@ public function getModalEditRoles(Request $request, Response $response, $args) * Generates a list of permissions, optionally paginated, sorted and/or filtered. * This page requires authentication. * Request type: GET - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getPermissions(Request $request, Response $response, $args) { @@ -843,11 +845,11 @@ public function getPermissions(Request $request, Response $response, $args) * * This page requires authentication. * Request type: GET - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function getRoles(Request $request, Response $response, $args) { @@ -897,10 +899,10 @@ public function getRoles(Request $request, Response $response, $args) * * This page requires authentication. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function pageInfo(Request $request, Response $response, $args) { @@ -909,6 +911,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the user no longer exists, forward to main user listing page if (!$user) { $usersPage = $this->ci->router->pathFor('uri_users'); + return $response->withRedirect($usersPage); } @@ -1016,10 +1019,10 @@ public function pageInfo(Request $request, Response $response, $args) } return $this->ci->view->render($response, 'pages/user.html.twig', [ - 'user' => $user, + 'user' => $user, 'locales' => $locales, - 'fields' => $fields, - 'tools' => $editButtons, + 'fields' => $fields, + 'tools' => $editButtons, 'widgets' => $widgets ]); } @@ -1032,10 +1035,10 @@ public function pageInfo(Request $request, Response $response, $args) * * This page requires authentication. * Request type: GET + * @param Request $request + * @param Response $response + * @param array $args * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function pageList(Request $request, Response $response, $args) { @@ -1063,11 +1066,11 @@ public function pageList(Request $request, Response $response, $args) * * This route requires authentication. * Request type: PUT - * @throws NotFoundException If user is not found + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found * @throws ForbiddenException If user is not authozied to access page - * @param Request $request - * @param Response $response - * @param array $args */ public function updateInfo(Request $request, Response $response, $args) { @@ -1167,7 +1170,7 @@ public function updateInfo(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated basic account info for user {$user->user_name}.", [ - 'type' => 'account_update_info', + 'type' => 'account_update_info', 'user_id' => $currentUser->id ]); }); @@ -1175,6 +1178,7 @@ public function updateInfo(Request $request, Response $response, $args) $ms->addMessageTranslated('success', 'DETAILS_UPDATED', [ 'user_name' => $user->user_name ]); + return $response->withJson([], 200); } @@ -1189,12 +1193,12 @@ public function updateInfo(Request $request, Response $response, $args) * * This route requires authentication. * Request type: PUT - * @throws NotFoundException If user is not found - * @throws ForbiddenException If user is not authozied to access page + * @param Request $request + * @param Response $response + * @param array $args + * @throws NotFoundException If user is not found + * @throws ForbiddenException If user is not authozied to access page * @throws BadRequestException - * @param Request $request - * @param Response $response - * @param array $args */ public function updateField(Request $request, Response $response, $args) { @@ -1305,7 +1309,7 @@ public function updateField(Request $request, Response $response, $args) // Create activity record $this->ci->userActivityLogger->info("User {$currentUser->user_name} updated property '$fieldName' for user {$user->user_name}.", [ - 'type' => 'account_update_field', + 'type' => 'account_update_field', 'user_id' => $currentUser->id ]); }); @@ -1337,8 +1341,8 @@ public function updateField(Request $request, Response $response, $args) /** * Get User instance from params * + * @param array $params * @throws BadRequestException - * @param array $params * @return User */ protected function getUserFromParams($params) diff --git a/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php index 7f87c28e7..4b027032b 100644 --- a/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/admin/src/ServicesProvider/ServicesProvider.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\ServicesProvider; use Interop\Container\ContainerInterface; @@ -40,6 +41,7 @@ public function register(ContainerInterface $container) $classMapper->setClassMapping('role_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\RoleSprunje'); $classMapper->setClassMapping('user_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\UserSprunje'); $classMapper->setClassMapping('user_permission_sprunje', 'UserFrosting\Sprinkle\Admin\Sprunje\UserPermissionSprunje'); + return $classMapper; }); @@ -55,9 +57,9 @@ public function register(ContainerInterface $container) * This method is invoked when a user completes the login process. * * Returns a callback that handles setting the `UF-Redirect` header after a successful login. - * @param \Psr\Http\Message\ServerRequestInterface $request - * @param \Psr\Http\Message\ResponseInterface $response - * @param array $args + * @param \Psr\Http\Message\ServerRequestInterface $request + * @param \Psr\Http\Message\ResponseInterface $response + * @param array $args * @return \Psr\Http\Message\ResponseInterface */ return function (Request $request, Response $response, array $args) use ($c) { diff --git a/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php b/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php index 393e7ea1f..9c7e1f812 100644 --- a/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php +++ b/app/sprinkles/admin/src/Sprunje/ActivitySprunje.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Sprunje; use Illuminate\Database\Schema\Builder; @@ -46,8 +47,8 @@ protected function baseQuery() /** * Filter LIKE the user info. * - * @param Builder $query - * @param mixed $value + * @param Builder $query + * @param mixed $value * @return self */ protected function filterUser($query, $value) @@ -61,19 +62,21 @@ protected function filterUser($query, $value) ->orLike('users.email', $value); } }); + return $this; } /** * Sort based on user last name. * - * @param Builder $query - * @param string $direction + * @param Builder $query + * @param string $direction * @return self */ protected function sortUser($query, $direction) { $query->orderBy('users.last_name', $direction); + return $this; } } diff --git a/app/sprinkles/admin/src/Sprunje/GroupSprunje.php b/app/sprinkles/admin/src/Sprunje/GroupSprunje.php index ebe2aabd2..435715611 100644 --- a/app/sprinkles/admin/src/Sprunje/GroupSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/GroupSprunje.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Sprunje; use UserFrosting\Sprinkle\Core\Sprunje\Sprunje; diff --git a/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php b/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php index d828e0941..870cef411 100644 --- a/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/PermissionSprunje.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Sprunje; use Illuminate\Database\Schema\Builder; @@ -47,8 +48,8 @@ protected function baseQuery() /** * Filter LIKE the slug, conditions, or description. * - * @param Builder $query - * @param mixed $value + * @param Builder $query + * @param mixed $value * @return self */ protected function filterInfo($query, $value) @@ -59,8 +60,8 @@ protected function filterInfo($query, $value) /** * Filter LIKE the slug, conditions, or description. * - * @param Builder $query - * @param mixed $value + * @param Builder $query + * @param mixed $value * @return self */ protected function filterProperties($query, $value) @@ -74,19 +75,21 @@ protected function filterProperties($query, $value) ->orLike('description', $value); } }); + return $this; } /** * Sort based on slug. * - * @param Builder $query - * @param string $direction + * @param Builder $query + * @param string $direction * @return self */ protected function sortProperties($query, $direction) { $query->orderBy('slug', $direction); + return $this; } } diff --git a/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php b/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php index 9dc278691..a132a5fa9 100644 --- a/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Sprunje; use UserFrosting\Support\Exception\BadRequestException; @@ -35,7 +36,7 @@ protected function baseQuery() // If the permission doesn't exist, return 404 if (!$permission) { - throw new NotFoundException; + throw new NotFoundException(); } // Get permission users diff --git a/app/sprinkles/admin/src/Sprunje/RoleSprunje.php b/app/sprinkles/admin/src/Sprunje/RoleSprunje.php index a71da5c70..6769821eb 100644 --- a/app/sprinkles/admin/src/Sprunje/RoleSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/RoleSprunje.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Sprunje; use Illuminate\Database\Schema\Builder; @@ -47,8 +48,8 @@ protected function baseQuery() /** * Filter LIKE name OR description. * - * @param Builder $query - * @param mixed $value + * @param Builder $query + * @param mixed $value * @return self */ protected function filterInfo($query, $value) @@ -61,6 +62,7 @@ protected function filterInfo($query, $value) ->orLike('description', $value); } }); + return $this; } } diff --git a/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php b/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php index 1f0c8fe33..e31791d23 100644 --- a/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Sprunje; use UserFrosting\Support\Exception\BadRequestException; @@ -35,7 +36,7 @@ protected function baseQuery() // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException; + throw new NotFoundException(); } // Get user permissions diff --git a/app/sprinkles/admin/src/Sprunje/UserSprunje.php b/app/sprinkles/admin/src/Sprunje/UserSprunje.php index d525c5c0d..5ca97acbb 100644 --- a/app/sprinkles/admin/src/Sprunje/UserSprunje.php +++ b/app/sprinkles/admin/src/Sprunje/UserSprunje.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Admin\Sprunje; use Illuminate\Database\Schema\Builder; @@ -56,8 +57,8 @@ protected function baseQuery() /** * Filter LIKE the last activity description. * - * @param Builder $query - * @param mixed $value + * @param Builder $query + * @param mixed $value * @return self */ protected function filterLastActivity($query, $value) @@ -69,14 +70,15 @@ protected function filterLastActivity($query, $value) $query->orLike('activities.description', $value); } }); + return $this; } /** * Filter LIKE the first name, last name, or email. * - * @param Builder $query - * @param mixed $value + * @param Builder $query + * @param mixed $value * @return self */ protected function filterName($query, $value) @@ -90,14 +92,15 @@ protected function filterName($query, $value) ->orLike('email', $value); } }); + return $this; } /** * Filter by status (active, disabled, unactivated) * - * @param Builder $query - * @param mixed $value + * @param Builder $query + * @param mixed $value * @return self */ protected function filterStatus($query, $value) @@ -117,6 +120,7 @@ protected function filterStatus($query, $value) } } }); + return $this; } @@ -130,15 +134,15 @@ protected function listStatus() return [ [ 'value' => 'active', - 'text' => Translator::translate('ACTIVE') + 'text' => Translator::translate('ACTIVE') ], [ 'value' => 'unactivated', - 'text' => Translator::translate('UNACTIVATED') + 'text' => Translator::translate('UNACTIVATED') ], [ 'value' => 'disabled', - 'text' => Translator::translate('DISABLED') + 'text' => Translator::translate('DISABLED') ] ]; } @@ -146,39 +150,42 @@ protected function listStatus() /** * Sort based on last activity time. * - * @param Builder $query - * @param string $direction + * @param Builder $query + * @param string $direction * @return self */ protected function sortLastActivity($query, $direction) { $query->orderBy('activities.occurred_at', $direction); + return $this; } /** * Sort based on last name. * - * @param Builder $query - * @param string $direction + * @param Builder $query + * @param string $direction * @return self */ protected function sortName($query, $direction) { $query->orderBy('last_name', $direction); + return $this; } /** * Sort active, unactivated, disabled * - * @param Builder $query - * @param string $direction + * @param Builder $query + * @param string $direction * @return self */ protected function sortStatus($query, $direction) { $query->orderBy('flag_enabled', $direction)->orderBy('flag_verified', $direction); + return $this; } } diff --git a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php index 4106ea975..493c713c2 100644 --- a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php +++ b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php @@ -1,4 +1,10 @@ getController(); $this->assertInstanceOf(AdminController::class, $controller); + return $controller; } @@ -76,7 +83,7 @@ public function testClearCache() $controller = $this->getController(); // First, store something in cache - /** @var \Illuminate\Cache\Repository $cache **/ + /** @var \Illuminate\Cache\Repository $cache */ $cache = $this->ci->cache; $value = rand(1, 100); $cache->put('foo', $value, 20); @@ -94,7 +101,7 @@ public function testClearCache() /** @var \UserFrosting\Sprinkle\Core\Alert\AlertStream $ms */ $ms = $this->ci->alerts; $messages = $ms->getAndClearMessages(); - $expectedMessage = end($messages)["message"]; + $expectedMessage = end($messages)['message']; $actualMessage = $this->ci->translator->translate('CACHE.CLEARED'); $this->assertSame($expectedMessage, $actualMessage); diff --git a/app/sprinkles/admin/tests/Integration/SprunjeTests.php b/app/sprinkles/admin/tests/Integration/SprunjeTests.php index 6cef7e2b6..9be401045 100644 --- a/app/sprinkles/admin/tests/Integration/SprunjeTests.php +++ b/app/sprinkles/admin/tests/Integration/SprunjeTests.php @@ -1,4 +1,10 @@ [ - 'use_raw' => true - ], - 'cache' => [ - 'twig' => false - ], +/* + * Debug development config file for UserFrosting. Sets every debug options on to help debug what's going wrong + */ +return [ + 'assets' => [ + 'use_raw' => true + ], + 'cache' => [ + 'twig' => false + ], + 'debug' => [ + 'deprecation' => true, + 'queries' => true, + 'smtp' => true, + 'twig' => true + ], + 'settings' => [ + 'displayErrorDetails' => true + ], + 'site' => [ 'debug' => [ - 'deprecation' => true, - 'queries' => true, - 'smtp' => true, - 'twig' => true - ], - 'settings' => [ - 'displayErrorDetails' => true - ], - 'site' => [ - 'debug' => [ - 'ajax' => true, - 'info' => true - ] + 'ajax' => true, + 'info' => true ] - ]; + ] +]; diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 5c42067ec..256c6d5ef 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -1,15 +1,20 @@ 'site.alerts', // the key to use to store flash messages ], - /** + /* * ---------------------------------------------------------------------- * Assets Service Config * ---------------------------------------------------------------------- @@ -54,7 +59,7 @@ 'use_raw' => true ], - /** + /* * ---------------------------------------------------------------------- * Cache Service Config * ---------------------------------------------------------------------- @@ -66,8 +71,8 @@ */ 'cache' => [ 'driver' => 'file', // Supported drivers : `file`, `memcached`, `redis` - 'prefix' => 'userfrosting', - 'memcached' => [ + 'prefix' => 'userfrosting', + 'memcached' => [ 'host' => '127.0.0.1', 'port' => 11211, 'weight' => 100 @@ -82,7 +87,7 @@ 'twig' => false ], - /** + /* * ---------------------------------------------------------------------- * CSRF middleware settings * ---------------------------------------------------------------------- @@ -105,7 +110,7 @@ ] ], - /** + /* * ---------------------------------------------------------------------- * Database Config * ---------------------------------------------------------------------- @@ -115,7 +120,7 @@ * Multiple connections can also be used. * See Laravel docs : https://laravel.com/docs/5.4/database */ - 'db' => [ + 'db' => [ 'default' => [ 'driver' => getenv('DB_DRIVER') ?: 'mysql', 'host' => getenv('DB_HOST') ?: null, @@ -129,7 +134,7 @@ ] ], - /** + /* * ---------------------------------------------------------------------- * Debug Configuration * ---------------------------------------------------------------------- @@ -142,7 +147,7 @@ 'twig' => false ], - /** + /* * ---------------------------------------------------------------------- * Filesystem Configuration * ---------------------------------------------------------------------- @@ -154,10 +159,10 @@ */ 'filesystems' => [ 'default' => getenv('FILESYSTEM_DRIVER') ?: 'local', - 'cloud' => getenv('FILESYSTEM_CLOUD') ?: 's3', + 'cloud' => getenv('FILESYSTEM_CLOUD') ?: 's3', 'disks' => [ - /** + /* * Default storage disk. Default path is `app/storage/`. All * files are accessible throught the FilesystemManager, but not * publicly accessible throught an URL. Can still be downloaded @@ -165,9 +170,9 @@ */ 'local' => [ 'driver' => 'local', - 'root' => \UserFrosting\STORAGE_DIR + 'root' => \UserFrosting\STORAGE_DIR ], - /** + /* * Public files are directly accessible throught the webserver for * better performances, but at the expanse of all files being public. * Direct access from http://{url}/files/, physically located in `/public/files` @@ -175,39 +180,39 @@ */ 'public' => [ 'driver' => 'local', - 'root' => \UserFrosting\STORAGE_PUBLIC_DIR, - 'url' => 'files/' + 'root' => \UserFrosting\STORAGE_PUBLIC_DIR, + 'url' => 'files/' ], - /** + /* * Amazon S3 Bucket Config. Config should go in .env file. For help, see : * https://aws.amazon.com/en/blogs/security/wheres-my-secret-access-key/ */ 's3' => [ 'driver' => 's3', - 'key' => getenv('AWS_ACCESS_KEY_ID') ?: '', + 'key' => getenv('AWS_ACCESS_KEY_ID') ?: '', 'secret' => getenv('AWS_SECRET_ACCESS_KEY') ?: '', 'region' => getenv('AWS_DEFAULT_REGION') ?: '', // See : http://docs.aws.amazon.com/general/latest/gr/rande.html 'bucket' => getenv('AWS_BUCKET') ?: '', - 'url' => getenv('AWS_URL') ?: '', + 'url' => getenv('AWS_URL') ?: '', ], ], ], - /** + /* * ---------------------------------------------------------------------- * Mail Service Config * ---------------------------------------------------------------------- * See https://learn.userfrosting.com/mail/the-mailer-service */ 'mail' => [ - 'mailer' => 'smtp', // Set to one of 'smtp', 'mail', 'qmail', 'sendmail' - 'host' => getenv('SMTP_HOST') ?: null, - 'port' => 587, - 'auth' => true, - 'secure' => 'tls', - 'username' => getenv('SMTP_USER') ?: null, - 'password' => getenv('SMTP_PASSWORD') ?: null, - 'smtp_debug' => 4, + 'mailer' => 'smtp', // Set to one of 'smtp', 'mail', 'qmail', 'sendmail' + 'host' => getenv('SMTP_HOST') ?: null, + 'port' => 587, + 'auth' => true, + 'secure' => 'tls', + 'username' => getenv('SMTP_USER') ?: null, + 'password' => getenv('SMTP_PASSWORD') ?: null, + 'smtp_debug' => 4, 'message_options' => [ 'CharSet' => 'UTF-8', 'isHtml' => true, @@ -215,7 +220,7 @@ ] ], - /** + /* * ---------------------------------------------------------------------- * Migration Service Config * ---------------------------------------------------------------------- @@ -225,7 +230,7 @@ 'repository_table' => 'migrations' ], - /** + /* * ---------------------------------------------------------------------- * Filesystem paths * ---------------------------------------------------------------------- @@ -235,7 +240,7 @@ 'public_relative' => dirname($_SERVER['SCRIPT_NAME']) // The location of `index.php` relative to the document root. Use for sites installed in subdirectories of your web server's document root. ], - /** + /* * ---------------------------------------------------------------------- * Session Config * ---------------------------------------------------------------------- @@ -257,7 +262,7 @@ ] ], - /** + /* * ---------------------------------------------------------------------- * Slim settings * ---------------------------------------------------------------------- @@ -268,7 +273,7 @@ 'displayErrorDetails' => true ], - /** + /* * ---------------------------------------------------------------------- * Site Settings * ---------------------------------------------------------------------- @@ -276,23 +281,23 @@ */ 'site' => [ // AdminLTE Settings - 'AdminLTE' => [ + 'AdminLTE' => [ 'skin' => 'blue' ], // Google Analytics Settings 'analytics' => [ 'google' => [ - 'code' => '', + 'code' => '', 'enabled' => false ] ], - 'author' => 'Author', // Site author + 'author' => 'Author', // Site author 'csrf' => null, // Do not set this variable. The core Twig extension will override it with values from the CSRF service. 'debug' => [ 'ajax' => false, 'info' => true ], - 'locales' => [ + 'locales' => [ // Should be ordered according to https://en.wikipedia.org/wiki/List_of_languages_by_total_number_of_speakers, // with the exception of English, which as the default language comes first. 'available' => [ @@ -335,7 +340,7 @@ ] ], - /** + /* * ---------------------------------------------------------------------- * PHP global settings * ---------------------------------------------------------------------- diff --git a/app/sprinkles/core/config/production.php b/app/sprinkles/core/config/production.php index 93cc5611d..70bed3686 100644 --- a/app/sprinkles/core/config/production.php +++ b/app/sprinkles/core/config/production.php @@ -1,56 +1,61 @@ [ - 'use_raw' => false - ], - /** - * Enable Twig cache - */ - 'cache' => [ - 'twig' => true - ], - /** - * Turn off debug logs - */ - 'debug' => [ - 'twig' => false, - 'auth' => false, - 'smtp' => false - ], - /** - * Use router cache, disable full error details - */ - 'settings' => [ - 'routerCacheFile' => \UserFrosting\ROOT_DIR . '/' . \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\CACHE_DIR_NAME . '/' . 'routes.cache', - 'displayErrorDetails' => false - ], - /** - * Enable analytics, disable more debugging - */ - 'site' => [ - 'analytics' => [ - 'google' => [ - 'enabled' => true - ] - ], - 'debug' => [ - 'ajax' => false, - 'info' => false + 'assets' => [ + 'use_raw' => false + ], + /* + * Enable Twig cache + */ + 'cache' => [ + 'twig' => true + ], + /* + * Turn off debug logs + */ + 'debug' => [ + 'twig' => false, + 'auth' => false, + 'smtp' => false + ], + /* + * Use router cache, disable full error details + */ + 'settings' => [ + 'routerCacheFile' => \UserFrosting\ROOT_DIR . '/' . \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\CACHE_DIR_NAME . '/' . 'routes.cache', + 'displayErrorDetails' => false + ], + /* + * Enable analytics, disable more debugging + */ + 'site' => [ + 'analytics' => [ + 'google' => [ + 'enabled' => true ] ], - /** - * Send errors to log - */ - 'php' => [ - 'display_errors' => 'false', - 'log_errors' => 'true' + 'debug' => [ + 'ajax' => false, + 'info' => false ] - ]; + ], + /* + * Send errors to log + */ + 'php' => [ + 'display_errors' => 'false', + 'log_errors' => 'true' + ] +]; diff --git a/app/sprinkles/core/config/testing.php b/app/sprinkles/core/config/testing.php index 9606cf2ab..8634daf9e 100755 --- a/app/sprinkles/core/config/testing.php +++ b/app/sprinkles/core/config/testing.php @@ -1,65 +1,70 @@ [ - 'illuminate' => [ - 'default' => 'array', - ] - ], - /** - * Define in memory db for testing - */ - 'db' => [ - 'test_integration' => [ - 'driver' => 'sqlite', - 'database' => ':memory:', - ] - ], - /** - * Don't log deprecations in tests - */ - 'debug' => [ - 'deprecation' => false, - ], - /** - * Use testning filesystem for tests - */ - 'filesystems' => [ - 'disks' => [ - 'testing' => [ - 'driver' => 'local', - 'root' => \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testing', - 'url' => 'files/testing/', - ], - 'testingDriver' => [ - 'driver' => 'localTest', - 'root' => \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testingDriver' - ], - ] - ], - /** - * Don't display error detail in test. Return the non formatted errors - */ - 'settings' => [ - 'displayErrorDetails' => false - ], - /** - * Disable native sessions in tests - */ - 'session' => [ - 'handler' => 'array' - ], - /** - * Database to use when using the TestDatabase Trait - */ - 'testing' => [ - 'dbConnection' => getenv('TEST_DB') ?: 'test_integration' + 'cache' => [ + 'illuminate' => [ + 'default' => 'array', + ] + ], + /* + * Define in memory db for testing + */ + 'db' => [ + 'test_integration' => [ + 'driver' => 'sqlite', + 'database' => ':memory:', ] - ]; + ], + /* + * Don't log deprecations in tests + */ + 'debug' => [ + 'deprecation' => false, + ], + /* + * Use testning filesystem for tests + */ + 'filesystems' => [ + 'disks' => [ + 'testing' => [ + 'driver' => 'local', + 'root' => \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testing', + 'url' => 'files/testing/', + ], + 'testingDriver' => [ + 'driver' => 'localTest', + 'root' => \UserFrosting\STORAGE_DIR . \UserFrosting\DS . 'testingDriver' + ], + ] + ], + /* + * Don't display error detail in test. Return the non formatted errors + */ + 'settings' => [ + 'displayErrorDetails' => false + ], + /* + * Disable native sessions in tests + */ + 'session' => [ + 'handler' => 'array' + ], + /* + * Database to use when using the TestDatabase Trait + */ + 'testing' => [ + 'dbConnection' => getenv('TEST_DB') ?: 'test_integration' + ] +]; diff --git a/app/sprinkles/core/defines.php b/app/sprinkles/core/defines.php index 51873819c..457e7e5d3 100644 --- a/app/sprinkles/core/defines.php +++ b/app/sprinkles/core/defines.php @@ -1,4 +1,10 @@ [ - "@TRANSLATION" => "خطأ", + 'ERROR' => [ + '@TRANSLATION' => 'خطأ', - "400" => [ - "TITLE" => "الخطأ 400:اقتراح غير جيد", - "DESCRIPTION" => "على الارجح ليس خطأك", + '400' => [ + 'TITLE' => 'الخطأ 400:اقتراح غير جيد', + 'DESCRIPTION' => 'على الارجح ليس خطأك', ], - "404" => [ - "TITLE" => "الخطأ 404: الصفحة غير موجودة", - "DESCRIPTION" => " لا يبدو للعثور على ما كنت تبحث عن", - "DETAIL" => "حاولنا العثور على صفحتك", - "EXPLAIN" => "لم نتمكن من العثور على الصفحة التي تبحث عنها", - "RETURN" => 'وفي كلتا الحالتين، اضغط هنا للعودة إلى الصفحة الأولى' + '404' => [ + 'TITLE' => 'الخطأ 404: الصفحة غير موجودة', + 'DESCRIPTION' => ' لا يبدو للعثور على ما كنت تبحث عن', + 'DETAIL' => 'حاولنا العثور على صفحتك', + 'EXPLAIN' => 'لم نتمكن من العثور على الصفحة التي تبحث عنها', + 'RETURN' => 'وفي كلتا الحالتين، اضغط هنا للعودة إلى الصفحة الأولى' ], - "CONFIG" => [ - "TITLE" => "مشكلة في تكوين UserFrosting", - "DESCRIPTION" => "لم تتحقق بعض متطلبات التكوين UserFrosting", - "DETAIL" => "شيء ليس صحيحا هنا", - "RETURN" => 'يرجى تصحيح الأخطاء التالية، ثم إعادة تحميل' + 'CONFIG' => [ + 'TITLE' => 'مشكلة في تكوين UserFrosting', + 'DESCRIPTION' => 'لم تتحقق بعض متطلبات التكوين UserFrosting', + 'DETAIL' => 'شيء ليس صحيحا هنا', + 'RETURN' => 'يرجى تصحيح الأخطاء التالية، ثم إعادة تحميل' ], - "DESCRIPTION" => "لقد لمست اضطراب كبير في الموقع", - "DETAIL" => "وهنا ما عندنا من معلومات", + 'DESCRIPTION' => 'لقد لمست اضطراب كبير في الموقع', + 'DETAIL' => 'وهنا ما عندنا من معلومات', - "ENCOUNTERED" => "حدث شيء لا نعرف ما هو", + 'ENCOUNTERED' => 'حدث شيء لا نعرف ما هو', - "MAIL" => "خطأ فادح في محاولة البريد الإلكتروني، اتصل بمسؤول المقع إذا كنت المشرف، يرجى التحقق من التسجل البريد الإلكتروني UF", + 'MAIL' => 'خطأ فادح في محاولة البريد الإلكتروني، اتصل بمسؤول المقع إذا كنت المشرف، يرجى التحقق من التسجل البريد الإلكتروني UF', - "RETURN" => 'اضغط هنا للعودة إلى الصفحة الأولى', + 'RETURN' => 'اضغط هنا للعودة إلى الصفحة الأولى', - "SERVER" => "يبدو خادمنا قد أخطأ إذا كنت المسير، يرجى مراجعة سجلات الخطأ PHP أو UF", + 'SERVER' => 'يبدو خادمنا قد أخطأ إذا كنت المسير، يرجى مراجعة سجلات الخطأ PHP أو UF', - "TITLE" => "اضطراب في الموقع" + 'TITLE' => 'اضطراب في الموقع' ] ]; diff --git a/app/sprinkles/core/locale/ar/messages.php b/app/sprinkles/core/locale/ar/messages.php index 45964a08b..d77179f2e 100644 --- a/app/sprinkles/core/locale/ar/messages.php +++ b/app/sprinkles/core/locale/ar/messages.php @@ -4,109 +4,109 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Modern Standard Arabic message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\ar * @author Alexander Weissman and Abdullah Seba */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "عن", + 'ABOUT' => 'عن', - "CAPTCHA" => [ - "@TRANSLATION" => "كلمة التحقق", - "FAIL" => "لم تقم بإدخال رمز كلمة التحقق بشكل صحيح", - "SPECIFY" => "أدخل كلمة التحقق", - "VERIFY" => "التحقق من كلمة التحقق" + 'CAPTCHA' => [ + '@TRANSLATION' => 'كلمة التحقق', + 'FAIL' => 'لم تقم بإدخال رمز كلمة التحقق بشكل صحيح', + 'SPECIFY' => 'أدخل كلمة التحقق', + 'VERIFY' => 'التحقق من كلمة التحقق' ], - "CSRF_MISSING" => "رمز CSRF غير موجود حاول تحديث الصفحة ومن ثم إرساله مرة أخرى", + 'CSRF_MISSING' => 'رمز CSRF غير موجود حاول تحديث الصفحة ومن ثم إرساله مرة أخرى', - "DB_INVALID" => "لا يمكن الاتصال بقاعدة البيانات إذا كنت مسؤولا، يرجى مراجعة سجل خطأ", - "DESCRIPTION" => "وصف", - "DOWNLOAD" => [ - "@TRANSLATION" => "تحميل", - "CSV" => "تحميل CSV" + 'DB_INVALID' => 'لا يمكن الاتصال بقاعدة البيانات إذا كنت مسؤولا، يرجى مراجعة سجل خطأ', + 'DESCRIPTION' => 'وصف', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'تحميل', + 'CSV' => 'تحميل CSV' ], - "EMAIL" => [ - "@TRANSLATION" => "البريد الإلكتروني", - "YOUR" => "عنوان بريدك الإلكتروني" + 'EMAIL' => [ + '@TRANSLATION' => 'البريد الإلكتروني', + 'YOUR' => 'عنوان بريدك الإلكتروني' ], - "HOME" => "الصفحة الرئيسية", - - "LEGAL" => [ - "@TRANSLATION" => "السياسة القانونية", - "DESCRIPTION" => "تسري سياستنا القانونية على استخدامك لهذا الموقع وخدماتنا" + 'HOME' => 'الصفحة الرئيسية', + + 'LEGAL' => [ + '@TRANSLATION' => 'السياسة القانونية', + 'DESCRIPTION' => 'تسري سياستنا القانونية على استخدامك لهذا الموقع وخدماتنا' ], - "LOCALE" => [ - "@TRANSLATION" => "اللغه", + 'LOCALE' => [ + '@TRANSLATION' => 'اللغه', ], - "NAME" => "اسم", - "NAVIGATION" => "التنقل", + 'NAME' => 'اسم', + 'NAVIGATION' => 'التنقل', - "PAGINATION" => [ - "GOTO" => "انتقال إلى الصفحة", - "SHOW" => "عرض", - "NEXT" => "الصفحة التالية", - "PREVIOUS" => "الصفحة السابقة", - "FIRST" => "الصفحة الأولى", - "LAST" => "آخر صفحة" + 'PAGINATION' => [ + 'GOTO' => 'انتقال إلى الصفحة', + 'SHOW' => 'عرض', + 'NEXT' => 'الصفحة التالية', + 'PREVIOUS' => 'الصفحة السابقة', + 'FIRST' => 'الصفحة الأولى', + 'LAST' => 'آخر صفحة' ], - "PRIVACY" => [ - "@TRANSLATION" => "سياسة الخصوصية", - "DESCRIPTION" => "تحدد سياسة الخصوصية لدينا نوع المعلومات التي نجمعها منك وكيفية استخدامها." + 'PRIVACY' => [ + '@TRANSLATION' => 'سياسة الخصوصية', + 'DESCRIPTION' => 'تحدد سياسة الخصوصية لدينا نوع المعلومات التي نجمعها منك وكيفية استخدامها.' ], - "SLUG" => "Slug", - "SLUG_CONDITION" => "Slug/الظروف", - "STATUS" => "الحالة", + 'SLUG' => 'Slug', + 'SLUG_CONDITION' => 'Slug/الظروف', + 'STATUS' => 'الحالة', - "UNKNOWN" => "غير معروف", + 'UNKNOWN' => 'غير معروف', // Actions words - "ACTIONS" => "الأفعال", - "ACTIVATE" => "تفعيل", - "ACTIVE" => "نشيط", - "ADD" => "إضافة", - "CANCEL" => "إلغاء", - "CONFIRM" => "تؤكد", - "CREATE" => "أنتج", - "DELETE" => "حذف", - "DELETE_CONFIRM" => "هل أنت متأكد أنك تريد حذف هذا", - "DELETE_CONFIRM_YES" => "نعم، احذف", - "DELETE_CONFIRM_NAMED" => "هل أنت متأكد أنك تريد حذف {{name}}?", - "DELETE_CONFIRM_YES_NAMED" => "نعم، احذف {{name}}", - "DELETE_CANNOT_UNDONE" => "لا يمكن التراجع عن هذا الإجراء", - "DELETE_NAMED" => "احذف {{name}}", - "DENY" => "رفض", - "DISABLE" => "تعطيل", - "DISABLED" => "معطل", - "EDIT" => "تصحيح", - "ENABLE" => "تمكين", - "ENABLED" => "مكين", - "OVERRIDE" => "كتب فوق الكتابة", - "RESET" => "إعادة تعيين", - "SAVE" => "احفظ", - "SEARCH" => "ابحث", - "SORT" => "فرز", - "SUBMIT" => "ارسل", - "PRINT" => "اطباعة", - "REMOVE" => "إزالة", - "UNACTIVATED" => "إبطال", - "UPDATE" => "تحديث", - "YES" => "نعم", - "NO" => "لا", - "OPTIONAL" => "اختياري", + 'ACTIONS' => 'الأفعال', + 'ACTIVATE' => 'تفعيل', + 'ACTIVE' => 'نشيط', + 'ADD' => 'إضافة', + 'CANCEL' => 'إلغاء', + 'CONFIRM' => 'تؤكد', + 'CREATE' => 'أنتج', + 'DELETE' => 'حذف', + 'DELETE_CONFIRM' => 'هل أنت متأكد أنك تريد حذف هذا', + 'DELETE_CONFIRM_YES' => 'نعم، احذف', + 'DELETE_CONFIRM_NAMED' => 'هل أنت متأكد أنك تريد حذف {{name}}?', + 'DELETE_CONFIRM_YES_NAMED' => 'نعم، احذف {{name}}', + 'DELETE_CANNOT_UNDONE' => 'لا يمكن التراجع عن هذا الإجراء', + 'DELETE_NAMED' => 'احذف {{name}}', + 'DENY' => 'رفض', + 'DISABLE' => 'تعطيل', + 'DISABLED' => 'معطل', + 'EDIT' => 'تصحيح', + 'ENABLE' => 'تمكين', + 'ENABLED' => 'مكين', + 'OVERRIDE' => 'كتب فوق الكتابة', + 'RESET' => 'إعادة تعيين', + 'SAVE' => 'احفظ', + 'SEARCH' => 'ابحث', + 'SORT' => 'فرز', + 'SUBMIT' => 'ارسل', + 'PRINT' => 'اطباعة', + 'REMOVE' => 'إزالة', + 'UNACTIVATED' => 'إبطال', + 'UPDATE' => 'تحديث', + 'YES' => 'نعم', + 'NO' => 'لا', + 'OPTIONAL' => 'اختياري', // Misc - "BUILT_WITH_UF" => "بنيت مع UserFrosting", - "ADMINLTE_THEME_BY" => "فكرة رئيسية Almsaeed Studio كل الحقوق محفوظة", - "WELCOME_TO" => "مرحبا بك في {{title}}!" + 'BUILT_WITH_UF' => 'بنيت مع UserFrosting', + 'ADMINLTE_THEME_BY' => 'فكرة رئيسية Almsaeed Studio كل الحقوق محفوظة', + 'WELCOME_TO' => 'مرحبا بك في {{title}}!' ]; diff --git a/app/sprinkles/core/locale/ar/validate.php b/app/sprinkles/core/locale/ar/validate.php index bbccab780..475932803 100644 --- a/app/sprinkles/core/locale/ar/validate.php +++ b/app/sprinkles/core/locale/ar/validate.php @@ -4,22 +4,22 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Modern Standard Arabic message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\ar * @author Alexander Weissman and Abdullah Seba */ - return [ - "VALIDATE" => [ - "ARRAY" => "القيمات ل {{label}} يجب أن تكون في مجموعة", - "BOOLEAN" => "القيم ل {{label}} يجب أن يكون إما '٠' أو '١'", - "INTEGER" => "القيم ل {{label}} يجب أن يكون رقم", - "INVALID_EMAIL" => "عنوان البريد الإلكتروني غير صالح", - "LENGTH_RANGE" => "{{label}} لابد ان تكون بين {{min}} و {{max}} حورف", - "NO_LEAD_WS" => "القيم ل {{label}} لا يمكن أن تبدأ المساحات، علامات، أو بيضاء أخرى", - "NO_TRAIL_WS" => "القيم ل {{label}} لا يمكن أن ينتهي مع مسافات، علامات، أو بيضاء أخرى", - "REQUIRED" => " تحديد قيمة ل {{label}}" + 'VALIDATE' => [ + 'ARRAY' => 'القيمات ل {{label}} يجب أن تكون في مجموعة', + 'BOOLEAN' => "القيم ل {{label}} يجب أن يكون إما '٠' أو '١'", + 'INTEGER' => 'القيم ل {{label}} يجب أن يكون رقم', + 'INVALID_EMAIL' => 'عنوان البريد الإلكتروني غير صالح', + 'LENGTH_RANGE' => '{{label}} لابد ان تكون بين {{min}} و {{max}} حورف', + 'NO_LEAD_WS' => 'القيم ل {{label}} لا يمكن أن تبدأ المساحات، علامات، أو بيضاء أخرى', + 'NO_TRAIL_WS' => 'القيم ل {{label}} لا يمكن أن ينتهي مع مسافات، علامات، أو بيضاء أخرى', + 'REQUIRED' => ' تحديد قيمة ل {{label}}' ] ]; diff --git a/app/sprinkles/core/locale/de_DE/errors.php b/app/sprinkles/core/locale/de_DE/errors.php index cde296b00..b8c48f3bd 100644 --- a/app/sprinkles/core/locale/de_DE/errors.php +++ b/app/sprinkles/core/locale/de_DE/errors.php @@ -4,50 +4,50 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * German message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\de * @author X-Anonymous-Y * @author kevinrombach * @author splitt3r */ - return [ - "ERROR" => [ - "@TRANSLATION" => "Fehler", + 'ERROR' => [ + '@TRANSLATION' => 'Fehler', - "400" => [ - "TITLE" => "Fehler 400: Ungültige Anforderung", - "DESCRIPTION" => "Die Anfrage-Nachricht war fehlerhaft aufgebaut.", + '400' => [ + 'TITLE' => 'Fehler 400: Ungültige Anforderung', + 'DESCRIPTION' => 'Die Anfrage-Nachricht war fehlerhaft aufgebaut.', ], - "404" => [ - "TITLE" => "Fehler 404: Seite nicht gefunden", - "DESCRIPTION" => "Die angeforderte Ressource wurde nicht gefunden.", - "DETAIL" => "Wir haben versucht Ihre Seite zu finden ...", - "EXPLAIN" => "Die von Ihnen gesuchte Seite konnte nicht gefunden werden.", - "RETURN" => "Klicken Sie Hier, um zur Startseite zurückzukehren." + '404' => [ + 'TITLE' => 'Fehler 404: Seite nicht gefunden', + 'DESCRIPTION' => 'Die angeforderte Ressource wurde nicht gefunden.', + 'DETAIL' => 'Wir haben versucht Ihre Seite zu finden ...', + 'EXPLAIN' => 'Die von Ihnen gesuchte Seite konnte nicht gefunden werden.', + 'RETURN' => "Klicken Sie Hier, um zur Startseite zurückzukehren." ], - "CONFIG" => [ - "TITLE" => "UserFrosting Konfigurationsproblem!", - "DESCRIPTION" => "Einige UserFrosting-Konfigurationsanforderungen wurden nicht erfüllt.", - "DETAIL" => "Etwas stimmt hier nicht.", - "RETURN" => "Bitte beheben Sie die folgenden Fehler dann laden Sie die Website neu." + 'CONFIG' => [ + 'TITLE' => 'UserFrosting Konfigurationsproblem!', + 'DESCRIPTION' => 'Einige UserFrosting-Konfigurationsanforderungen wurden nicht erfüllt.', + 'DETAIL' => 'Etwas stimmt hier nicht.', + 'RETURN' => "Bitte beheben Sie die folgenden Fehler dann laden Sie die Website neu." ], - "DESCRIPTION" => "Wir haben eine große Störung in der Macht erkannt.", - "DETAIL" => "Hier haben wir:", + 'DESCRIPTION' => 'Wir haben eine große Störung in der Macht erkannt.', + 'DETAIL' => 'Hier haben wir:', - "ENCOUNTERED" => "Uhhh ... etwas ist passiert. Wir wissen nicht was.", + 'ENCOUNTERED' => 'Uhhh ... etwas ist passiert. Wir wissen nicht was.', - "MAIL" => "Schwerwiegender Fehler beim Mailversand, wenden Sie sich an Ihren Serveradministrator. Wenn Sie der Administrator sind, überprüfen Sie bitte das UF-Mail-Protokoll.", + 'MAIL' => 'Schwerwiegender Fehler beim Mailversand, wenden Sie sich an Ihren Serveradministrator. Wenn Sie der Administrator sind, überprüfen Sie bitte das UF-Mail-Protokoll.', - "RETURN" => "Klicken Sie Hier, um zur Startseite zurückzukehren.", + 'RETURN' => "Klicken Sie Hier, um zur Startseite zurückzukehren.", - "SERVER" => "Hoppla, sieht aus als hätte der Server möglicherweise gepatzt. Wenn Sie ein Administrator sind, überprüfen Sie bitte die PHP- oder UF-Fehlerprotokolle.", + 'SERVER' => 'Hoppla, sieht aus als hätte der Server möglicherweise gepatzt. Wenn Sie ein Administrator sind, überprüfen Sie bitte die PHP- oder UF-Fehlerprotokolle.', - "TITLE" => "Störung in der Kraft" + 'TITLE' => 'Störung in der Kraft' ] ]; diff --git a/app/sprinkles/core/locale/de_DE/messages.php b/app/sprinkles/core/locale/de_DE/messages.php index e254c65b6..0c565e40c 100644 --- a/app/sprinkles/core/locale/de_DE/messages.php +++ b/app/sprinkles/core/locale/de_DE/messages.php @@ -4,120 +4,120 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * German message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\de * @author X-Anonymous-Y * @author kevinrombach * @author splitt3r */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "Über", + 'ABOUT' => 'Über', - "CAPTCHA" => [ - "@TRANSLATION" => "Sicherheitscode", - "FAIL" => "Sie haben den Sicherheitscode nicht korrekt eingegeben.", - "SPECIFY" => "Geben Sie den Sicherheitscode ein", - "VERIFY" => "Überprüfen Sie den Sicherheitscode" + 'CAPTCHA' => [ + '@TRANSLATION' => 'Sicherheitscode', + 'FAIL' => 'Sie haben den Sicherheitscode nicht korrekt eingegeben.', + 'SPECIFY' => 'Geben Sie den Sicherheitscode ein', + 'VERIFY' => 'Überprüfen Sie den Sicherheitscode' ], - "CSRF_MISSING" => "Fehlender CSRF-Token. Versuchen, die Seite zu aktualisieren und erneut zu senden?", + 'CSRF_MISSING' => 'Fehlender CSRF-Token. Versuchen, die Seite zu aktualisieren und erneut zu senden?', - "DB_INVALID" => "Keine Verbindung zur Datenbank möglich. Wenn Sie ein Administrator sind, überprüfen Sie bitte Ihr Fehlerprotokoll.", - "DESCRIPTION" => "Beschreibung", - "DOWNLOAD" => [ - "@TRANSLATION" => "Herunterladen", - "CSV" => "CSV herunterladen" + 'DB_INVALID' => 'Keine Verbindung zur Datenbank möglich. Wenn Sie ein Administrator sind, überprüfen Sie bitte Ihr Fehlerprotokoll.', + 'DESCRIPTION' => 'Beschreibung', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'Herunterladen', + 'CSV' => 'CSV herunterladen' ], - "EMAIL" => [ - "@TRANSLATION" => "E-Mail", - "YOUR" => "Ihre E-Mail-Adresse" + 'EMAIL' => [ + '@TRANSLATION' => 'E-Mail', + 'YOUR' => 'Ihre E-Mail-Adresse' ], - "HOME" => "Startseite", + 'HOME' => 'Startseite', - "LEGAL" => [ - "@TRANSLATION" => "Rechtsgrundsatz", - "DESCRIPTION" => "Unser Rechtsgrundsatz gilt für die Benutzung dieser Internetseite und unserer Dienste." + 'LEGAL' => [ + '@TRANSLATION' => 'Rechtsgrundsatz', + 'DESCRIPTION' => 'Unser Rechtsgrundsatz gilt für die Benutzung dieser Internetseite und unserer Dienste.' ], - "LOCALE" => [ - "@TRANSLATION" => "Sprache" + 'LOCALE' => [ + '@TRANSLATION' => 'Sprache' ], - "NAME" => "Name", - "NAVIGATION" => "Navigation", - "NO_RESULTS" => "Sorry, hier gibt es bisher nichts zu sehen.", + 'NAME' => 'Name', + 'NAVIGATION' => 'Navigation', + 'NO_RESULTS' => 'Sorry, hier gibt es bisher nichts zu sehen.', - "PAGINATION" => [ - "GOTO" => "Gehe zu Seite", - "SHOW" => "Anzeigen", + 'PAGINATION' => [ + 'GOTO' => 'Gehe zu Seite', + 'SHOW' => 'Anzeigen', // Paginator // possible variables: {size}, {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} // also {page:input} & {startRow:input} will add a modifiable input in place of the value - "OUTPUT" => "{startRow} bis {endRow} von {filteredRows} ({totalRows})", + 'OUTPUT' => '{startRow} bis {endRow} von {filteredRows} ({totalRows})', - "NEXT" => "Nächste Seite", - "PREVIOUS" => "Vorherige Seite", - "FIRST" => "Erste Seite", - "LAST" => "Letzte Seite" + 'NEXT' => 'Nächste Seite', + 'PREVIOUS' => 'Vorherige Seite', + 'FIRST' => 'Erste Seite', + 'LAST' => 'Letzte Seite' ], - "PRIVACY" => [ - "@TRANSLATION" => "Datenschutzbestimmungen", - "DESCRIPTION" => "In unsere Datenschutzbestimmungen erklären wir Ihnen, welche Daten wir sammeln und wozu wir diese benutzen." + 'PRIVACY' => [ + '@TRANSLATION' => 'Datenschutzbestimmungen', + 'DESCRIPTION' => 'In unsere Datenschutzbestimmungen erklären wir Ihnen, welche Daten wir sammeln und wozu wir diese benutzen.' ], - "SLUG" => "Schnecke", - "SLUG_CONDITION" => "Schnecke/Bedingungen", - "SLUG_IN_USE" => "Die Schnecke {{slug}} existiert bereits", - "STATUS" => "Status", - "SUGGEST" => "Vorschlagen", + 'SLUG' => 'Schnecke', + 'SLUG_CONDITION' => 'Schnecke/Bedingungen', + 'SLUG_IN_USE' => 'Die Schnecke {{slug}} existiert bereits', + 'STATUS' => 'Status', + 'SUGGEST' => 'Vorschlagen', - "UNKNOWN" => "Unbekannt", + 'UNKNOWN' => 'Unbekannt', // Actions words - "ACTIONS" => "Aktionen", - "ACTIVATE" => "Aktivieren", - "ACTIVE" => "Aktiv", - "ADD" => "Hinzufügen", - "CANCEL" => "Abbrechen", - "CONFIRM" => "Bestätigen", - "CREATE" => "Erstellen", - "DELETE" => "Löschen", - "DELETE_CONFIRM" => "Möchten Sie diese wirklich löschen?", - "DELETE_CONFIRM_YES" => "Ja, löschen", - "DELETE_CONFIRM_NAMED" => "Möchten Sie {{name}} wirklich löschen?", - "DELETE_CONFIRM_YES_NAMED" => "Ja, {{name}} löschen", - "DELETE_CANNOT_UNDONE" => "Diese Aktion kann nicht rückgängig gemacht werden.", - "DELETE_NAMED" => "{{name}} löschen", - "DENY" => "Verweigern", - "DISABLE" => "Deaktivieren", - "DISABLED" => "Deaktiviert", - "EDIT" => "Bearbeiten", - "ENABLE" => "Aktivieren", - "ENABLED" => "Aktiviert", - "OVERRIDE" => "Überschreiben", - "RESET" => "Zurücksetzen", - "SAVE" => "Speichern", - "SEARCH" => "Suchen", - "SORT" => "Sortieren", - "SUBMIT" => "Einreichen", - "PRINT" => "Drucken", - "REMOVE" => "Entfernen", - "UNACTIVATED" => "Unaktiviert", - "UPDATE" => "Aktualisieren", - "YES" => "Ja", - "NO" => "Nein", - "OPTIONAL" => "Optional", + 'ACTIONS' => 'Aktionen', + 'ACTIVATE' => 'Aktivieren', + 'ACTIVE' => 'Aktiv', + 'ADD' => 'Hinzufügen', + 'CANCEL' => 'Abbrechen', + 'CONFIRM' => 'Bestätigen', + 'CREATE' => 'Erstellen', + 'DELETE' => 'Löschen', + 'DELETE_CONFIRM' => 'Möchten Sie diese wirklich löschen?', + 'DELETE_CONFIRM_YES' => 'Ja, löschen', + 'DELETE_CONFIRM_NAMED' => 'Möchten Sie {{name}} wirklich löschen?', + 'DELETE_CONFIRM_YES_NAMED' => 'Ja, {{name}} löschen', + 'DELETE_CANNOT_UNDONE' => 'Diese Aktion kann nicht rückgängig gemacht werden.', + 'DELETE_NAMED' => '{{name}} löschen', + 'DENY' => 'Verweigern', + 'DISABLE' => 'Deaktivieren', + 'DISABLED' => 'Deaktiviert', + 'EDIT' => 'Bearbeiten', + 'ENABLE' => 'Aktivieren', + 'ENABLED' => 'Aktiviert', + 'OVERRIDE' => 'Überschreiben', + 'RESET' => 'Zurücksetzen', + 'SAVE' => 'Speichern', + 'SEARCH' => 'Suchen', + 'SORT' => 'Sortieren', + 'SUBMIT' => 'Einreichen', + 'PRINT' => 'Drucken', + 'REMOVE' => 'Entfernen', + 'UNACTIVATED' => 'Unaktiviert', + 'UPDATE' => 'Aktualisieren', + 'YES' => 'Ja', + 'NO' => 'Nein', + 'OPTIONAL' => 'Optional', // Misc. - "BUILT_WITH_UF" => "Errichtet mit UserFrosting", - "ADMINLTE_THEME_BY" => "Theme von Almsaeed Studio. Alle Rechte vorbehalten", - "WELCOME_TO" => "Willkommen auf {{title}}!" + 'BUILT_WITH_UF' => 'Errichtet mit UserFrosting', + 'ADMINLTE_THEME_BY' => 'Theme von Almsaeed Studio. Alle Rechte vorbehalten', + 'WELCOME_TO' => 'Willkommen auf {{title}}!' ]; diff --git a/app/sprinkles/core/locale/de_DE/validate.php b/app/sprinkles/core/locale/de_DE/validate.php index c10a20a2f..1ef1cbfc6 100644 --- a/app/sprinkles/core/locale/de_DE/validate.php +++ b/app/sprinkles/core/locale/de_DE/validate.php @@ -4,29 +4,29 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * German message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\de * @author X-Anonymous-Y * @author kevinrombach * @author splitt3r */ - return [ - "VALIDATE" => [ - "ARRAY" => "Die Werte für {{label}} müssen in einem Feld liegen.", - "BOOLEAN" => "Der Wert für {{label}} muss entweder '0' oder '1' sein.", - "INTEGER" => "Der Wert für {{label}} muss eine ganze Zahl sein.", - "INVALID_EMAIL" => "Ungültige E-Mail-Adresse.", - "LENGTH_RANGE" => "{{label}} muss zwischen {{min}} und {{max}} Zeichen lang sein.", - "NO_LEAD_WS" => "Der Wert für {{label}} kann nicht mit Leerzeichen, Tabulatoren oder anderen Leerzeichen beginnen.", - "NO_TRAIL_WS" => "Der Wert für {{label}} kann nicht mit Leerzeichen, Tabulatoren oder anderen Leerzeichen enden.", - "REQUIRED" => "Bitte geben Sie einen Wert für {{label}} an.", - "SPRUNJE" => [ - "BAD_FILTER" => "{{name}} ist kein gültiger Filter für dieses Sprunje.", - "BAD_LIST" => "{{name}} ist kein gültige Liste für dieses Sprunje.", - "BAD_SORT" => "{{name}} ist kein gültiges Sortierungsfeld für dieses Sprunje." + 'VALIDATE' => [ + 'ARRAY' => 'Die Werte für {{label}} müssen in einem Feld liegen.', + 'BOOLEAN' => "Der Wert für {{label}} muss entweder '0' oder '1' sein.", + 'INTEGER' => 'Der Wert für {{label}} muss eine ganze Zahl sein.', + 'INVALID_EMAIL' => 'Ungültige E-Mail-Adresse.', + 'LENGTH_RANGE' => '{{label}} muss zwischen {{min}} und {{max}} Zeichen lang sein.', + 'NO_LEAD_WS' => 'Der Wert für {{label}} kann nicht mit Leerzeichen, Tabulatoren oder anderen Leerzeichen beginnen.', + 'NO_TRAIL_WS' => 'Der Wert für {{label}} kann nicht mit Leerzeichen, Tabulatoren oder anderen Leerzeichen enden.', + 'REQUIRED' => 'Bitte geben Sie einen Wert für {{label}} an.', + 'SPRUNJE' => [ + 'BAD_FILTER' => '{{name}} ist kein gültiger Filter für dieses Sprunje.', + 'BAD_LIST' => '{{name}} ist kein gültige Liste für dieses Sprunje.', + 'BAD_SORT' => '{{name}} ist kein gültiges Sortierungsfeld für dieses Sprunje.' ] ] ]; diff --git a/app/sprinkles/core/locale/en_US/errors.php b/app/sprinkles/core/locale/en_US/errors.php index e86897429..8fc30cb9a 100644 --- a/app/sprinkles/core/locale/en_US/errors.php +++ b/app/sprinkles/core/locale/en_US/errors.php @@ -4,48 +4,49 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * US English message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\en_US * @author Alexander Weissman */ return [ - "ERROR" => [ - "@TRANSLATION" => "Error", + 'ERROR' => [ + '@TRANSLATION' => 'Error', - "400" => [ - "TITLE" => "Error 400: Bad Request", - "DESCRIPTION" => "It's probably not your fault.", + '400' => [ + 'TITLE' => 'Error 400: Bad Request', + 'DESCRIPTION' => "It's probably not your fault.", ], - "404" => [ - "TITLE" => "Error 404: Not Found", - "DESCRIPTION" => "We can't seem to find what you're looking for.", - "DETAIL" => "We tried to find your page...", - "EXPLAIN" => "We could not find the page you were looking for.", - "RETURN" => 'Either way, click here to return to the front page.' + '404' => [ + 'TITLE' => 'Error 404: Not Found', + 'DESCRIPTION' => "We can't seem to find what you're looking for.", + 'DETAIL' => 'We tried to find your page...', + 'EXPLAIN' => 'We could not find the page you were looking for.', + 'RETURN' => 'Either way, click here to return to the front page.' ], - "CONFIG" => [ - "TITLE" => "UserFrosting Configuration Issue!", - "DESCRIPTION" => "Some UserFrosting configuration requirements have not been met.", - "DETAIL" => "Something's not right here.", - "RETURN" => 'Please fix the following errors, then reload.' + 'CONFIG' => [ + 'TITLE' => 'UserFrosting Configuration Issue!', + 'DESCRIPTION' => 'Some UserFrosting configuration requirements have not been met.', + 'DETAIL' => "Something's not right here.", + 'RETURN' => 'Please fix the following errors, then reload.' ], - "DESCRIPTION" => "We've sensed a great disturbance in the Force.", - "DETAIL" => "Here's what we got:", + 'DESCRIPTION' => "We've sensed a great disturbance in the Force.", + 'DETAIL' => "Here's what we got:", + + 'ENCOUNTERED' => "Uhhh...something happened. We don't know what.", - "ENCOUNTERED" => "Uhhh...something happened. We don't know what.", + 'MAIL' => 'Fatal error attempting mail, contact your server administrator. If you are the admin, please check the UserFrosting log.', - "MAIL" => "Fatal error attempting mail, contact your server administrator. If you are the admin, please check the UserFrosting log.", - - "RETURN" => 'Click here to return to the front page.', + 'RETURN' => 'Click here to return to the front page.', - "SERVER" => "Oops, looks like our server might have goofed. If you're an admin, please check the PHP or UserFrosting logs.", + 'SERVER' => "Oops, looks like our server might have goofed. If you're an admin, please check the PHP or UserFrosting logs.", - "TITLE" => "Disturbance in the Force" + 'TITLE' => 'Disturbance in the Force' ] ]; diff --git a/app/sprinkles/core/locale/en_US/messages.php b/app/sprinkles/core/locale/en_US/messages.php index b0827e262..657a1f753 100644 --- a/app/sprinkles/core/locale/en_US/messages.php +++ b/app/sprinkles/core/locale/en_US/messages.php @@ -4,117 +4,117 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * US English message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\en_US * @author Alexander Weissman */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "About", + 'ABOUT' => 'About', - "CAPTCHA" => [ - "@TRANSLATION" => "Captcha", - "FAIL" => "You did not enter the captcha code correctly.", - "SPECIFY" => "Enter the captcha", - "VERIFY" => "Verify the captcha" + 'CAPTCHA' => [ + '@TRANSLATION' => 'Captcha', + 'FAIL' => 'You did not enter the captcha code correctly.', + 'SPECIFY' => 'Enter the captcha', + 'VERIFY' => 'Verify the captcha' ], - "CSRF_MISSING" => "Missing CSRF token. Try refreshing the page and then submitting again?", + 'CSRF_MISSING' => 'Missing CSRF token. Try refreshing the page and then submitting again?', - "DB_INVALID" => "Cannot connect to the database. If you are an administrator, please check your error log.", - "DESCRIPTION" => "Description", - "DOWNLOAD" => [ - "@TRANSLATION" => "Download", - "CSV" => "Download CSV" + 'DB_INVALID' => 'Cannot connect to the database. If you are an administrator, please check your error log.', + 'DESCRIPTION' => 'Description', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'Download', + 'CSV' => 'Download CSV' ], - "EMAIL" => [ - "@TRANSLATION" => "Email", - "YOUR" => "Your email address" + 'EMAIL' => [ + '@TRANSLATION' => 'Email', + 'YOUR' => 'Your email address' ], - "HOME" => "Home", + 'HOME' => 'Home', - "LEGAL" => [ - "@TRANSLATION" => "Legal Policy", - "DESCRIPTION" => "Our legal policy applies to your usage of this website and our services." + 'LEGAL' => [ + '@TRANSLATION' => 'Legal Policy', + 'DESCRIPTION' => 'Our legal policy applies to your usage of this website and our services.' ], - "LOCALE" => [ - "@TRANSLATION" => "Locale" + 'LOCALE' => [ + '@TRANSLATION' => 'Locale' ], - "NAME" => "Name", - "NAVIGATION" => "Navigation", - "NO_RESULTS" => "Sorry, we've got nothing here.", + 'NAME' => 'Name', + 'NAVIGATION' => 'Navigation', + 'NO_RESULTS' => "Sorry, we've got nothing here.", - "PAGINATION" => [ - "GOTO" => "Jump to Page", - "SHOW" => "Show", + 'PAGINATION' => [ + 'GOTO' => 'Jump to Page', + 'SHOW' => 'Show', // Paginator // possible variables: {size}, {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} // also {page:input} & {startRow:input} will add a modifiable input in place of the value - "OUTPUT" => "{startRow} to {endRow} of {filteredRows} ({totalRows})", - "NEXT" => "Next page", - "PREVIOUS" => "Previous page", - "FIRST" => "First page", - "LAST" => "Last page" + 'OUTPUT' => '{startRow} to {endRow} of {filteredRows} ({totalRows})', + 'NEXT' => 'Next page', + 'PREVIOUS' => 'Previous page', + 'FIRST' => 'First page', + 'LAST' => 'Last page' ], - "PRIVACY" => [ - "@TRANSLATION" => "Privacy Policy", - "DESCRIPTION" => "Our privacy policy outlines what kind of information we collect from you and how we will use it." + 'PRIVACY' => [ + '@TRANSLATION' => 'Privacy Policy', + 'DESCRIPTION' => 'Our privacy policy outlines what kind of information we collect from you and how we will use it.' ], - "SLUG" => "Slug", - "SLUG_CONDITION" => "Slug/Conditions", - "SLUG_IN_USE" => "A {{slug}} slug already exists", - "STATUS" => "Status", - "SUGGEST" => "Suggest", + 'SLUG' => 'Slug', + 'SLUG_CONDITION' => 'Slug/Conditions', + 'SLUG_IN_USE' => 'A {{slug}} slug already exists', + 'STATUS' => 'Status', + 'SUGGEST' => 'Suggest', - "UNKNOWN" => "Unknown", + 'UNKNOWN' => 'Unknown', // Actions words - "ACTIONS" => "Actions", - "ACTIVATE" => "Activate", - "ACTIVE" => "Active", - "ADD" => "Add", - "CANCEL" => "Cancel", - "CONFIRM" => "Confirm", - "CREATE" => "Create", - "DELETE" => "Delete", - "DELETE_CONFIRM" => "Are you sure you want to delete this?", - "DELETE_CONFIRM_YES" => "Yes, delete", - "DELETE_CONFIRM_NAMED" => "Are you sure you want to delete {{name}}?", - "DELETE_CONFIRM_YES_NAMED" => "Yes, delete {{name}}", - "DELETE_CANNOT_UNDONE" => "This action cannot be undone.", - "DELETE_NAMED" => "Delete {{name}}", - "DENY" => "Deny", - "DISABLE" => "Disable", - "DISABLED" => "Disabled", - "EDIT" => "Edit", - "ENABLE" => "Enable", - "ENABLED" => "Enabled", - "OVERRIDE" => "Override", - "RESET" => "Reset", - "SAVE" => "Save", - "SEARCH" => "Search", - "SORT" => "Sort", - "SUBMIT" => "Submit", - "PRINT" => "Print", - "REMOVE" => "Remove", - "UNACTIVATED" => "Unactivated", - "UPDATE" => "Update", - "YES" => "Yes", - "NO" => "No", - "OPTIONAL" => "Optional", + 'ACTIONS' => 'Actions', + 'ACTIVATE' => 'Activate', + 'ACTIVE' => 'Active', + 'ADD' => 'Add', + 'CANCEL' => 'Cancel', + 'CONFIRM' => 'Confirm', + 'CREATE' => 'Create', + 'DELETE' => 'Delete', + 'DELETE_CONFIRM' => 'Are you sure you want to delete this?', + 'DELETE_CONFIRM_YES' => 'Yes, delete', + 'DELETE_CONFIRM_NAMED' => 'Are you sure you want to delete {{name}}?', + 'DELETE_CONFIRM_YES_NAMED' => 'Yes, delete {{name}}', + 'DELETE_CANNOT_UNDONE' => 'This action cannot be undone.', + 'DELETE_NAMED' => 'Delete {{name}}', + 'DENY' => 'Deny', + 'DISABLE' => 'Disable', + 'DISABLED' => 'Disabled', + 'EDIT' => 'Edit', + 'ENABLE' => 'Enable', + 'ENABLED' => 'Enabled', + 'OVERRIDE' => 'Override', + 'RESET' => 'Reset', + 'SAVE' => 'Save', + 'SEARCH' => 'Search', + 'SORT' => 'Sort', + 'SUBMIT' => 'Submit', + 'PRINT' => 'Print', + 'REMOVE' => 'Remove', + 'UNACTIVATED' => 'Unactivated', + 'UPDATE' => 'Update', + 'YES' => 'Yes', + 'NO' => 'No', + 'OPTIONAL' => 'Optional', // Misc. - "BUILT_WITH_UF" => "Built with UserFrosting", - "ADMINLTE_THEME_BY" => "Theme by Almsaeed Studio. All rights reserved", - "WELCOME_TO" => "Welcome to {{title}}!" + 'BUILT_WITH_UF' => 'Built with UserFrosting', + 'ADMINLTE_THEME_BY' => 'Theme by Almsaeed Studio. All rights reserved', + 'WELCOME_TO' => 'Welcome to {{title}}!' ]; diff --git a/app/sprinkles/core/locale/en_US/validate.php b/app/sprinkles/core/locale/en_US/validate.php index 8e03c8453..75001302c 100644 --- a/app/sprinkles/core/locale/en_US/validate.php +++ b/app/sprinkles/core/locale/en_US/validate.php @@ -4,30 +4,30 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * US English message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\en_US * @author Alexander Weissman */ - return [ - "VALIDATE" => [ - "ARRAY" => "The values for {{label}} must be in an array.", - "BOOLEAN" => "The value for {{label}} must be either '0' or '1'.", - "INTEGER" => "The value for {{label}} must be an integer.", - "INVALID_EMAIL" => "Invalid email address.", - "LENGTH_RANGE" => "{{label}} must be between {{min}} and {{max}} characters in length.", - "MAX_LENGTH" => "{{label}} must be maximum {{max}} characters in length.", - "MIN_LENGTH" => "{{label}} must be minimum {{min}} characters in length.", - "NO_LEAD_WS" => "The value for {{label}} cannot begin with spaces, tabs, or other whitespace.", - "NO_TRAIL_WS" => "The value for {{label}} cannot end with spaces, tabs, or other whitespace.", - "RANGE" => "The value for {{label}} must be between {{min}} and {{max}}.", - "REQUIRED" => "Please specify a value for {{label}}.", - "SPRUNJE" => [ - "BAD_FILTER" => "{{name}} is not a valid filter for this Sprunje.", - "BAD_LIST" => "{{name}} is not a valid list for this Sprunje.", - "BAD_SORT" => "{{name}} is not a valid sort field for this Sprunje." + 'VALIDATE' => [ + 'ARRAY' => 'The values for {{label}} must be in an array.', + 'BOOLEAN' => "The value for {{label}} must be either '0' or '1'.", + 'INTEGER' => 'The value for {{label}} must be an integer.', + 'INVALID_EMAIL' => 'Invalid email address.', + 'LENGTH_RANGE' => '{{label}} must be between {{min}} and {{max}} characters in length.', + 'MAX_LENGTH' => '{{label}} must be maximum {{max}} characters in length.', + 'MIN_LENGTH' => '{{label}} must be minimum {{min}} characters in length.', + 'NO_LEAD_WS' => 'The value for {{label}} cannot begin with spaces, tabs, or other whitespace.', + 'NO_TRAIL_WS' => 'The value for {{label}} cannot end with spaces, tabs, or other whitespace.', + 'RANGE' => 'The value for {{label}} must be between {{min}} and {{max}}.', + 'REQUIRED' => 'Please specify a value for {{label}}.', + 'SPRUNJE' => [ + 'BAD_FILTER' => '{{name}} is not a valid filter for this Sprunje.', + 'BAD_LIST' => '{{name}} is not a valid list for this Sprunje.', + 'BAD_SORT' => '{{name}} is not a valid sort field for this Sprunje.' ] ] ]; diff --git a/app/sprinkles/core/locale/es_ES/errors.php b/app/sprinkles/core/locale/es_ES/errors.php index 6dd553d12..f92476129 100755 --- a/app/sprinkles/core/locale/es_ES/errors.php +++ b/app/sprinkles/core/locale/es_ES/errors.php @@ -4,48 +4,48 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Spanish message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\es_ES * @author rafa31gz */ - return [ - "ERROR" => [ - "@TRANSLATION" => "Error", + 'ERROR' => [ + '@TRANSLATION' => 'Error', - "400" => [ - "TITLE" => "Error 400: solicitud incorrecta", - "DESCRIPTION" => "Probablemente no es tu culpa.", + '400' => [ + 'TITLE' => 'Error 400: solicitud incorrecta', + 'DESCRIPTION' => 'Probablemente no es tu culpa.', ], - "404" => [ - "TITLE" => "Error 404 - Página no encontrada", - "DESCRIPTION" => "Parece que no podemos encontrar lo que buscas.", - "DETAIL" => "Intentamos encontrar tu página ...", - "EXPLAIN" => "No pudimos encontrar la página que buscabas.", - "RETURN" => 'De cualquier manera, haz clic en aquí para volver a la página principal.' + '404' => [ + 'TITLE' => 'Error 404 - Página no encontrada', + 'DESCRIPTION' => 'Parece que no podemos encontrar lo que buscas.', + 'DETAIL' => 'Intentamos encontrar tu página ...', + 'EXPLAIN' => 'No pudimos encontrar la página que buscabas.', + 'RETURN' => 'De cualquier manera, haz clic en aquí para volver a la página principal.' ], - - "CONFIG" => [ - "TITLE" => "¡Problema de configuración del Servidor!", - "DESCRIPTION" => "Algunos requisitos de configuración de Servidor no se han cumplido.", - "DETAIL" => "Algo no está bien aquí.", - "RETURN" => 'Corrije los siguientes errores, luego recargue .' + + 'CONFIG' => [ + 'TITLE' => '¡Problema de configuración del Servidor!', + 'DESCRIPTION' => 'Algunos requisitos de configuración de Servidor no se han cumplido.', + 'DETAIL' => 'Algo no está bien aquí.', + 'RETURN' => 'Corrije los siguientes errores, luego recargue .' ], - - "DESCRIPTION" => "Hemos sentido una gran perturbación en la Fuerza.", - "DETAIL" => "Esto es lo que tenemos:", - "ENCOUNTERED" => "Uhhh ... sucedió algo. No sabemos qué.", + 'DESCRIPTION' => 'Hemos sentido una gran perturbación en la Fuerza.', + 'DETAIL' => 'Esto es lo que tenemos:', + + 'ENCOUNTERED' => 'Uhhh ... sucedió algo. No sabemos qué.', - "MAIL" => "Error fatal al intentar enviar correo, ponte en contacto con el administrador del servidor. Si tú eres el administrador, comprueba el log de errores.", + 'MAIL' => 'Error fatal al intentar enviar correo, ponte en contacto con el administrador del servidor. Si tú eres el administrador, comprueba el log de errores.', - "RETURN" => 'Haz clic en aquí para volver a la página principal.', + 'RETURN' => 'Haz clic en aquí para volver a la página principal.', - "SERVER" => "¡Vaya! Parece que nuestro servidor pudo haber metido la pata. Si eres un administrador, comprueba los registros de errores de PHP o el log de UserFrosting.", + 'SERVER' => '¡Vaya! Parece que nuestro servidor pudo haber metido la pata. Si eres un administrador, comprueba los registros de errores de PHP o el log de UserFrosting.', - "TITLE" => "Perturbación en la Fuerza", + 'TITLE' => 'Perturbación en la Fuerza', ] ]; diff --git a/app/sprinkles/core/locale/es_ES/messages.php b/app/sprinkles/core/locale/es_ES/messages.php index cd8a3e1aa..69e2ecf36 100755 --- a/app/sprinkles/core/locale/es_ES/messages.php +++ b/app/sprinkles/core/locale/es_ES/messages.php @@ -4,112 +4,112 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Spanish message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\es_ES * @author rafa31gz */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "Acerca de", - "WELCOME_TO" => "¡Bienvenido a {{title}}!", + 'ABOUT' => 'Acerca de', + 'WELCOME_TO' => '¡Bienvenido a {{title}}!', - "CAPTCHA" => [ - "@TRANSLATION" => "Captcha", - "FAIL" => "No has introducido correctamente el código de captcha.", - "SPECIFY" => "Introduzce el captcha", - "VERIFY" => "Verificar el captcha" + 'CAPTCHA' => [ + '@TRANSLATION' => 'Captcha', + 'FAIL' => 'No has introducido correctamente el código de captcha.', + 'SPECIFY' => 'Introduzce el captcha', + 'VERIFY' => 'Verificar el captcha' ], - "CSRF_MISSING" => "¿Falta el símbolo CSRF?. Intenta refrescar la página y luego volver a enviarla", + 'CSRF_MISSING' => '¿Falta el símbolo CSRF?. Intenta refrescar la página y luego volver a enviarla', - "DB_INVALID" => "No se puede conectar a la base de datos. Si eres un administrador, comprueba su registro de errores.", - "DESCRIPTION" => "Descripción", - "DOWNLOAD" => [ - "@TRANSLATION" => "Descargar", - "CSV" => "Descargar CSV" + 'DB_INVALID' => 'No se puede conectar a la base de datos. Si eres un administrador, comprueba su registro de errores.', + 'DESCRIPTION' => 'Descripción', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'Descargar', + 'CSV' => 'Descargar CSV' ], - "EMAIL" => [ - "@TRANSLATION" => "Email", - "YOUR" => "Tu correo electrónico" + 'EMAIL' => [ + '@TRANSLATION' => 'Email', + 'YOUR' => 'Tu correo electrónico' ], - "HOME" => "Inicio", + 'HOME' => 'Inicio', - "LEGAL" => "Política Legal", + 'LEGAL' => 'Política Legal', - "LOCALE" => [ - "@TRANSLATION" => "Traducción" + 'LOCALE' => [ + '@TRANSLATION' => 'Traducción' ], - "MAIL_ERROR" => "Error fatal al intentar enviar correo, ponte en contacto con el administrador del servidor. Si eres el administrador, comprueba el registro de correo de UF.", + 'MAIL_ERROR' => 'Error fatal al intentar enviar correo, ponte en contacto con el administrador del servidor. Si eres el administrador, comprueba el registro de correo de UF.', - "NAME" => "Nombre", - "NAVIGATION" => "Navegación", + 'NAME' => 'Nombre', + 'NAVIGATION' => 'Navegación', - "PAGINATION" => [ - "GOTO" => "Ir a la página", - "SHOW" => "Mostrar", + 'PAGINATION' => [ + 'GOTO' => 'Ir a la página', + 'SHOW' => 'Mostrar', // Paginator // possible variables: {size}, {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} // also {page:input} & {startRow:input} will add a modifiable input in place of the value - "OUTPUT" => "{startRow} a {endRow} de {filteredRows} ({totalRows})", - "NEXT" => "Siguiente página", - "PREVIOUS" => "Pagina anterior", - "FIRST" => "Primera página", - "LAST" => "Última página" + 'OUTPUT' => '{startRow} a {endRow} de {filteredRows} ({totalRows})', + 'NEXT' => 'Siguiente página', + 'PREVIOUS' => 'Pagina anterior', + 'FIRST' => 'Primera página', + 'LAST' => 'Última página' ], - "PRIVACY" => "Política de privacidad", + 'PRIVACY' => 'Política de privacidad', - "SLUG" => "Slug", - "SLUG_CONDITION" => "Slug/Condiciones", - "SLUG_IN_USE" => "A {{slug}} slug ya existe", - "STATUS" => "Estado", - "SUGGEST" => "Sugerencia", + 'SLUG' => 'Slug', + 'SLUG_CONDITION' => 'Slug/Condiciones', + 'SLUG_IN_USE' => 'A {{slug}} slug ya existe', + 'STATUS' => 'Estado', + 'SUGGEST' => 'Sugerencia', - "UNKNOWN" => "Desconocido", + 'UNKNOWN' => 'Desconocido', // Actions words - "ACTIONS" => "Acciones", - "ACTIVATE" => "Activar", - "ACTIVE" => "Activo", - "ADD" => "Añadir", - "CANCEL" => "Cancelar", - "CONFIRM" => "Confirmar", - "CREATE" => "Crear", - "DELETE" => "Eliminar", - "DELETE_CONFIRM" => "¿Estás seguro que quieres eliminar esto?", - "DELETE_CONFIRM_YES" => "Sí, borrar", - "DELETE_CONFIRM_NAMED" => "¿Seguro que quieres eliminar {{name}}?", - "DELETE_CONFIRM_YES_NAMED" => "Sí, eliminar {{nombre}}", - "DELETE_CANNOT_UNDONE" => "Esta acción no se puede deshacer.", - "DELETE_NAMED" => "Eliminar {{name}}", - "DENY" => "Negar", - "DISABLE" => "Inhabilitar", - "DISABLED" => "Deshabilidato", - "EDIT" => "Editar", - "ENABLE" => "Habilitar", - "ENABLED" => "Habilitado", - "OVERRIDE" => "Anular", - "RESET" => "Reiniciar", - "SAVE" => "Guardar", - "SEARCH" => "Buscar", - "SORT" => "Ordenar", - "SUBMIT" => "Enviar", - "PRINT" => "Imprimir", - "REMOVE" => "Remover", - "UNACTIVATED" => "Desactivado", - "UPDATE" => "Actualizar", - "YES" => "Sí", - "NO" => "No", - "OPTIONAL" => "Opcional", + 'ACTIONS' => 'Acciones', + 'ACTIVATE' => 'Activar', + 'ACTIVE' => 'Activo', + 'ADD' => 'Añadir', + 'CANCEL' => 'Cancelar', + 'CONFIRM' => 'Confirmar', + 'CREATE' => 'Crear', + 'DELETE' => 'Eliminar', + 'DELETE_CONFIRM' => '¿Estás seguro que quieres eliminar esto?', + 'DELETE_CONFIRM_YES' => 'Sí, borrar', + 'DELETE_CONFIRM_NAMED' => '¿Seguro que quieres eliminar {{name}}?', + 'DELETE_CONFIRM_YES_NAMED' => 'Sí, eliminar {{nombre}}', + 'DELETE_CANNOT_UNDONE' => 'Esta acción no se puede deshacer.', + 'DELETE_NAMED' => 'Eliminar {{name}}', + 'DENY' => 'Negar', + 'DISABLE' => 'Inhabilitar', + 'DISABLED' => 'Deshabilidato', + 'EDIT' => 'Editar', + 'ENABLE' => 'Habilitar', + 'ENABLED' => 'Habilitado', + 'OVERRIDE' => 'Anular', + 'RESET' => 'Reiniciar', + 'SAVE' => 'Guardar', + 'SEARCH' => 'Buscar', + 'SORT' => 'Ordenar', + 'SUBMIT' => 'Enviar', + 'PRINT' => 'Imprimir', + 'REMOVE' => 'Remover', + 'UNACTIVATED' => 'Desactivado', + 'UPDATE' => 'Actualizar', + 'YES' => 'Sí', + 'NO' => 'No', + 'OPTIONAL' => 'Opcional', // Misc. - "BUILT_WITH_UF" => "Construido con UserFrosting ", - "ADMINLTE_THEME_BY" => "Theme by Almsaeed Studio. All rights reserved" + 'BUILT_WITH_UF' => 'Construido con UserFrosting ', + 'ADMINLTE_THEME_BY' => 'Theme by Almsaeed Studio. All rights reserved' ]; diff --git a/app/sprinkles/core/locale/es_ES/validate.php b/app/sprinkles/core/locale/es_ES/validate.php index d2e6024be..b8635ae45 100755 --- a/app/sprinkles/core/locale/es_ES/validate.php +++ b/app/sprinkles/core/locale/es_ES/validate.php @@ -4,32 +4,32 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Spanish message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\es_ES * @author rafa31gz */ - return [ - "VALIDATE" => [ - "ARRAY" => "Los valores de {{label}} deben estar en una matriz.", - "BOOLEAN" => "El valor de {{label}} debe ser '0' o '1'.", - "INTEGER" => "El valor de {{label}} debe ser un entero.", - "NUMERIC" => "El valor de {{label}} debe ser sólo números.", - "INVALID_EMAIL" => "Dirección de correo electrónico no válida.", - "LENGTH_RANGE" => "{{label}} debe tener entre {{min}} y {{max}} caracteres de longitud.", - "MAX_LENGTH" => "{{label}} debe tener un máximo de {{max}} caracteres de longitud.", - "MIN_LENGTH" => "{{label}} debe tener un mínimo de {{min}} caracteres de longitud.", - "NO_LEAD_WS" => "El valor de {{label}} no puede comenzar con espacios, pestañas u otros espacios en blanco.", - "NO_TRAIL_WS" => "El valor de {{label}} no puede finalizar con espacios, pestañas u otros espacios en blanco.", - "RANGE" => "El valor de {{label}} debe estar entre {{min}} y {{max}}.", - "REQUIRED" => "Especifica un valor para {{label}} .", - "PHONE" => "El número proporcionado para el télefono es inválido.", - "SPRUNJE" => [ - "BAD_FILTER" => " {{name}} no es un filtro válido para este Sprunje.", - "BAD_LIST" => " {{name}} no es una lista válida para este Sprunje.", - "BAD_SORT" => "{{name}} no es un campo de clasificación válido para este Sprunje." + 'VALIDATE' => [ + 'ARRAY' => 'Los valores de {{label}} deben estar en una matriz.', + 'BOOLEAN' => "El valor de {{label}} debe ser '0' o '1'.", + 'INTEGER' => 'El valor de {{label}} debe ser un entero.', + 'NUMERIC' => 'El valor de {{label}} debe ser sólo números.', + 'INVALID_EMAIL' => 'Dirección de correo electrónico no válida.', + 'LENGTH_RANGE' => '{{label}} debe tener entre {{min}} y {{max}} caracteres de longitud.', + 'MAX_LENGTH' => '{{label}} debe tener un máximo de {{max}} caracteres de longitud.', + 'MIN_LENGTH' => '{{label}} debe tener un mínimo de {{min}} caracteres de longitud.', + 'NO_LEAD_WS' => 'El valor de {{label}} no puede comenzar con espacios, pestañas u otros espacios en blanco.', + 'NO_TRAIL_WS' => 'El valor de {{label}} no puede finalizar con espacios, pestañas u otros espacios en blanco.', + 'RANGE' => 'El valor de {{label}} debe estar entre {{min}} y {{max}}.', + 'REQUIRED' => 'Especifica un valor para {{label}} .', + 'PHONE' => 'El número proporcionado para el télefono es inválido.', + 'SPRUNJE' => [ + 'BAD_FILTER' => ' {{name}} no es un filtro válido para este Sprunje.', + 'BAD_LIST' => ' {{name}} no es una lista válida para este Sprunje.', + 'BAD_SORT' => '{{name}} no es un campo de clasificación válido para este Sprunje.' ] ] ]; diff --git a/app/sprinkles/core/locale/fa/errors.php b/app/sprinkles/core/locale/fa/errors.php index 77bfe4f8d..e28f1c3e9 100644 --- a/app/sprinkles/core/locale/fa/errors.php +++ b/app/sprinkles/core/locale/fa/errors.php @@ -5,48 +5,48 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Standard Farsi/Persian message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\fa * @author aminakbari */ - return [ - "ERROR" => [ - "@TRANSLATION" => "خطا", + 'ERROR' => [ + '@TRANSLATION' => 'خطا', - "400" => [ - "TITLE" => "خطا 400: درخواست بد", - "DESCRIPTION" => "احتمالا تقصیر شما نیست.", + '400' => [ + 'TITLE' => 'خطا 400: درخواست بد', + 'DESCRIPTION' => 'احتمالا تقصیر شما نیست.', ], - "404" => [ - "TITLE" => "خطا 404: صفحه یافت نشد", - "DESCRIPTION" => "به نظر نمیرسد چیزی را که دنبالش هستید پیدا کنیم.", - "DETAIL" => "ما سعی کردیم صفحه شما را پیدا کنیم...", - "EXPLAIN" => "ما نتوانستیم صفحه ی مورد نظر شما را پیدا کنیم.", - "RETURN" => 'در هر حال، اینجا کلیک کنید تا به صفحه اصلی بازگردید.' + '404' => [ + 'TITLE' => 'خطا 404: صفحه یافت نشد', + 'DESCRIPTION' => 'به نظر نمیرسد چیزی را که دنبالش هستید پیدا کنیم.', + 'DETAIL' => 'ما سعی کردیم صفحه شما را پیدا کنیم...', + 'EXPLAIN' => 'ما نتوانستیم صفحه ی مورد نظر شما را پیدا کنیم.', + 'RETURN' => 'در هر حال، اینجا کلیک کنید تا به صفحه اصلی بازگردید.' ], - "CONFIG" => [ - "TITLE" => "خطای تنظیمات یوزرفروستینگ!", - "DESCRIPTION" => "برخی از الزامات پیکربندی یوزرفروستینگ به نتیجه نرسید.", - "DETAIL" => "خطایی پیش آمد.", - "RETURN" => 'لطفا خطاهای زیر را اصلاح کنید و سپس مجددا بارگذاری نمایید.' + 'CONFIG' => [ + 'TITLE' => 'خطای تنظیمات یوزرفروستینگ!', + 'DESCRIPTION' => 'برخی از الزامات پیکربندی یوزرفروستینگ به نتیجه نرسید.', + 'DETAIL' => 'خطایی پیش آمد.', + 'RETURN' => 'لطفا خطاهای زیر را اصلاح کنید و سپس مجددا بارگذاری نمایید.' ], - "DESCRIPTION" => "ما یک اختلال بزرگ در سیستم احساس کردیم.", - "DETAIL" => "این چیزی است که ما دریافت کردیم", + 'DESCRIPTION' => 'ما یک اختلال بزرگ در سیستم احساس کردیم.', + 'DETAIL' => 'این چیزی است که ما دریافت کردیم', + + 'ENCOUNTERED' => 'خطایی ویژه. نمیدانیم مشکل چیست.', - "ENCOUNTERED" => "خطایی ویژه. نمیدانیم مشکل چیست.", + 'MAIL' => 'خطا در ارسال ایمیل. لطفا با مدیر سیستم تماس برقرار کنید. لطفا لاگ را بررسی کنید.', - "MAIL" => "خطا در ارسال ایمیل. لطفا با مدیر سیستم تماس برقرار کنید. لطفا لاگ را بررسی کنید.", - - "RETURN" => 'اینجا کلیک تا به صفحه اصلی بازگردید.', + 'RETURN' => 'اینجا کلیک تا به صفحه اصلی بازگردید.', - "SERVER" => "به نظر می آید که در سرور خطایی بوجود آمد. لطفا لاگ پی اچ پی و یوزرفروستینگ را چک کنید.", + 'SERVER' => 'به نظر می آید که در سرور خطایی بوجود آمد. لطفا لاگ پی اچ پی و یوزرفروستینگ را چک کنید.', - "TITLE" => "اختلالی پدید آمد." + 'TITLE' => 'اختلالی پدید آمد.' ] ]; diff --git a/app/sprinkles/core/locale/fa/messages.php b/app/sprinkles/core/locale/fa/messages.php index 2832b6ddf..9c8c7638f 100644 --- a/app/sprinkles/core/locale/fa/messages.php +++ b/app/sprinkles/core/locale/fa/messages.php @@ -5,106 +5,106 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Standard Farsi/Persian message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\fa * @author aminakbari */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "درباره", + 'ABOUT' => 'درباره', - "CAPTCHA" => [ - "@TRANSLATION" => "کد امنیتی", - "FAIL" => "کد امنیتی درست نیست", - "SPECIFY" => "کد امنیتی را وارد کنید", - "VERIFY" => "کد امنیتی را بررسی کنید" + 'CAPTCHA' => [ + '@TRANSLATION' => 'کد امنیتی', + 'FAIL' => 'کد امنیتی درست نیست', + 'SPECIFY' => 'کد امنیتی را وارد کنید', + 'VERIFY' => 'کد امنیتی را بررسی کنید' ], - "CSRF_MISSING" => "سی اس آر اف توکن یافت نشد. لطفا صفحه را از نو بارگذاری کرده و دوباره تلاش کنید.", + 'CSRF_MISSING' => 'سی اس آر اف توکن یافت نشد. لطفا صفحه را از نو بارگذاری کرده و دوباره تلاش کنید.', - "DB_INVALID" => "خطا در اتصال به پایگاه داده ها. لطفا لاگ پی اچ پی را چک کنید.", - "DESCRIPTION" => "توضیحات", - "DOWNLOAD" => [ - "@TRANSLATION" => "دانلود", - "CSV" => "دانلود سی اس وی" + 'DB_INVALID' => 'خطا در اتصال به پایگاه داده ها. لطفا لاگ پی اچ پی را چک کنید.', + 'DESCRIPTION' => 'توضیحات', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'دانلود', + 'CSV' => 'دانلود سی اس وی' ], - "EMAIL" => [ - "@TRANSLATION" => "ایمیل", - "YOUR" => "آدرس ایمیل" + 'EMAIL' => [ + '@TRANSLATION' => 'ایمیل', + 'YOUR' => 'آدرس ایمیل' ], - "HOME" => "خانه", + 'HOME' => 'خانه', - "LEGAL" => "سیاست حقوقی", + 'LEGAL' => 'سیاست حقوقی', - "LOCALE" => [ - "@TRANSLATION" => "زبان" + 'LOCALE' => [ + '@TRANSLATION' => 'زبان' ], - "NAME" => "نام", - "NAVIGATION" => "جهت یابی", - "NO_RESULTS" => "با عرض پوزش، چیزی یافت نشد.", + 'NAME' => 'نام', + 'NAVIGATION' => 'جهت یابی', + 'NO_RESULTS' => 'با عرض پوزش، چیزی یافت نشد.', - "PAGINATION" => [ - "GOTO" => "پرش به صفحه", - "SHOW" => "نمایش", + 'PAGINATION' => [ + 'GOTO' => 'پرش به صفحه', + 'SHOW' => 'نمایش', // Paginator // possible variables: {size}, {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} // also {page:input} & {startRow:input} will add a modifiable input in place of the value - "OUTPUT" => "{startRow} تا {endRow} از {filteredRows} ({totalRows})" + 'OUTPUT' => '{startRow} تا {endRow} از {filteredRows} ({totalRows})' ], - "PRIVACY" => "سیاست حفظ حریم خصوصی", + 'PRIVACY' => 'سیاست حفظ حریم خصوصی', - "SLUG" => "اسلاگ", - "SLUG_CONDITION" => "اسلاگ/شرایط", - "SLUG_IN_USE" => "{{slug}} وجود دارد", - "STATUS" => "وضعیت", - "SUGGEST" => "پیشنهاد", + 'SLUG' => 'اسلاگ', + 'SLUG_CONDITION' => 'اسلاگ/شرایط', + 'SLUG_IN_USE' => '{{slug}} وجود دارد', + 'STATUS' => 'وضعیت', + 'SUGGEST' => 'پیشنهاد', - "UNKNOWN" => "ناشناخته", + 'UNKNOWN' => 'ناشناخته', // Actions words - "ACTIONS" => "اقدام ها", - "ACTIVATE" => "فعال سازی", - "ACTIVE" => "فعال", - "ADD" => "اضافه کردن", - "CANCEL" => "لغو", - "CONFIRM" => "تایید", - "CREATE" => "اضافه کردن", - "DELETE" => "حذف", - "DELETE_CONFIRM" => "آیا مطمئن هستید که میخواهید این را حذف کنید؟", - "DELETE_CONFIRM_YES" => "بله، حذف شود", - "DELETE_CONFIRM_NAMED" => "اطمینان دارید که میخواهید {{name}} را حذف کنید؟", - "DELETE_CONFIRM_YES_NAMED" => "بله، {{name}} حذف شود", - "DELETE_CANNOT_UNDONE" => "این عملیات قابل بازگشت نیست.", - "DELETE_NAMED" => "{{name}} حذف شود", - "DENY" => "انکار", - "DISABLE" => "غیر فعال", - "DISABLED" => "غیر فعال", - "EDIT" => "ویرایش", - "ENABLE" => "فعال", - "ENABLED" => "فعال", - "OVERRIDE" => "تغییر", - "RESET" => "تنظیم مجدد", - "SAVE" => "ذخیره", - "SEARCH" => "جست و جو", - "SORT" => "مرتب سازی", - "SUBMIT" => "ارسال", - "PRINT" => "چاپ", - "REMOVE" => "حذف", - "UNACTIVATED" => "غیر فعال", - "UPDATE" => "به روز رسانی", - "YES" => "بله", - "NO" => "خیر", - "OPTIONAL" => "اختیاری", + 'ACTIONS' => 'اقدام ها', + 'ACTIVATE' => 'فعال سازی', + 'ACTIVE' => 'فعال', + 'ADD' => 'اضافه کردن', + 'CANCEL' => 'لغو', + 'CONFIRM' => 'تایید', + 'CREATE' => 'اضافه کردن', + 'DELETE' => 'حذف', + 'DELETE_CONFIRM' => 'آیا مطمئن هستید که میخواهید این را حذف کنید؟', + 'DELETE_CONFIRM_YES' => 'بله، حذف شود', + 'DELETE_CONFIRM_NAMED' => 'اطمینان دارید که میخواهید {{name}} را حذف کنید؟', + 'DELETE_CONFIRM_YES_NAMED' => 'بله، {{name}} حذف شود', + 'DELETE_CANNOT_UNDONE' => 'این عملیات قابل بازگشت نیست.', + 'DELETE_NAMED' => '{{name}} حذف شود', + 'DENY' => 'انکار', + 'DISABLE' => 'غیر فعال', + 'DISABLED' => 'غیر فعال', + 'EDIT' => 'ویرایش', + 'ENABLE' => 'فعال', + 'ENABLED' => 'فعال', + 'OVERRIDE' => 'تغییر', + 'RESET' => 'تنظیم مجدد', + 'SAVE' => 'ذخیره', + 'SEARCH' => 'جست و جو', + 'SORT' => 'مرتب سازی', + 'SUBMIT' => 'ارسال', + 'PRINT' => 'چاپ', + 'REMOVE' => 'حذف', + 'UNACTIVATED' => 'غیر فعال', + 'UPDATE' => 'به روز رسانی', + 'YES' => 'بله', + 'NO' => 'خیر', + 'OPTIONAL' => 'اختیاری', // Misc. - "BUILT_WITH_UF" => "ساخته شده با یوزرفراستینگ", - "ADMINLTE_THEME_BY" => "قالب از Almsaeed Studio. تمامی حقوق محفوظ است" + 'BUILT_WITH_UF' => 'ساخته شده با یوزرفراستینگ', + 'ADMINLTE_THEME_BY' => 'قالب از Almsaeed Studio. تمامی حقوق محفوظ است' ]; diff --git a/app/sprinkles/core/locale/fa/validate.php b/app/sprinkles/core/locale/fa/validate.php index 54d7afe4b..026ebd18f 100644 --- a/app/sprinkles/core/locale/fa/validate.php +++ b/app/sprinkles/core/locale/fa/validate.php @@ -5,27 +5,27 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Standard Farsi/Persian message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\fa * @author aminakbari */ - return [ - "VALIDATE" => [ - "ARRAY" => "مقادیر {{label}} باید از یک آرایه باشند.", - "BOOLEAN" => "مقدار {{label}} باید 1 یا 0 باشد.", - "INTEGER" => "مقدار {{label}} باید یک عدد اینتجر باشد.", - "INVALID_EMAIL" => "آدرس پست الکترونیکی صحیح نیست.", - "LENGTH_RANGE" => "{{label}} باید بین {{min}} و {{max}} حرف باشد.", - "NO_LEAD_WS" => "مقدار {{label}} نباید با فاصله شروع شود.", - "NO_TRAIL_WS" => "مقدار {{label}} نباید با فاصله تمام شود.", - "REQUIRED" => "لطفا برای {{label}} مقداری تعیین کنید.", - "SPRUNJE" => [ - "BAD_FILTER" => "{{name}} فیلتر صحیحی نیست.", - "BAD_LIST" => "{{name}} لیست صحیحی نیست.", - "BAD_SORT" => "{{name}} فیلد مرتب سازی صحیحی نیست." + 'VALIDATE' => [ + 'ARRAY' => 'مقادیر {{label}} باید از یک آرایه باشند.', + 'BOOLEAN' => 'مقدار {{label}} باید 1 یا 0 باشد.', + 'INTEGER' => 'مقدار {{label}} باید یک عدد اینتجر باشد.', + 'INVALID_EMAIL' => 'آدرس پست الکترونیکی صحیح نیست.', + 'LENGTH_RANGE' => '{{label}} باید بین {{min}} و {{max}} حرف باشد.', + 'NO_LEAD_WS' => 'مقدار {{label}} نباید با فاصله شروع شود.', + 'NO_TRAIL_WS' => 'مقدار {{label}} نباید با فاصله تمام شود.', + 'REQUIRED' => 'لطفا برای {{label}} مقداری تعیین کنید.', + 'SPRUNJE' => [ + 'BAD_FILTER' => '{{name}} فیلتر صحیحی نیست.', + 'BAD_LIST' => '{{name}} لیست صحیحی نیست.', + 'BAD_SORT' => '{{name}} فیلد مرتب سازی صحیحی نیست.' ] ] ]; diff --git a/app/sprinkles/core/locale/fr_FR/errors.php b/app/sprinkles/core/locale/fr_FR/errors.php index 570a676b2..90e826de0 100644 --- a/app/sprinkles/core/locale/fr_FR/errors.php +++ b/app/sprinkles/core/locale/fr_FR/errors.php @@ -4,48 +4,48 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * French message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\fr * @author Louis Charette */ - return [ - "ERROR" => [ - "@TRANSLATION" => "Erreur", + 'ERROR' => [ + '@TRANSLATION' => 'Erreur', - "400" => [ - "TITLE" => "Erreur 400: Mauvaise requête", - "DESCRIPTION" => "Ce n'est probablement pas de votre faute.", + '400' => [ + 'TITLE' => 'Erreur 400: Mauvaise requête', + 'DESCRIPTION' => "Ce n'est probablement pas de votre faute.", ], - "404" => [ - "TITLE" => "Erreur 404: Page introuvable", - "DESCRIPTION" => "Nous ne pouvons trouver ce que vous cherchez.", - "DETAIL" => "Nous avons tout tenté...", - "EXPLAIN" => "Nous ne pouvons trouver la page que vous cherchez.", - "RETURN" => 'Cliquez ici pour retourner à la page d\'accueil.' + '404' => [ + 'TITLE' => 'Erreur 404: Page introuvable', + 'DESCRIPTION' => 'Nous ne pouvons trouver ce que vous cherchez.', + 'DETAIL' => 'Nous avons tout tenté...', + 'EXPLAIN' => 'Nous ne pouvons trouver la page que vous cherchez.', + 'RETURN' => 'Cliquez ici pour retourner à la page d\'accueil.' ], - "CONFIG" => [ - "TITLE" => "Problème de configuration UserFrosting!", - "DESCRIPTION" => "Les exigences de configuration de UserFrosting n'ont pas été satisfaites.", - "DETAIL" => "Quelque chose cloche ici...", - "RETURN" => 'Corrigez les erreurs suivantes, ensuite recharger la page.' + 'CONFIG' => [ + 'TITLE' => 'Problème de configuration UserFrosting!', + 'DESCRIPTION' => "Les exigences de configuration de UserFrosting n'ont pas été satisfaites.", + 'DETAIL' => 'Quelque chose cloche ici...', + 'RETURN' => 'Corrigez les erreurs suivantes, ensuite recharger la page.' ], - "DESCRIPTION" => "Nous avons ressenti un grand bouleversement de la Force.", - "DETAIL" => "Voici les détails :", + 'DESCRIPTION' => 'Nous avons ressenti un grand bouleversement de la Force.', + 'DETAIL' => 'Voici les détails :', - "ENCOUNTERED" => "D'oh! Quelque chose s'est produit. Aucune idée c'est quoi.", + 'ENCOUNTERED' => "D'oh! Quelque chose s'est produit. Aucune idée c'est quoi.", - "MAIL" => "Erreur fatale lors de l'envoie du courriel. Contactez votre administrateur. Si vous être administrateur, consultez les logs.", + 'MAIL' => "Erreur fatale lors de l'envoie du courriel. Contactez votre administrateur. Si vous être administrateur, consultez les logs.", - "RETURN" => 'Cliquez ici pour retourner à la page d\'accueil.', + 'RETURN' => 'Cliquez ici pour retourner à la page d\'accueil.', - "SERVER" => "Oops, il semblerait que le serveur a gaffé. Si vous êtes administrateur, s-v-p vérifier les logs d'erreurs PHP ou ceux de UserFrosting.", + 'SERVER' => "Oops, il semblerait que le serveur a gaffé. Si vous êtes administrateur, s-v-p vérifier les logs d'erreurs PHP ou ceux de UserFrosting.", - "TITLE" => "Bouleversement de la Force" + 'TITLE' => 'Bouleversement de la Force' ] ]; diff --git a/app/sprinkles/core/locale/fr_FR/messages.php b/app/sprinkles/core/locale/fr_FR/messages.php index 90718421b..62176e595 100644 --- a/app/sprinkles/core/locale/fr_FR/messages.php +++ b/app/sprinkles/core/locale/fr_FR/messages.php @@ -4,102 +4,102 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * French message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\fr * @author Louis Charette */ - return [ - "@PLURAL_RULE" => 2, + '@PLURAL_RULE' => 2, - "ABOUT" => "À propos", + 'ABOUT' => 'À propos', - "CAPTCHA" => [ - "@TRANSLATE" => "Captcha", - "VERIFY" => "Vérification du captcha", - "SPECIFY" => "Entrer la valeur du captcha", - "FAIL" => "La valeur du captcha n'a pas été entrée correctement." + 'CAPTCHA' => [ + '@TRANSLATE' => 'Captcha', + 'VERIFY' => 'Vérification du captcha', + 'SPECIFY' => 'Entrer la valeur du captcha', + 'FAIL' => "La valeur du captcha n'a pas été entrée correctement." ], - "CSRF_MISSING" => "Jeton CSRF manquant. Essayez de rafraîchir la page et de soumettre de nouveau?", + 'CSRF_MISSING' => 'Jeton CSRF manquant. Essayez de rafraîchir la page et de soumettre de nouveau?', - "DB_INVALID" => "Impossible de se connecter à la base de données. Si vous êtes un administrateur, vérifiez votre journal d'erreurs.", - "DESCRIPTION" => "Description", - "DOWNLOAD" => [ - "@TRANSLATION" => "Télécharger", - "CSV" => "Télécharger CSV" + 'DB_INVALID' => "Impossible de se connecter à la base de données. Si vous êtes un administrateur, vérifiez votre journal d'erreurs.", + 'DESCRIPTION' => 'Description', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'Télécharger', + 'CSV' => 'Télécharger CSV' ], - "EMAIL" => [ - "@TRANSLATION" => "Email", - "YOUR" => "Votre adresse email" + 'EMAIL' => [ + '@TRANSLATION' => 'Email', + 'YOUR' => 'Votre adresse email' ], - "HOME" => "Accueil", + 'HOME' => 'Accueil', - "LEGAL" => "Politique légale", + 'LEGAL' => 'Politique légale', - "LOCALE" => [ - "@TRANSLATION" => "Langue" + 'LOCALE' => [ + '@TRANSLATION' => 'Langue' ], - "NAME" => "Nom", - "NAVIGATION" => "Menu principal", - "NO_RESULTS" => "Aucun résultat trouvé.", + 'NAME' => 'Nom', + 'NAVIGATION' => 'Menu principal', + 'NO_RESULTS' => 'Aucun résultat trouvé.', - "PAGINATION" => [ - "GOTO" => "Aller à la page", - "SHOW" => "Afficher", - "OUTPUT" => "{startRow} à {endRow} de {filteredRows} ({totalRows})" + 'PAGINATION' => [ + 'GOTO' => 'Aller à la page', + 'SHOW' => 'Afficher', + 'OUTPUT' => '{startRow} à {endRow} de {filteredRows} ({totalRows})' ], - "PRIVACY" => "Politique de confidentialité", + 'PRIVACY' => 'Politique de confidentialité', - "SLUG" => "Jeton", - "SLUG_CONDITION" => "Jeton/Conditions", - "SLUG_IN_USE" => "Un jeton {{slug}} existe déjà", - "STATUS" => "Statut", - "SUGGEST" => "Suggérer", + 'SLUG' => 'Jeton', + 'SLUG_CONDITION' => 'Jeton/Conditions', + 'SLUG_IN_USE' => 'Un jeton {{slug}} existe déjà', + 'STATUS' => 'Statut', + 'SUGGEST' => 'Suggérer', - "UNKNOWN" => "Inconnu", + 'UNKNOWN' => 'Inconnu', // Actions words - "ACTIONS" => "Actions", - "ACTIVATE" => "Autoriser", - "ACTIVE" => "Activé", - "ADD" => "Ajouter", - "CANCEL" => "Annuler", - "CONFIRM" => "Confirmer", - "CREATE" => "Créer", - "DELETE" => "Supprimer", - "DELETE_CONFIRM" => "Êtes-vous sûr de vouloir supprimer ceci?", - "DELETE_CONFIRM_YES" => "Oui, supprimer", - "DELETE_CONFIRM_NAMED" => "Êtes-vous sûr de vouloir supprimer {{name}}?", - "DELETE_CONFIRM_YES_NAMED" => "Oui, supprimer {{name}}", - "DELETE_CANNOT_UNDONE" => "Cette action ne peut être annulée.", //This action cannot be undone - "DELETE_NAMED" => "Supprimer {{name}}", - "DENY" => "Refuser", - "DISABLE" => "Désactiver", - "DISABLED" => "Désactivé", - "EDIT" => "Modifier", - "ENABLE" => "Activer", - "ENABLED" => "Activé", - "OVERRIDE" => "Forcer", - "RESET" => "Réinitialiser", - "SAVE" => "Sauvegarder", - "SEARCH" => "Rechercher", - "SORT" => "Trier", - "SUBMIT" => "Envoyer", - "PRINT" => "Imprimer", - "REMOVE" => "Supprimer", - "UNACTIVATED" => "Non activé", - "UPDATE" => "Mettre à jour", - "YES" => "Oui", - "NO" => "Non", - "OPTIONAL" => "Facultatif", + 'ACTIONS' => 'Actions', + 'ACTIVATE' => 'Autoriser', + 'ACTIVE' => 'Activé', + 'ADD' => 'Ajouter', + 'CANCEL' => 'Annuler', + 'CONFIRM' => 'Confirmer', + 'CREATE' => 'Créer', + 'DELETE' => 'Supprimer', + 'DELETE_CONFIRM' => 'Êtes-vous sûr de vouloir supprimer ceci?', + 'DELETE_CONFIRM_YES' => 'Oui, supprimer', + 'DELETE_CONFIRM_NAMED' => 'Êtes-vous sûr de vouloir supprimer {{name}}?', + 'DELETE_CONFIRM_YES_NAMED' => 'Oui, supprimer {{name}}', + 'DELETE_CANNOT_UNDONE' => 'Cette action ne peut être annulée.', //This action cannot be undone + 'DELETE_NAMED' => 'Supprimer {{name}}', + 'DENY' => 'Refuser', + 'DISABLE' => 'Désactiver', + 'DISABLED' => 'Désactivé', + 'EDIT' => 'Modifier', + 'ENABLE' => 'Activer', + 'ENABLED' => 'Activé', + 'OVERRIDE' => 'Forcer', + 'RESET' => 'Réinitialiser', + 'SAVE' => 'Sauvegarder', + 'SEARCH' => 'Rechercher', + 'SORT' => 'Trier', + 'SUBMIT' => 'Envoyer', + 'PRINT' => 'Imprimer', + 'REMOVE' => 'Supprimer', + 'UNACTIVATED' => 'Non activé', + 'UPDATE' => 'Mettre à jour', + 'YES' => 'Oui', + 'NO' => 'Non', + 'OPTIONAL' => 'Facultatif', // Misc. - "BUILT_WITH_UF" => "Créé avec UserFrosting", - "ADMINLTE_THEME_BY" => "Thème par Almsaeed Studio. Tous droits réservés" + 'BUILT_WITH_UF' => 'Créé avec UserFrosting', + 'ADMINLTE_THEME_BY' => 'Thème par Almsaeed Studio. Tous droits réservés' ]; diff --git a/app/sprinkles/core/locale/fr_FR/validate.php b/app/sprinkles/core/locale/fr_FR/validate.php index 0c8dd2886..3c9bf8b9c 100644 --- a/app/sprinkles/core/locale/fr_FR/validate.php +++ b/app/sprinkles/core/locale/fr_FR/validate.php @@ -4,30 +4,30 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * French message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\fr * @author Louis Charette */ - return [ - "VALIDATE" => [ - "ARRAY" => "Les valeurs de {{label}} doivent être dans un tableau.", - "BOOLEAN" => "La valeur de {{label}} doit être '0' ou '1'.", - "INTEGER" => "La valeur de {{label}} doit être un nombre entier.", - "INVALID_EMAIL" => "Addresse email invalide.", - "LENGTH_RANGE" => "La valeur de {{label}} doit faire entre {{min}} et {{max}} caractères.", - "MAX_LENGTH" => "La valeur de {{label}} doit être d'un maximum de {{max}} caractères.", - "MIN_LENGTH" => "La valeur de {{label}} doit être d'un minimum de {{min}} caractères.", - "NO_LEAD_WS" => "La valeur de {{label}} ne peut pas commencer par des espaces, des tabulations ou d'autres caractères invisibles", - "NO_TRAIL_WS" => "La valeur de {{label}} ne peut pas se terminer par des espaces, des tabulations ou d'autres caractères invisibles", - "RANGE" => "Le champ {{label}} doit être une valeur entre {{min}} et {{max}}.", - "REQUIRED" => "Le champ {{label}} doit être rempli.", - "SPRUNJE" => [ - "BAD_FILTER" => "{{name}} ne peut pas être utilisé pour filtrer ce Sprunje.", - "BAD_LIST" => "{{name}} is not a valid list for this Sprunje.", - "BAD_SORT" => "{{name}} ne peut pas être utilisé pour trier Sprunje." + 'VALIDATE' => [ + 'ARRAY' => 'Les valeurs de {{label}} doivent être dans un tableau.', + 'BOOLEAN' => "La valeur de {{label}} doit être '0' ou '1'.", + 'INTEGER' => 'La valeur de {{label}} doit être un nombre entier.', + 'INVALID_EMAIL' => 'Addresse email invalide.', + 'LENGTH_RANGE' => 'La valeur de {{label}} doit faire entre {{min}} et {{max}} caractères.', + 'MAX_LENGTH' => "La valeur de {{label}} doit être d'un maximum de {{max}} caractères.", + 'MIN_LENGTH' => "La valeur de {{label}} doit être d'un minimum de {{min}} caractères.", + 'NO_LEAD_WS' => "La valeur de {{label}} ne peut pas commencer par des espaces, des tabulations ou d'autres caractères invisibles", + 'NO_TRAIL_WS' => "La valeur de {{label}} ne peut pas se terminer par des espaces, des tabulations ou d'autres caractères invisibles", + 'RANGE' => 'Le champ {{label}} doit être une valeur entre {{min}} et {{max}}.', + 'REQUIRED' => 'Le champ {{label}} doit être rempli.', + 'SPRUNJE' => [ + 'BAD_FILTER' => '{{name}} ne peut pas être utilisé pour filtrer ce Sprunje.', + 'BAD_LIST' => '{{name}} is not a valid list for this Sprunje.', + 'BAD_SORT' => '{{name}} ne peut pas être utilisé pour trier Sprunje.' ] ] ]; diff --git a/app/sprinkles/core/locale/it_IT/errors.php b/app/sprinkles/core/locale/it_IT/errors.php index ed3df0690..bc015b245 100644 --- a/app/sprinkles/core/locale/it_IT/errors.php +++ b/app/sprinkles/core/locale/it_IT/errors.php @@ -4,50 +4,50 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Italian message token translations for the 'core' sprinkle. * This translation was generated with Google translate. Please contribute if you are a native speaker. * - * @package userfrosting\i18n\it * @author Alexander Weissman * @author Pietro Marangon (@Pe46dro) */ - return [ - "ERROR" => [ - "@TRANSLATION" => "Errore", + 'ERROR' => [ + '@TRANSLATION' => 'Errore', - "400" => [ - "TITLE" => "Errore 400: Richiesta non valida", - "DESCRIPTION" => "Siamo spiacenti per l'errore.", + '400' => [ + 'TITLE' => 'Errore 400: Richiesta non valida', + 'DESCRIPTION' => "Siamo spiacenti per l'errore.", ], - "404" => [ - "TITLE" => "Errore 404 - Pagina non trovata", - "DESCRIPTION" => "Non riusciamo a trovare quel che cerchi...", - "DETAIL" => "Abbiamo provato a trovare quello che cercavi...", - "EXPLAIN" => "Non abbiamo trovato la pagina che stavi cercando.", - "RETURN" => "Fai clic qui per tornare alla homepage." + '404' => [ + 'TITLE' => 'Errore 404 - Pagina non trovata', + 'DESCRIPTION' => 'Non riusciamo a trovare quel che cerchi...', + 'DETAIL' => 'Abbiamo provato a trovare quello che cercavi...', + 'EXPLAIN' => 'Non abbiamo trovato la pagina che stavi cercando.', + 'RETURN' => 'Fai clic qui per tornare alla homepage.' ], - "CONFIG" => [ - "TITLE" => "Problema di configurazione di UserFrosting!", - "DESCRIPTION" => "Alcuni requisiti di configurazione di UserFrosting non sono stati soddisfatti.", - "DETAIL" => "Qualcosa qui non va bene.", - "RETURN" => "Correggi i seguenti errori, quindi ricarica la pagina." + 'CONFIG' => [ + 'TITLE' => 'Problema di configurazione di UserFrosting!', + 'DESCRIPTION' => 'Alcuni requisiti di configurazione di UserFrosting non sono stati soddisfatti.', + 'DETAIL' => 'Qualcosa qui non va bene.', + 'RETURN' => 'Correggi i seguenti errori, quindi ricarica la pagina.' ], - "DESCRIPTION" => "Abbiamo notato un grande disturbo della Forza.", - "DETAIL" => "Ecco quello che sappiamo:", + 'DESCRIPTION' => 'Abbiamo notato un grande disturbo della Forza.', + 'DETAIL' => 'Ecco quello che sappiamo:', - "ENCOUNTERED" => "Uhhh... è successo qualosa. Non sappiamo cosa.", + 'ENCOUNTERED' => 'Uhhh... è successo qualosa. Non sappiamo cosa.', - "MAIL" => "Errore nell'invio della mail, contatta l'amministratore di sistema", + 'MAIL' => "Errore nell'invio della mail, contatta l'amministratore di sistema", - "RETURN" => "Fai clic qui per tornare alla homepage.", + 'RETURN' => 'Fai clic qui per tornare alla homepage.', - "SERVER" => "Sembra esserci un errore nel server. Se sei un admin, controlla i log di PHP o UserFrosting.", + 'SERVER' => 'Sembra esserci un errore nel server. Se sei un admin, controlla i log di PHP o UserFrosting.', - "TITLE" => "Disturbo della Forza" + 'TITLE' => 'Disturbo della Forza' ] ]; diff --git a/app/sprinkles/core/locale/it_IT/messages.php b/app/sprinkles/core/locale/it_IT/messages.php index 5d8d7a888..b24725cff 100644 --- a/app/sprinkles/core/locale/it_IT/messages.php +++ b/app/sprinkles/core/locale/it_IT/messages.php @@ -4,120 +4,120 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Italian message token translations for the 'core' sprinkle. * This translation was generated with Google translate. Please contribute if you are a native speaker. * - * @package userfrosting\i18n\it * @author Alexander Weissman * @author Pietro Marangon (@Pe46dro) */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "Su di noi", + 'ABOUT' => 'Su di noi', - "CAPTCHA" => [ - "@TRANSLATION" => "Captcha", - "FAIL" => "Captcha errato", - "SPECIFY" => "Inserisci il captcha", - "VERIFY" => "Verifica captcha" + 'CAPTCHA' => [ + '@TRANSLATION' => 'Captcha', + 'FAIL' => 'Captcha errato', + 'SPECIFY' => 'Inserisci il captcha', + 'VERIFY' => 'Verifica captcha' ], - "CSRF_MISSING" => "Token CSRF mancante. Prova ad aggiornare la pagina e poi invia nuovamente la richiesta.", + 'CSRF_MISSING' => 'Token CSRF mancante. Prova ad aggiornare la pagina e poi invia nuovamente la richiesta.', - "DB_INVALID" => "Impossibile connettersi al database. Se sei un amministratore, controlla il log PHP o di UserFrosting.", - "DESCRIPTION" => "Descrizione", - "DOWNLOAD" => [ - "@TRANSLATION" => "Scarica", - "CSV" => "Scarica CSV" + 'DB_INVALID' => 'Impossibile connettersi al database. Se sei un amministratore, controlla il log PHP o di UserFrosting.', + 'DESCRIPTION' => 'Descrizione', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'Scarica', + 'CSV' => 'Scarica CSV' ], - "EMAIL" => [ - "@TRANSLATION" => "Email", - "YOUR" => "La tua email" + 'EMAIL' => [ + '@TRANSLATION' => 'Email', + 'YOUR' => 'La tua email' ], - "HOME" => "Home", + 'HOME' => 'Home', - "LEGAL" => [ - "@TRANSLATION" => "Politica legale", - "DESCRIPTION" => "La nostra politica legale si applica al tuo utilizzo di questo sito e dei nostri servizi." + 'LEGAL' => [ + '@TRANSLATION' => 'Politica legale', + 'DESCRIPTION' => 'La nostra politica legale si applica al tuo utilizzo di questo sito e dei nostri servizi.' ], - "LOCALE" => [ - "@TRANSLATION" => "Lingua" + 'LOCALE' => [ + '@TRANSLATION' => 'Lingua' ], - "NAME" => "Nome", - "NAVIGATION" => "Navigazione", - "NO_RESULTS" => "Spiacenti, qui non c'è niente.", + 'NAME' => 'Nome', + 'NAVIGATION' => 'Navigazione', + 'NO_RESULTS' => "Spiacenti, qui non c'è niente.", - "PAGINATION" => [ - "GOTO" => "Vai alla pagina", - "SHOW" => "Mostra", + 'PAGINATION' => [ + 'GOTO' => 'Vai alla pagina', + 'SHOW' => 'Mostra', // Paginator // possible variables: {size}, {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} // also {page:input} & {startRow:input} will add a modifiable input in place of the value - "OUTPUT" => "{startRow} a {endRow} di {filteredRows} ({totalRows})", - "NEXT" => "Pagina successiva", - "PREVIOUS" => "Pagina precedente", - "FIRST" => "Prima pagina", - "LAST" => "Ultima pagina" + 'OUTPUT' => '{startRow} a {endRow} di {filteredRows} ({totalRows})', + 'NEXT' => 'Pagina successiva', + 'PREVIOUS' => 'Pagina precedente', + 'FIRST' => 'Prima pagina', + 'LAST' => 'Ultima pagina' ], - "PRIVACY" => [ - "@TRANSLATION" => "Politica sulla riservatezza", - "DESCRIPTION" => "La nostra politica sulla privacy descrive quali tipi di informazioni raccoglieremo da te e come le useremo." + 'PRIVACY' => [ + '@TRANSLATION' => 'Politica sulla riservatezza', + 'DESCRIPTION' => 'La nostra politica sulla privacy descrive quali tipi di informazioni raccoglieremo da te e come le useremo.' ], - "SLUG" => "Slug", - "SLUG_CONDITION" => "Slug/Condizioni", - "SLUG_IN_USE" => "Esiste già uno slug {{slug}}", - "STATUS" => "Stato", - "SUGGEST" => "Suggerisci", + 'SLUG' => 'Slug', + 'SLUG_CONDITION' => 'Slug/Condizioni', + 'SLUG_IN_USE' => 'Esiste già uno slug {{slug}}', + 'STATUS' => 'Stato', + 'SUGGEST' => 'Suggerisci', - "UNKNOWN" => "Sconosciuto", + 'UNKNOWN' => 'Sconosciuto', // Actions words - "ACTIONS" => "Azioni", - "ACTIVATE" => "Attiva", - "ACTIVE" => "Attivo", - "ADD" => "Aggiungi", - "CANCEL" => "Annulla", - "CONFIRM" => "Conferma", - "CREATE" => "Crea", - "DELETE" => "Elimina", - "DELETE_CONFIRM" => "Sei sicuro di volerlo eliminare?", - "DELETE_CONFIRM_YES" => "Sì, elimina", - "DELETE_CONFIRM_NAMED" => "Sei sicuro di voler eliminare {{name}}?", - "DELETE_CONFIRM_YES_NAMED" => "Sì, elimina {{name}}", - "DELETE_CANNOT_UNDONE" => "Questa azione non può essere annullata.", - "DELETE_NAMED" => "Elimina {{name}}", - "DENY" => "Rifiuta", - "DISABLE" => "Disabilita", - "DISABLED" => "Disabilitato", - "EDIT" => "Modifica", - "ENABLE" => "Abilita", - "ENABLED" => "Abilitato", - "OVERRIDE" => "Sovrascrivi", - "RESET" => "Azzera", - "SAVE" => "Salva", - "SEARCH" => "Cerca", - "SORT" => "Ordina", - "SUBMIT" => "Invia", - "SUCCESS" => "Successo", - "PRINT" => "Stampa", - "REMOVE" => "Rimuovi", - "UNACTIVATED" => "Disattivato", - "UPDATE" => "Aggiorna", - "YES" => "Sì", - "NO" => "No", - "OPTIONAL" => "Opzionale", + 'ACTIONS' => 'Azioni', + 'ACTIVATE' => 'Attiva', + 'ACTIVE' => 'Attivo', + 'ADD' => 'Aggiungi', + 'CANCEL' => 'Annulla', + 'CONFIRM' => 'Conferma', + 'CREATE' => 'Crea', + 'DELETE' => 'Elimina', + 'DELETE_CONFIRM' => 'Sei sicuro di volerlo eliminare?', + 'DELETE_CONFIRM_YES' => 'Sì, elimina', + 'DELETE_CONFIRM_NAMED' => 'Sei sicuro di voler eliminare {{name}}?', + 'DELETE_CONFIRM_YES_NAMED' => 'Sì, elimina {{name}}', + 'DELETE_CANNOT_UNDONE' => 'Questa azione non può essere annullata.', + 'DELETE_NAMED' => 'Elimina {{name}}', + 'DENY' => 'Rifiuta', + 'DISABLE' => 'Disabilita', + 'DISABLED' => 'Disabilitato', + 'EDIT' => 'Modifica', + 'ENABLE' => 'Abilita', + 'ENABLED' => 'Abilitato', + 'OVERRIDE' => 'Sovrascrivi', + 'RESET' => 'Azzera', + 'SAVE' => 'Salva', + 'SEARCH' => 'Cerca', + 'SORT' => 'Ordina', + 'SUBMIT' => 'Invia', + 'SUCCESS' => 'Successo', + 'PRINT' => 'Stampa', + 'REMOVE' => 'Rimuovi', + 'UNACTIVATED' => 'Disattivato', + 'UPDATE' => 'Aggiorna', + 'YES' => 'Sì', + 'NO' => 'No', + 'OPTIONAL' => 'Opzionale', // Misc. - "BUILT_WITH_UF" => "Construito con UserFrosting", - "ADMINLTE_THEME_BY" => "Tema di Almsaeed Studio. Tutti i diritti riservati", - "WELCOME_TO" => "Benvenuto su {{title}}!" + 'BUILT_WITH_UF' => 'Construito con UserFrosting', + 'ADMINLTE_THEME_BY' => 'Tema di Almsaeed Studio. Tutti i diritti riservati', + 'WELCOME_TO' => 'Benvenuto su {{title}}!' ]; diff --git a/app/sprinkles/core/locale/it_IT/validate.php b/app/sprinkles/core/locale/it_IT/validate.php index a4a02929e..cf81eff62 100644 --- a/app/sprinkles/core/locale/it_IT/validate.php +++ b/app/sprinkles/core/locale/it_IT/validate.php @@ -4,29 +4,29 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Italian message token translations for the 'core' sprinkle. * This translation was generated with Google translate. Please contribute if you are a native speaker. * - * @package userfrosting\i18n\it * @author Alexander Weissman * @author Pietro Marangon (@Pe46dro) */ - return [ - "VALIDATE" => [ - "ARRAY" => "I valori per {{label}} devono essere in un array.", - "BOOLEAN" => "Il valore per {{label}} deve essere '0' o '1'.", - "INTEGER" => "Il valore per {{label}} deve essere un numero intero.", - "INVALID_EMAIL" => "Indirizzo email non valido", - "LENGTH_RANGE" => "{{label}} deve essere compreso tra {{min}} e {{max}} caratteri di lunghezza.", - "NO_LEAD_WS" => "Il valore di {{label}} non può iniziare con spazi, tab o altri spazi vuoti.", - "NO_TRAIL_WS" => "Il valore di {{label}} non può terminare con spazi, tab o altri spazi vuoti.", - "REQUIRED" => "Il campo {{label}} deve essere specificato.", - "SPRUNJE" => [ - "BAD_FILTER" => "{{name}} non è un filtro valido per questo Sprunje.", - "BAD_LIST" => " {{name}} non è un elenco valido per questo Sprunje.", - "BAD_SORT" => "{{name}} non è un campo di ordinamento valido per questo Sprunje." + 'VALIDATE' => [ + 'ARRAY' => 'I valori per {{label}} devono essere in un array.', + 'BOOLEAN' => "Il valore per {{label}} deve essere '0' o '1'.", + 'INTEGER' => 'Il valore per {{label}} deve essere un numero intero.', + 'INVALID_EMAIL' => 'Indirizzo email non valido', + 'LENGTH_RANGE' => '{{label}} deve essere compreso tra {{min}} e {{max}} caratteri di lunghezza.', + 'NO_LEAD_WS' => 'Il valore di {{label}} non può iniziare con spazi, tab o altri spazi vuoti.', + 'NO_TRAIL_WS' => 'Il valore di {{label}} non può terminare con spazi, tab o altri spazi vuoti.', + 'REQUIRED' => 'Il campo {{label}} deve essere specificato.', + 'SPRUNJE' => [ + 'BAD_FILTER' => '{{name}} non è un filtro valido per questo Sprunje.', + 'BAD_LIST' => ' {{name}} non è un elenco valido per questo Sprunje.', + 'BAD_SORT' => '{{name}} non è un campo di ordinamento valido per questo Sprunje.' ] ] ]; diff --git a/app/sprinkles/core/locale/pt_PT/errors.php b/app/sprinkles/core/locale/pt_PT/errors.php index 2c938ec90..e127fb2ae 100644 --- a/app/sprinkles/core/locale/pt_PT/errors.php +++ b/app/sprinkles/core/locale/pt_PT/errors.php @@ -4,48 +4,48 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Portuguese message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\pt * @author Bruno Silva (brunomnsilva@gmail.com) */ - return [ - "ERROR" => [ - "@TRANSLATION" => "Erro", + 'ERROR' => [ + '@TRANSLATION' => 'Erro', - "400" => [ - "TITLE" => "Erro 400: Pedido Inválido", - "DESCRIPTION" => "Provavelmente a culpa não é sua.", + '400' => [ + 'TITLE' => 'Erro 400: Pedido Inválido', + 'DESCRIPTION' => 'Provavelmente a culpa não é sua.', ], - "404" => [ - "TITLE" => "Erro 404: Página não Encontrada", - "DESCRIPTION" => "Parece que não conseguimos encontrar a página que procura.", - "DETAIL" => "Tentámos encontrar a sua página...", - "EXPLAIN" => "Não conseguimos encontrar a página que procura.", - "RETURN" => 'De qualquer forma, clique aqui para regressar à página inicial.' + '404' => [ + 'TITLE' => 'Erro 404: Página não Encontrada', + 'DESCRIPTION' => 'Parece que não conseguimos encontrar a página que procura.', + 'DETAIL' => 'Tentámos encontrar a sua página...', + 'EXPLAIN' => 'Não conseguimos encontrar a página que procura.', + 'RETURN' => 'De qualquer forma, clique aqui para regressar à página inicial.' ], - "CONFIG" => [ - "TITLE" => "Problema de Configuração do UserFrosting!", - "DESCRIPTION" => "Alguns requisitos de configuração do UserFrosting não foram satisfeitos.", - "DETAIL" => "Algo não está bem.", - "RETURN" => 'Por favor corrija os seguintes erros, depois refresque a página.' + 'CONFIG' => [ + 'TITLE' => 'Problema de Configuração do UserFrosting!', + 'DESCRIPTION' => 'Alguns requisitos de configuração do UserFrosting não foram satisfeitos.', + 'DETAIL' => 'Algo não está bem.', + 'RETURN' => 'Por favor corrija os seguintes erros, depois refresque a página.' ], - "DESCRIPTION" => "Sentimos uma grande perturbância na Força.", - "DETAIL" => "Eis o que sabemos:", + 'DESCRIPTION' => 'Sentimos uma grande perturbância na Força.', + 'DETAIL' => 'Eis o que sabemos:', - "ENCOUNTERED" => "Uhhh...algo aconteceu. Não sabemos bem o quê.", + 'ENCOUNTERED' => 'Uhhh...algo aconteceu. Não sabemos bem o quê.', - "MAIL" => "Erro fatal ao tentar enviar email, contate o administrator do servidor. Se é administrador, por favor consulte o log de mail do UF.", + 'MAIL' => 'Erro fatal ao tentar enviar email, contate o administrator do servidor. Se é administrador, por favor consulte o log de mail do UF.', - "RETURN" => 'Clique aqui para regressar à página inicial.', + 'RETURN' => 'Clique aqui para regressar à página inicial.', - "SERVER" => "Oops, parece que o nosso servidor deu o berro. Se é um administrador, por favor consulte o log de erros PHP ou UF.", + 'SERVER' => 'Oops, parece que o nosso servidor deu o berro. Se é um administrador, por favor consulte o log de erros PHP ou UF.', - "TITLE" => "Perturbância na Força" + 'TITLE' => 'Perturbância na Força' ] ]; diff --git a/app/sprinkles/core/locale/pt_PT/messages.php b/app/sprinkles/core/locale/pt_PT/messages.php index 155bf9aa2..c2c7fe0f7 100644 --- a/app/sprinkles/core/locale/pt_PT/messages.php +++ b/app/sprinkles/core/locale/pt_PT/messages.php @@ -4,99 +4,99 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Portuguese message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\pt * @author Bruno Silva (brunomnsilva@gmail.com) */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "Acerca", + 'ABOUT' => 'Acerca', - "CAPTCHA" => [ - "@TRANSLATION" => "Captcha", - "FAIL" => "Código captcha não introduzido corretamente.", - "SPECIFY" => "Introduza o código captcha", - "VERIFY" => "Verifique o código captcha" + 'CAPTCHA' => [ + '@TRANSLATION' => 'Captcha', + 'FAIL' => 'Código captcha não introduzido corretamente.', + 'SPECIFY' => 'Introduza o código captcha', + 'VERIFY' => 'Verifique o código captcha' ], - "CSRF_MISSING" => "Token CSRF em falta. Tente refrescar a página e submeter de novo?", + 'CSRF_MISSING' => 'Token CSRF em falta. Tente refrescar a página e submeter de novo?', - "DB_INVALID" => "Não é possível estabelecer ligação com a base de dados. Se é administrador, por favor consulte o log do servidor.", - "DESCRIPTION" => "Descrição", - "DOWNLOAD" => [ - "@TRANSLATION" => "Descarregar", - "CSV" => "Descarregar CSV" + 'DB_INVALID' => 'Não é possível estabelecer ligação com a base de dados. Se é administrador, por favor consulte o log do servidor.', + 'DESCRIPTION' => 'Descrição', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'Descarregar', + 'CSV' => 'Descarregar CSV' ], - "EMAIL" => [ - "@TRANSLATION" => "Email", - "YOUR" => "O seu endereço de email" + 'EMAIL' => [ + '@TRANSLATION' => 'Email', + 'YOUR' => 'O seu endereço de email' ], - "HOME" => "Início", + 'HOME' => 'Início', - "LEGAL" => "Política Legal", + 'LEGAL' => 'Política Legal', - "LOCALE" => [ - "@TRANSLATION" => "Localização" + 'LOCALE' => [ + '@TRANSLATION' => 'Localização' ], - "NAME" => "Nome", - "NAVIGATION" => "Navegação", + 'NAME' => 'Nome', + 'NAVIGATION' => 'Navegação', - "PAGINATION" => [ - "GOTO" => "Saltar para Página", - "SHOW" => "Mostrar", - "OUTPUT" => "{startRow} to {endRow} of {filteredRows} ({totalRows})" + 'PAGINATION' => [ + 'GOTO' => 'Saltar para Página', + 'SHOW' => 'Mostrar', + 'OUTPUT' => '{startRow} to {endRow} of {filteredRows} ({totalRows})' ], - "PRIVACY" => "Política de Privacidade", + 'PRIVACY' => 'Política de Privacidade', - "SLUG" => "Slug", - "SLUG_CONDITION" => "Slug/Condições", - "STATUS" => "Estado", + 'SLUG' => 'Slug', + 'SLUG_CONDITION' => 'Slug/Condições', + 'STATUS' => 'Estado', - "UNKNOWN" => "Desconhecido", + 'UNKNOWN' => 'Desconhecido', // Actions words - "ACTIONS" => "Ações", - "ACTIVATE" => "Ativar", - "ACTIVE" => "Ativo", - "ADD" => "Adicionar", - "CANCEL" => "Cancelar", - "CONFIRM" => "Confirmar", - "CREATE" => "Criar", - "DELETE" => "Remover", - "DELETE_CONFIRM" => "Tem a certeza que deseja remover isto?", - "DELETE_CONFIRM_YES" => "Sim, remover", - "DELETE_CONFIRM_NAMED" => "Tem a certeza que deseja remover {{name}}?", - "DELETE_CONFIRM_YES_NAMED" => "Sim, remover {{name}}", - "DELETE_CANNOT_UNDONE" => "Esta ação não pode ser desfeita.", - "DELETE_NAMED" => "Remover {{name}}", - "DENY" => "Recusar", - "DISABLE" => "Desativar", - "DISABLED" => "Inativo", - "EDIT" => "Editar", - "ENABLE" => "Ativar", - "ENABLED" => "Ativo", - "OVERRIDE" => "Alterar", - "RESET" => "Apagar", - "SAVE" => "Guardar", - "SEARCH" => "Procurar", - "SORT" => "Ordenar", - "SUBMIT" => "Submeter", - "PRINT" => "Imprimir", - "REMOVE" => "Remover", - "UNACTIVATED" => "Inativo", - "UPDATE" => "Atualizar", - "YES" => "Sim", - "NO" => "Não", - "OPTIONAL" => "Opcional", + 'ACTIONS' => 'Ações', + 'ACTIVATE' => 'Ativar', + 'ACTIVE' => 'Ativo', + 'ADD' => 'Adicionar', + 'CANCEL' => 'Cancelar', + 'CONFIRM' => 'Confirmar', + 'CREATE' => 'Criar', + 'DELETE' => 'Remover', + 'DELETE_CONFIRM' => 'Tem a certeza que deseja remover isto?', + 'DELETE_CONFIRM_YES' => 'Sim, remover', + 'DELETE_CONFIRM_NAMED' => 'Tem a certeza que deseja remover {{name}}?', + 'DELETE_CONFIRM_YES_NAMED' => 'Sim, remover {{name}}', + 'DELETE_CANNOT_UNDONE' => 'Esta ação não pode ser desfeita.', + 'DELETE_NAMED' => 'Remover {{name}}', + 'DENY' => 'Recusar', + 'DISABLE' => 'Desativar', + 'DISABLED' => 'Inativo', + 'EDIT' => 'Editar', + 'ENABLE' => 'Ativar', + 'ENABLED' => 'Ativo', + 'OVERRIDE' => 'Alterar', + 'RESET' => 'Apagar', + 'SAVE' => 'Guardar', + 'SEARCH' => 'Procurar', + 'SORT' => 'Ordenar', + 'SUBMIT' => 'Submeter', + 'PRINT' => 'Imprimir', + 'REMOVE' => 'Remover', + 'UNACTIVATED' => 'Inativo', + 'UPDATE' => 'Atualizar', + 'YES' => 'Sim', + 'NO' => 'Não', + 'OPTIONAL' => 'Opcional', // Misc. - "BUILT_WITH_UF" => "Desenvolvido sobre UserFrosting", - "ADMINLTE_THEME_BY" => "Tema por Almsaeed Studio. Todos os direitos reservados" + 'BUILT_WITH_UF' => 'Desenvolvido sobre UserFrosting', + 'ADMINLTE_THEME_BY' => 'Tema por Almsaeed Studio. Todos os direitos reservados' ]; diff --git a/app/sprinkles/core/locale/pt_PT/validate.php b/app/sprinkles/core/locale/pt_PT/validate.php index bc9647c35..8a7eefd59 100644 --- a/app/sprinkles/core/locale/pt_PT/validate.php +++ b/app/sprinkles/core/locale/pt_PT/validate.php @@ -4,22 +4,22 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Portuguese message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\pt * @author Bruno Silva (brunomnsilva@gmail.com) */ - return [ - "VALIDATE" => [ - "ARRAY" => "Os valores para {{label}} devem estar contidos num array.", - "BOOLEAN" => "O valor para {{label}} deve ser '0' ou '1'.", - "INTEGER" => "O valor para {{label}} deve ser um inteiro.", - "INVALID_EMAIL" => "Endereço de email inválido.", - "LENGTH_RANGE" => "{{label}} deve conter entre {{min}} e {{max}} caracteres.", - "NO_LEAD_WS" => "O valor para {{label}} não pode começar por espaços, tabulações, ou outros espaços em branco.", - "NO_TRAIL_WS" => "O valor para {{label}} não pode terminar em espaços, tabulações, ou outros espaços em branco.", - "REQUIRED" => "Por favor especifique um valor para {{label}}." + 'VALIDATE' => [ + 'ARRAY' => 'Os valores para {{label}} devem estar contidos num array.', + 'BOOLEAN' => "O valor para {{label}} deve ser '0' ou '1'.", + 'INTEGER' => 'O valor para {{label}} deve ser um inteiro.', + 'INVALID_EMAIL' => 'Endereço de email inválido.', + 'LENGTH_RANGE' => '{{label}} deve conter entre {{min}} e {{max}} caracteres.', + 'NO_LEAD_WS' => 'O valor para {{label}} não pode começar por espaços, tabulações, ou outros espaços em branco.', + 'NO_TRAIL_WS' => 'O valor para {{label}} não pode terminar em espaços, tabulações, ou outros espaços em branco.', + 'REQUIRED' => 'Por favor especifique um valor para {{label}}.' ] ]; diff --git a/app/sprinkles/core/locale/ru_RU/errors.php b/app/sprinkles/core/locale/ru_RU/errors.php index d2dd6175f..7ab728fa7 100644 --- a/app/sprinkles/core/locale/ru_RU/errors.php +++ b/app/sprinkles/core/locale/ru_RU/errors.php @@ -4,48 +4,48 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Russian message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\ru_RU * @author @rendername */ - return [ - "ERROR" => [ - "@TRANSLATION" => "Ошибка", + 'ERROR' => [ + '@TRANSLATION' => 'Ошибка', - "400" => [ - "TITLE" => "Ошибка 400: Неправильный запрос", - "DESCRIPTION" => "Это, вероятно, не ваша вина.", + '400' => [ + 'TITLE' => 'Ошибка 400: Неправильный запрос', + 'DESCRIPTION' => 'Это, вероятно, не ваша вина.', ], - "404" => [ - "TITLE" => "Ошибка 404: Не найдено", - "DESCRIPTION" => "Кажется, мы не можем найти то, что вам нужно.", - "DETAIL" => "Мы пытались найти вашу страницу...", - "EXPLAIN" => "Мы не можем найти страницу, которую вы искали.", - "RETURN" => 'В любом случае, нажмите здесь чтобы вернуться на главную страницу.' + '404' => [ + 'TITLE' => 'Ошибка 404: Не найдено', + 'DESCRIPTION' => 'Кажется, мы не можем найти то, что вам нужно.', + 'DETAIL' => 'Мы пытались найти вашу страницу...', + 'EXPLAIN' => 'Мы не можем найти страницу, которую вы искали.', + 'RETURN' => 'В любом случае, нажмите здесь чтобы вернуться на главную страницу.' ], - "CONFIG" => [ - "TITLE" => "Проблема в конфигурации!", - "DESCRIPTION" => "Некоторые требования к конфигурации UserFrosting, не были соблюдены.", - "DETAIL" => "Что-то здесь не так.", - "RETURN" => 'Пожалуйста, исправьте следующие ошибки, затем перезагрузите.' + 'CONFIG' => [ + 'TITLE' => 'Проблема в конфигурации!', + 'DESCRIPTION' => 'Некоторые требования к конфигурации UserFrosting, не были соблюдены.', + 'DETAIL' => 'Что-то здесь не так.', + 'RETURN' => 'Пожалуйста, исправьте следующие ошибки, затем перезагрузите.' ], - "DESCRIPTION" => "Мы обнаружили большое и сильное нарушение.", - "DETAIL" => "Вот что мы получили:", + 'DESCRIPTION' => 'Мы обнаружили большое и сильное нарушение.', + 'DETAIL' => 'Вот что мы получили:', + + 'ENCOUNTERED' => 'Ох... что-то произошло. Мы не знаем, что.', - "ENCOUNTERED" => "Ох... что-то произошло. Мы не знаем, что.", + 'MAIL' => 'Неустранимая ошибка почтовой службы, обратитесь к администратору сервера. Если вы являетесь администратором, пожалуйста, проверьте логи.', - "MAIL" => "Неустранимая ошибка почтовой службы, обратитесь к администратору сервера. Если вы являетесь администратором, пожалуйста, проверьте логи.", - - "RETURN" => 'Нажмите здесь для возврата на главную страницу.', + 'RETURN' => 'Нажмите здесь для возврата на главную страницу.', - "SERVER" => "К сожалению, кажется сервер имеет ошибки. Если вы являетесь администратором сервера, пожалуйста проверьте логи.", + 'SERVER' => 'К сожалению, кажется сервер имеет ошибки. Если вы являетесь администратором сервера, пожалуйста проверьте логи.', - "TITLE" => "Сильное нарушение" + 'TITLE' => 'Сильное нарушение' ] ]; diff --git a/app/sprinkles/core/locale/ru_RU/messages.php b/app/sprinkles/core/locale/ru_RU/messages.php index c3c9a60ff..20a97fee6 100644 --- a/app/sprinkles/core/locale/ru_RU/messages.php +++ b/app/sprinkles/core/locale/ru_RU/messages.php @@ -4,117 +4,117 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Russian message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\ru_RU * @author @rendername */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "О нас", + 'ABOUT' => 'О нас', - "CAPTCHA" => [ - "@TRANSLATION" => "Капча", - "FAIL" => "Код безопасности был введен с ошибками.", - "SPECIFY" => "Введите код капчи", - "VERIFY" => "Проверьте капчу" + 'CAPTCHA' => [ + '@TRANSLATION' => 'Капча', + 'FAIL' => 'Код безопасности был введен с ошибками.', + 'SPECIFY' => 'Введите код капчи', + 'VERIFY' => 'Проверьте капчу' ], - "CSRF_MISSING" => "Отсутствует CSRF токен. Попробуйте обновить страницу и повторить попытку ещё раз?", + 'CSRF_MISSING' => 'Отсутствует CSRF токен. Попробуйте обновить страницу и повторить попытку ещё раз?', - "DB_INVALID" => "Не удается подключиться к базе данных. Если вы являетесь администратором, пожалуйста проверьте лог ошибок.", - "DESCRIPTION" => "Описание", - "DOWNLOAD" => [ - "@TRANSLATION" => "Скачать", - "CSV" => "Скачать CSV" + 'DB_INVALID' => 'Не удается подключиться к базе данных. Если вы являетесь администратором, пожалуйста проверьте лог ошибок.', + 'DESCRIPTION' => 'Описание', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'Скачать', + 'CSV' => 'Скачать CSV' ], - "EMAIL" => [ - "@TRANSLATION" => "Email", - "YOUR" => "Ваш e-mail" + 'EMAIL' => [ + '@TRANSLATION' => 'Email', + 'YOUR' => 'Ваш e-mail' ], - "HOME" => "Главная", + 'HOME' => 'Главная', - "LEGAL" => [ - "@TRANSLATION" => "Правовая информация", - "DESCRIPTION" => "Наша правовая политика применима к использованию вами данного веб-сайта и наших услуг." + 'LEGAL' => [ + '@TRANSLATION' => 'Правовая информация', + 'DESCRIPTION' => 'Наша правовая политика применима к использованию вами данного веб-сайта и наших услуг.' ], - "LOCALE" => [ - "@TRANSLATION" => "Язык" + 'LOCALE' => [ + '@TRANSLATION' => 'Язык' ], - "NAME" => "Имя", - "NAVIGATION" => "Навигация", - "NO_RESULTS" => "Извини, здесь ничего нет.", + 'NAME' => 'Имя', + 'NAVIGATION' => 'Навигация', + 'NO_RESULTS' => 'Извини, здесь ничего нет.', - "PAGINATION" => [ - "GOTO" => "Перейти к странице", - "SHOW" => "Показать", + 'PAGINATION' => [ + 'GOTO' => 'Перейти к странице', + 'SHOW' => 'Показать', // Paginator // possible variables: {size}, {page}, {totalPages}, {filteredPages}, {startRow}, {endRow}, {filteredRows} and {totalRows} // also {page:input} & {startRow:input} will add a modifiable input in place of the value - "OUTPUT" => "{startRow} к {endRow} из {filteredRows} ({totalRows})", - "NEXT" => "Следующая", - "PREVIOUS" => "Предыдущая", - "FIRST" => "Первая", - "LAST" => "Последняя" + 'OUTPUT' => '{startRow} к {endRow} из {filteredRows} ({totalRows})', + 'NEXT' => 'Следующая', + 'PREVIOUS' => 'Предыдущая', + 'FIRST' => 'Первая', + 'LAST' => 'Последняя' ], - "PRIVACY" => [ - "@TRANSLATION" => "Политика конфиденциальности", - "DESCRIPTION" => "Наша политика конфиденциальности описывает, какую информацию мы собираем от вас и как мы будем использовать её." + 'PRIVACY' => [ + '@TRANSLATION' => 'Политика конфиденциальности', + 'DESCRIPTION' => 'Наша политика конфиденциальности описывает, какую информацию мы собираем от вас и как мы будем использовать её.' ], - "SLUG" => "Метка", - "SLUG_CONDITION" => "Метка/Условия", - "SLUG_IN_USE" => "{{slug}} метка уже существует", - "STATUS" => "Статус", - "SUGGEST" => "Предложить", + 'SLUG' => 'Метка', + 'SLUG_CONDITION' => 'Метка/Условия', + 'SLUG_IN_USE' => '{{slug}} метка уже существует', + 'STATUS' => 'Статус', + 'SUGGEST' => 'Предложить', - "UNKNOWN" => "Неизвестно", + 'UNKNOWN' => 'Неизвестно', // Actions words - "ACTIONS" => "Действия", - "ACTIVATE" => "Активировать", - "ACTIVE" => "Активные", - "ADD" => "Добавить", - "CANCEL" => "Отмена", - "CONFIRM" => "Подтвердить", - "CREATE" => "Создать", - "DELETE" => "Удалить", - "DELETE_CONFIRM" => "Вы уверены, что хотите удалить это?", - "DELETE_CONFIRM_YES" => "Да, удалить", - "DELETE_CONFIRM_NAMED" => "Вы уверены, что хотите удалить {{name}}?", - "DELETE_CONFIRM_YES_NAMED" => "Да, удалить {{name}}", - "DELETE_CANNOT_UNDONE" => "Это действие нельзя будет отменить.", - "DELETE_NAMED" => "Удаление {{name}}", - "DENY" => "Запретить", - "DISABLE" => "Отключить", - "DISABLED" => "Отключено", - "EDIT" => "Изменить", - "ENABLE" => "Включить", - "ENABLED" => "Включено", - "OVERRIDE" => "Отменить", - "RESET" => "Сброс", - "SAVE" => "Сохранить", - "SEARCH" => "Поиск", - "SORT" => "Сортировка", - "SUBMIT" => "Отправить", - "PRINT" => "Печать", - "REMOVE" => "Удалить", - "UNACTIVATED" => "Не активировано", - "UPDATE" => "Обновить", - "YES" => "Да", - "NO" => "Нет", - "OPTIONAL" => "Дополнительно", + 'ACTIONS' => 'Действия', + 'ACTIVATE' => 'Активировать', + 'ACTIVE' => 'Активные', + 'ADD' => 'Добавить', + 'CANCEL' => 'Отмена', + 'CONFIRM' => 'Подтвердить', + 'CREATE' => 'Создать', + 'DELETE' => 'Удалить', + 'DELETE_CONFIRM' => 'Вы уверены, что хотите удалить это?', + 'DELETE_CONFIRM_YES' => 'Да, удалить', + 'DELETE_CONFIRM_NAMED' => 'Вы уверены, что хотите удалить {{name}}?', + 'DELETE_CONFIRM_YES_NAMED' => 'Да, удалить {{name}}', + 'DELETE_CANNOT_UNDONE' => 'Это действие нельзя будет отменить.', + 'DELETE_NAMED' => 'Удаление {{name}}', + 'DENY' => 'Запретить', + 'DISABLE' => 'Отключить', + 'DISABLED' => 'Отключено', + 'EDIT' => 'Изменить', + 'ENABLE' => 'Включить', + 'ENABLED' => 'Включено', + 'OVERRIDE' => 'Отменить', + 'RESET' => 'Сброс', + 'SAVE' => 'Сохранить', + 'SEARCH' => 'Поиск', + 'SORT' => 'Сортировка', + 'SUBMIT' => 'Отправить', + 'PRINT' => 'Печать', + 'REMOVE' => 'Удалить', + 'UNACTIVATED' => 'Не активировано', + 'UPDATE' => 'Обновить', + 'YES' => 'Да', + 'NO' => 'Нет', + 'OPTIONAL' => 'Дополнительно', // Misc. - "BUILT_WITH_UF" => "Создано через UserFrosting", - "ADMINLTE_THEME_BY" => "Тема от Almsaeed Studio. Все права защищены", - "WELCOME_TO" => "Добро пожаловать на {{title}}!" + 'BUILT_WITH_UF' => 'Создано через UserFrosting', + 'ADMINLTE_THEME_BY' => 'Тема от Almsaeed Studio. Все права защищены', + 'WELCOME_TO' => 'Добро пожаловать на {{title}}!' ]; diff --git a/app/sprinkles/core/locale/ru_RU/validate.php b/app/sprinkles/core/locale/ru_RU/validate.php index e705fa443..e7d8923aa 100644 --- a/app/sprinkles/core/locale/ru_RU/validate.php +++ b/app/sprinkles/core/locale/ru_RU/validate.php @@ -4,30 +4,30 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Russian message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\ru_RU * @author @rendername */ - return [ - "VALIDATE" => [ - "ARRAY" => "Значения для {{label}} должны быть элементами массива.", - "BOOLEAN" => "Значение {{label}} должно быть '0' или '1'.", - "INTEGER" => "Значение {{label}} должно быть целым.", - "INVALID_EMAIL" => "Неправильный email.", - "LENGTH_RANGE" => "{{label}} должно быть между {{min}} и {{max}} символов в длину.", - "MAX_LENGTH" => "{{label}} должны быть максимально {{max}} символов в длину.", - "MIN_LENGTH" => "{{label}} должно быть минимально {{min}} символов в длину.", - "NO_LEAD_WS" => "Значение {{label}} не может начинаться с пробелов, табуляции или других пробелов.", - "NO_TRAIL_WS" => "Значение {{label}} не может заканчиваться пробелами, табуляции или другими пробелами.", - "RANGE" => "Значение {{label}} должно быть между {{min}} и {{max}} симв.", - "REQUIRED" => "Пожалуйста, укажите значение для {{label}}.", - "SPRUNJE" => [ - "BAD_FILTER" => "{{name}} не является допустимым фильтром.", - "BAD_LIST" => "{{name}} не является допустимым списком.", - "BAD_SORT" => "{{name}} не является допустимым для сортировки полей." + 'VALIDATE' => [ + 'ARRAY' => 'Значения для {{label}} должны быть элементами массива.', + 'BOOLEAN' => "Значение {{label}} должно быть '0' или '1'.", + 'INTEGER' => 'Значение {{label}} должно быть целым.', + 'INVALID_EMAIL' => 'Неправильный email.', + 'LENGTH_RANGE' => '{{label}} должно быть между {{min}} и {{max}} символов в длину.', + 'MAX_LENGTH' => '{{label}} должны быть максимально {{max}} символов в длину.', + 'MIN_LENGTH' => '{{label}} должно быть минимально {{min}} символов в длину.', + 'NO_LEAD_WS' => 'Значение {{label}} не может начинаться с пробелов, табуляции или других пробелов.', + 'NO_TRAIL_WS' => 'Значение {{label}} не может заканчиваться пробелами, табуляции или другими пробелами.', + 'RANGE' => 'Значение {{label}} должно быть между {{min}} и {{max}} симв.', + 'REQUIRED' => 'Пожалуйста, укажите значение для {{label}}.', + 'SPRUNJE' => [ + 'BAD_FILTER' => '{{name}} не является допустимым фильтром.', + 'BAD_LIST' => '{{name}} не является допустимым списком.', + 'BAD_SORT' => '{{name}} не является допустимым для сортировки полей.' ] ] ]; diff --git a/app/sprinkles/core/locale/th_TH/errors.php b/app/sprinkles/core/locale/th_TH/errors.php index 7b3d41de2..8913e70b8 100644 --- a/app/sprinkles/core/locale/th_TH/errors.php +++ b/app/sprinkles/core/locale/th_TH/errors.php @@ -4,48 +4,48 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Thai message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\th * @author Karuhut Komol */ - return [ - "ERROR" => [ - "@TRANSLATION" => "ข้อผิดพลาด", + 'ERROR' => [ + '@TRANSLATION' => 'ข้อผิดพลาด', - "400" => [ - "TITLE" => "ข้อผิดพลาด 400: การร้องขอไม่ถูกต้อง", - "DESCRIPTION" => "นี่ไม่น่าจะเป็นความผิดพลาดของคุณ", + '400' => [ + 'TITLE' => 'ข้อผิดพลาด 400: การร้องขอไม่ถูกต้อง', + 'DESCRIPTION' => 'นี่ไม่น่าจะเป็นความผิดพลาดของคุณ', ], - "404" => [ - "TITLE" => "ข้อผิดพลาด 404: ไม่พบหน้านี้", - "DESCRIPTION" => "ดูเหมือนเราจะไม่สามารถหาสิ่งที่คุณต้องการได้", - "DETAIL" => "เราพยายามได้ที่จะหาหน้าของคุณ...", - "EXPLAIN" => "เราไม่สามารถหาหน้าที่คุณมองหาอยู่ได้", - "RETURN" => 'อย่างไรก็ตาม คลิก ที่นี่ เพื่อกลับไปยังหน้าแรก' + '404' => [ + 'TITLE' => 'ข้อผิดพลาด 404: ไม่พบหน้านี้', + 'DESCRIPTION' => 'ดูเหมือนเราจะไม่สามารถหาสิ่งที่คุณต้องการได้', + 'DETAIL' => 'เราพยายามได้ที่จะหาหน้าของคุณ...', + 'EXPLAIN' => 'เราไม่สามารถหาหน้าที่คุณมองหาอยู่ได้', + 'RETURN' => 'อย่างไรก็ตาม คลิก ที่นี่ เพื่อกลับไปยังหน้าแรก' ], - "CONFIG" => [ - "TITLE" => "เกิดปัญหาจากการตั้งค่า UserFrosting!", - "DESCRIPTION" => "การตั้งค่าบางอย่างของ UserFrosting ยังไม่ตรงตามความต้องการ", - "DETAIL" => "มีบางอย่างไม่ถูกต้องอยู่", - "RETURN" => 'กรุณาแก้ไขข้อผิดพลาดดังกล่าว จากนั้น โหลดหน้านี้อีกครั้ง' + 'CONFIG' => [ + 'TITLE' => 'เกิดปัญหาจากการตั้งค่า UserFrosting!', + 'DESCRIPTION' => 'การตั้งค่าบางอย่างของ UserFrosting ยังไม่ตรงตามความต้องการ', + 'DETAIL' => 'มีบางอย่างไม่ถูกต้องอยู่', + 'RETURN' => 'กรุณาแก้ไขข้อผิดพลาดดังกล่าว จากนั้น โหลดหน้านี้อีกครั้ง' ], - "DESCRIPTION" => "เรารู้สึกความโกลาหลในกองทัพได้เป็นอย่างดี", - "DETAIL" => "นี่คือสิ่งที่เราพบ:", + 'DESCRIPTION' => 'เรารู้สึกความโกลาหลในกองทัพได้เป็นอย่างดี', + 'DETAIL' => 'นี่คือสิ่งที่เราพบ:', - "ENCOUNTERED" => "อืมม...บางอย่างเกิดขึ้น แต่เราไม่รู้ว่าคืออะไร", + 'ENCOUNTERED' => 'อืมม...บางอย่างเกิดขึ้น แต่เราไม่รู้ว่าคืออะไร', - "MAIL" => "เกิดข้อผิดพลาดร้ายแรงระหว่างการพยายามส่งอีเมล กรุณาติดต่อผู้ดูแลระบบของเซิฟเวอร์นี้ หากคุณเป็นผู้ดูแล กรุณาตรวจสอบบันทึกอีเมลของ UF", + 'MAIL' => 'เกิดข้อผิดพลาดร้ายแรงระหว่างการพยายามส่งอีเมล กรุณาติดต่อผู้ดูแลระบบของเซิฟเวอร์นี้ หากคุณเป็นผู้ดูแล กรุณาตรวจสอบบันทึกอีเมลของ UF', - "RETURN" => 'คลิก ที่นี่ เพื่อกลับไปยังหน้าแรก', + 'RETURN' => 'คลิก ที่นี่ เพื่อกลับไปยังหน้าแรก', - "SERVER" => "โอ้ว ดูเหมือนระบบของเราอาจจะผิดพลาดเอง หากคุณเป็นผู้ดูแล กรุณาตรวจสอบบันทึกข้อผิดพลาดของ PHP หรือ UF", + 'SERVER' => 'โอ้ว ดูเหมือนระบบของเราอาจจะผิดพลาดเอง หากคุณเป็นผู้ดูแล กรุณาตรวจสอบบันทึกข้อผิดพลาดของ PHP หรือ UF', - "TITLE" => "เกิดความโกลาหลในกองทัพ" + 'TITLE' => 'เกิดความโกลาหลในกองทัพ' ] ]; diff --git a/app/sprinkles/core/locale/th_TH/messages.php b/app/sprinkles/core/locale/th_TH/messages.php index 0073a40a2..7a4a75734 100644 --- a/app/sprinkles/core/locale/th_TH/messages.php +++ b/app/sprinkles/core/locale/th_TH/messages.php @@ -4,99 +4,99 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Thai message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\th * @author Karuhut Komol */ - return [ - "@PLURAL_RULE" => 1, + '@PLURAL_RULE' => 1, - "ABOUT" => "เกี่ยวกับ", + 'ABOUT' => 'เกี่ยวกับ', - "CAPTCHA" => [ - "@TRANSLATION" => "รหัสยืนยัน", - "FAIL" => "คุณยังกรอกรหัสยืนยันไม่ถูกต้อง", - "SPECIFY" => "กรอกรหัสยืนยัน", - "VERIFY" => "ตรวจสอบรหัสยืนยัน" + 'CAPTCHA' => [ + '@TRANSLATION' => 'รหัสยืนยัน', + 'FAIL' => 'คุณยังกรอกรหัสยืนยันไม่ถูกต้อง', + 'SPECIFY' => 'กรอกรหัสยืนยัน', + 'VERIFY' => 'ตรวจสอบรหัสยืนยัน' ], - "CSRF_MISSING" => "ไม่พบโทเคน CSRF กรุณารีเฟรชแล้วส่งข้อมูลใหม่", + 'CSRF_MISSING' => 'ไม่พบโทเคน CSRF กรุณารีเฟรชแล้วส่งข้อมูลใหม่', - "DB_INVALID" => "ไม่สามารถเชื่อมต่อกับฐานข้อมูลได้ หากคุณเป็นผู้ดูแลระบบ กรุณาตรวจสอบบันทึกข้อผิดพลาด", - "DESCRIPTION" => "รายละเอียด", - "DOWNLOAD" => [ - "@TRANSLATION" => "ดาวน์โหลด", - "CSV" => "ดาวน์โหลด CSV" + 'DB_INVALID' => 'ไม่สามารถเชื่อมต่อกับฐานข้อมูลได้ หากคุณเป็นผู้ดูแลระบบ กรุณาตรวจสอบบันทึกข้อผิดพลาด', + 'DESCRIPTION' => 'รายละเอียด', + 'DOWNLOAD' => [ + '@TRANSLATION' => 'ดาวน์โหลด', + 'CSV' => 'ดาวน์โหลด CSV' ], - "EMAIL" => [ - "@TRANSLATION" => "อีเมล", - "YOUR" => "ที่อยู่อีเมลของคุณ" + 'EMAIL' => [ + '@TRANSLATION' => 'อีเมล', + 'YOUR' => 'ที่อยู่อีเมลของคุณ' ], - "HOME" => "หน้าแรก", + 'HOME' => 'หน้าแรก', - "LEGAL" => "นโยบายทางกฎหมาย", + 'LEGAL' => 'นโยบายทางกฎหมาย', - "LOCALE" => [ - "@TRANSLATION" => "ภาษา" + 'LOCALE' => [ + '@TRANSLATION' => 'ภาษา' ], - "NAME" => "ชื่อ", - "NAVIGATION" => "เมนูนำทาง", + 'NAME' => 'ชื่อ', + 'NAVIGATION' => 'เมนูนำทาง', - "PAGINATION" => [ - "GOTO" => "ข้ามไปยังหน้า", - "SHOW" => "แสดง", - "OUTPUT" => "{startRow} to {endRow} of {filteredRows} ({totalRows})" + 'PAGINATION' => [ + 'GOTO' => 'ข้ามไปยังหน้า', + 'SHOW' => 'แสดง', + 'OUTPUT' => '{startRow} to {endRow} of {filteredRows} ({totalRows})' ], - "PRIVACY" => "นโยบายความเป็นส่วนตัว", + 'PRIVACY' => 'นโยบายความเป็นส่วนตัว', - "SLUG" => "ข้อกำหนด", - "SLUG_CONDITION" => "ข้อกำหนด/เงื่อนไข", - "STATUS" => "สถานะ", + 'SLUG' => 'ข้อกำหนด', + 'SLUG_CONDITION' => 'ข้อกำหนด/เงื่อนไข', + 'STATUS' => 'สถานะ', - "UNKNOWN" => "ไม่ทราบ", + 'UNKNOWN' => 'ไม่ทราบ', // Actions words - "ACTIONS" => "การดำเนินการ", - "ACTIVATE" => "เปิดใช้งาน", - "ACTIVE" => "เปิดใช้งานอยู่", - "ADD" => "เพิ่ม", - "CANCEL" => "ยกเลิก", - "CONFIRM" => "ยืนยัน", - "CREATE" => "สร้าง", - "DELETE" => "ลบ", - "DELETE_CONFIRM" => "คุณต้องการที่จะลบใช่หรือไม่?", - "DELETE_CONFIRM_YES" => "ใช่ ลบเลย", - "DELETE_CONFIRM_NAMED" => "คุณต้องการที่จะลบ {{name}} ใช่หรือไม่?", - "DELETE_CONFIRM_YES_NAMED" => "ใช่ ลบ {{name}} เลย", - "DELETE_CANNOT_UNDONE" => "การดำเนินการนี้ไม่สามารถยกเลิกได้", - "DELETE_NAMED" => "ลบ {{name}}", - "DENY" => "ปฏิเสธ", - "DISABLE" => "ปิดการใช้งาน", - "DISABLED" => "ปิดการใช้งานอยู่", - "EDIT" => "แก้ไข", - "ENABLE" => "เปิด", - "ENABLED" => "เปิดอยู่", - "OVERRIDE" => "เขียนทับ", - "RESET" => "รีเซ็ต", - "SAVE" => "บันทึก", - "SEARCH" => "ค้นหา", - "SORT" => "ประเภท", - "SUBMIT" => "ส่ง", - "PRINT" => "พิมพ์", - "REMOVE" => "เอาออก", - "UNACTIVATED" => "ไม่มีการเปิดใช้", - "UPDATE" => "ปรับปรุง", - "YES" => "ใช่", - "NO" => "ไม่", - "OPTIONAL" => "ตัวเลือกเพิ่มเติม", + 'ACTIONS' => 'การดำเนินการ', + 'ACTIVATE' => 'เปิดใช้งาน', + 'ACTIVE' => 'เปิดใช้งานอยู่', + 'ADD' => 'เพิ่ม', + 'CANCEL' => 'ยกเลิก', + 'CONFIRM' => 'ยืนยัน', + 'CREATE' => 'สร้าง', + 'DELETE' => 'ลบ', + 'DELETE_CONFIRM' => 'คุณต้องการที่จะลบใช่หรือไม่?', + 'DELETE_CONFIRM_YES' => 'ใช่ ลบเลย', + 'DELETE_CONFIRM_NAMED' => 'คุณต้องการที่จะลบ {{name}} ใช่หรือไม่?', + 'DELETE_CONFIRM_YES_NAMED' => 'ใช่ ลบ {{name}} เลย', + 'DELETE_CANNOT_UNDONE' => 'การดำเนินการนี้ไม่สามารถยกเลิกได้', + 'DELETE_NAMED' => 'ลบ {{name}}', + 'DENY' => 'ปฏิเสธ', + 'DISABLE' => 'ปิดการใช้งาน', + 'DISABLED' => 'ปิดการใช้งานอยู่', + 'EDIT' => 'แก้ไข', + 'ENABLE' => 'เปิด', + 'ENABLED' => 'เปิดอยู่', + 'OVERRIDE' => 'เขียนทับ', + 'RESET' => 'รีเซ็ต', + 'SAVE' => 'บันทึก', + 'SEARCH' => 'ค้นหา', + 'SORT' => 'ประเภท', + 'SUBMIT' => 'ส่ง', + 'PRINT' => 'พิมพ์', + 'REMOVE' => 'เอาออก', + 'UNACTIVATED' => 'ไม่มีการเปิดใช้', + 'UPDATE' => 'ปรับปรุง', + 'YES' => 'ใช่', + 'NO' => 'ไม่', + 'OPTIONAL' => 'ตัวเลือกเพิ่มเติม', // Misc. - "BUILT_WITH_UF" => "สร้างด้วย UserFrosting", - "ADMINLTE_THEME_BY" => "ธีมโดย Almsaeed Studio สงวนลิขสิทธิ์" + 'BUILT_WITH_UF' => 'สร้างด้วย UserFrosting', + 'ADMINLTE_THEME_BY' => 'ธีมโดย Almsaeed Studio สงวนลิขสิทธิ์' ]; diff --git a/app/sprinkles/core/locale/th_TH/validate.php b/app/sprinkles/core/locale/th_TH/validate.php index 6d141aab3..09d3216ec 100644 --- a/app/sprinkles/core/locale/th_TH/validate.php +++ b/app/sprinkles/core/locale/th_TH/validate.php @@ -4,22 +4,22 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Thai message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\th * @author Karuhut Komol */ - return [ - "VALIDATE" => [ - "ARRAY" => "ค่าของ {{label}} จะต้องเป็น Array", - "BOOLEAN" => "ค่าของ {{label}} จะต้องเป็น '0' หรือ '1'", - "INTEGER" => "ค่าของ {{label}} จะต้องเป็นตัวเลข", - "INVALID_EMAIL" => "ที่อยู่อีเมลไม่ถูกต้อง", - "LENGTH_RANGE" => "ความยาวของ {{label}} จะต้องอยู่ระหว่าง {{min}} ถึง {{max}} ตัวอักษร", - "NO_LEAD_WS" => "ค่าของ {{label}} ไม่สามารถเริ่มต้นด้วยช่องว่าง หรือ แท็บ", - "NO_TRAIL_WS" => "ค่าของ {{label}} ไม่สามารถลงท้ายด้วยช่องว่าง หรือ แท็บ", - "REQUIRED" => "กรุณากำหนดค่าของ {{label}}" + 'VALIDATE' => [ + 'ARRAY' => 'ค่าของ {{label}} จะต้องเป็น Array', + 'BOOLEAN' => "ค่าของ {{label}} จะต้องเป็น '0' หรือ '1'", + 'INTEGER' => 'ค่าของ {{label}} จะต้องเป็นตัวเลข', + 'INVALID_EMAIL' => 'ที่อยู่อีเมลไม่ถูกต้อง', + 'LENGTH_RANGE' => 'ความยาวของ {{label}} จะต้องอยู่ระหว่าง {{min}} ถึง {{max}} ตัวอักษร', + 'NO_LEAD_WS' => 'ค่าของ {{label}} ไม่สามารถเริ่มต้นด้วยช่องว่าง หรือ แท็บ', + 'NO_TRAIL_WS' => 'ค่าของ {{label}} ไม่สามารถลงท้ายด้วยช่องว่าง หรือ แท็บ', + 'REQUIRED' => 'กรุณากำหนดค่าของ {{label}}' ] ]; diff --git a/app/sprinkles/core/locale/valitron/ar.php b/app/sprinkles/core/locale/valitron/ar.php index 0c03547e9..24625c48f 100644 --- a/app/sprinkles/core/locale/valitron/ar.php +++ b/app/sprinkles/core/locale/valitron/ar.php @@ -1,28 +1,34 @@ "مطلوب", +return [ + 'required' => 'مطلوب', 'equals' => "يجب أن يكون مساوي لي '%s'", 'different' => "يجب ان يكون غير '%s'", - 'accepted' => "يجب ان يكون نعم", - 'numeric' => "يجب ان يكون رقم", - 'integer' => "يجب ان يكون رقم (0-9)", - 'length' => "يجب ان يكون أطول من %d", - 'min' => "يجب ان يكون اعلي من %s", - 'max' => "يجب ان يكون اقل من %s", - 'in' => "الُمدخل يغير صحيح", - 'notIn' => "الُمدخل يغير صحيح", - 'ip' => "رقم الإتصال غير صحيح", - 'email' => "البريد الألكتروني غير صحيح", - 'url' => "الرابط غير صحيح", - 'urlActive' => "يجب أن يكون نطاق فعال", - 'alpha' => "يجب أن يحتوي فقط علي a-z", - 'alphaNum' => "يجب ان يحتوي فقط a-z او ارقام 0-9", - 'slug' => "يجب ان يحتوي فقط علي a-z, و ارقام 0-9, شرطات و خط سفلي", - 'regex' => "خطا بالصيغة", - 'date' => "خطا بالتاريخ", + 'accepted' => 'يجب ان يكون نعم', + 'numeric' => 'يجب ان يكون رقم', + 'integer' => 'يجب ان يكون رقم (0-9)', + 'length' => 'يجب ان يكون أطول من %d', + 'min' => 'يجب ان يكون اعلي من %s', + 'max' => 'يجب ان يكون اقل من %s', + 'in' => 'الُمدخل يغير صحيح', + 'notIn' => 'الُمدخل يغير صحيح', + 'ip' => 'رقم الإتصال غير صحيح', + 'email' => 'البريد الألكتروني غير صحيح', + 'url' => 'الرابط غير صحيح', + 'urlActive' => 'يجب أن يكون نطاق فعال', + 'alpha' => 'يجب أن يحتوي فقط علي a-z', + 'alphaNum' => 'يجب ان يحتوي فقط a-z او ارقام 0-9', + 'slug' => 'يجب ان يحتوي فقط علي a-z, و ارقام 0-9, شرطات و خط سفلي', + 'regex' => 'خطا بالصيغة', + 'date' => 'خطا بالتاريخ', 'dateFormat' => "يجب ان يكون تاريخ بهذه الصيغة '%s'", 'dateBefore' => "التاريخ يجب ان يكون قبل '%s'", 'dateAfter' => "التاريخ يجب ان يكون بعد '%s'", - 'contains' => "يجب ان يحتوي %s" -); + 'contains' => 'يجب ان يحتوي %s' +]; diff --git a/app/sprinkles/core/locale/valitron/de.php b/app/sprinkles/core/locale/valitron/de.php index 4847bd0e2..eec34dba7 100644 --- a/app/sprinkles/core/locale/valitron/de.php +++ b/app/sprinkles/core/locale/valitron/de.php @@ -1,33 +1,39 @@ "ist erforderlich", +return [ + 'required' => 'ist erforderlich', 'equals' => "muss identisch mit '%s' sein", 'different' => "muss sich von '%s' unterscheiden", - 'accepted' => "muss markiert sein", - 'numeric' => "muss eine Zahl sein", - 'integer' => "muss eine ganze Zahl sein", - 'length' => "kann nicht länger als %d sein", - 'min' => "muss größer als %s sein", - 'max' => "muss kleiner als %s sein", - 'in' => "enthält einen ungültigen Wert", - 'notIn' => "enthält einen ungültigen Wert", - 'ip' => "enthält keine gültige IP-Addresse", - 'email' => "enthält keine gültige E-Mail-Adresse", - 'url' => "enthält keine gültige URL", - 'urlActive' => "muss eine aktive Domain sein", - 'alpha' => "darf nur Buchstaben enthalten", - 'alphaNum' => "darf nur Buchstaben und Ganzzahlen enthalten", - 'slug' => "darf nur Buchstaben, Ganzzahlen, Schrägstriche und Grundstriche enthalten", - 'regex' => "enthält ungültige Zeichen", - 'date' => "enthält kein gültiges Datum", + 'accepted' => 'muss markiert sein', + 'numeric' => 'muss eine Zahl sein', + 'integer' => 'muss eine ganze Zahl sein', + 'length' => 'kann nicht länger als %d sein', + 'min' => 'muss größer als %s sein', + 'max' => 'muss kleiner als %s sein', + 'in' => 'enthält einen ungültigen Wert', + 'notIn' => 'enthält einen ungültigen Wert', + 'ip' => 'enthält keine gültige IP-Addresse', + 'email' => 'enthält keine gültige E-Mail-Adresse', + 'url' => 'enthält keine gültige URL', + 'urlActive' => 'muss eine aktive Domain sein', + 'alpha' => 'darf nur Buchstaben enthalten', + 'alphaNum' => 'darf nur Buchstaben und Ganzzahlen enthalten', + 'slug' => 'darf nur Buchstaben, Ganzzahlen, Schrägstriche und Grundstriche enthalten', + 'regex' => 'enthält ungültige Zeichen', + 'date' => 'enthält kein gültiges Datum', 'dateFormat' => "benötigt ein Datum im Format '%s'", 'dateBefore' => "benötigt ein Datum, das vor dem '%s' liegt", 'dateAfter' => "benötigt ein Datum, das nach dem '%s' liegt", - 'contains' => "muss %s beinhalten", - 'boolean' => "muss ein Wahrheitswert sein", - 'lengthBetween' => "benötigt zwischen %d und %d Zeichen", - 'creditCard' => "muss eine gültige Kreditkartennummer sein", - "lengthMin" => "muss mindestens %d Zeichen enthalten", - "lengthMax" => "kann nicht mehr als %d Zeichen enthalten" -); + 'contains' => 'muss %s beinhalten', + 'boolean' => 'muss ein Wahrheitswert sein', + 'lengthBetween' => 'benötigt zwischen %d und %d Zeichen', + 'creditCard' => 'muss eine gültige Kreditkartennummer sein', + 'lengthMin' => 'muss mindestens %d Zeichen enthalten', + 'lengthMax' => 'kann nicht mehr als %d Zeichen enthalten' +]; diff --git a/app/sprinkles/core/locale/valitron/el.php b/app/sprinkles/core/locale/valitron/el.php index 8f27d3903..508a1f126 100644 --- a/app/sprinkles/core/locale/valitron/el.php +++ b/app/sprinkles/core/locale/valitron/el.php @@ -1,34 +1,40 @@ "είναι απαραίτητο", +return [ + 'required' => 'είναι απαραίτητο', 'equals' => "πρέπει να είναι ίδιο με '%s'", 'different' => "πρέπει να διαφέρει από '%s'", - 'accepted' => "πρέπει να έχει αποδεχτεί", - 'numeric' => "πρέπει να είναι αριθμός", - 'integer' => "πρέπει να είναι ακέραιος αριθμός (0-9)", - 'length' => "πρέπει να είναι μεγαλύτερο από %d", - 'min' => "πρέπει να είναι τουλάχιστον %s", - 'max' => "δεν πρέπει να είναι περισσότερο από %s", - 'in' => "περιέχει μη έγκυρη τιμή", - 'notIn' => "περιέχει μη έγκυρη τιμή", - 'ip' => "δεν είναι έγκυρη διεύθυνση IP", - 'email' => "δεν είναι έγκυρη διεύθυνση email", - 'url' => "δεν είναι URL", - 'urlActive' => "πρέπει να είναι ενεργό domain", - 'alpha' => "πρέπει να περιέχει μόνο χαρακτήρες", - 'alphaNum' => "πρέπει να περιέχει μόνο χαρακτήρες και/ή αριθμούς", - 'slug' => "πρέπει να περιέχει μόνο χαρακτήρες, αριθμούς, παύλες και κάτω παύλες", - 'regex' => "περιέχει μη έγκυρους χαρακτήρες", - 'date' => "δεν είναι έγκυρη ημερομηνία", + 'accepted' => 'πρέπει να έχει αποδεχτεί', + 'numeric' => 'πρέπει να είναι αριθμός', + 'integer' => 'πρέπει να είναι ακέραιος αριθμός (0-9)', + 'length' => 'πρέπει να είναι μεγαλύτερο από %d', + 'min' => 'πρέπει να είναι τουλάχιστον %s', + 'max' => 'δεν πρέπει να είναι περισσότερο από %s', + 'in' => 'περιέχει μη έγκυρη τιμή', + 'notIn' => 'περιέχει μη έγκυρη τιμή', + 'ip' => 'δεν είναι έγκυρη διεύθυνση IP', + 'email' => 'δεν είναι έγκυρη διεύθυνση email', + 'url' => 'δεν είναι URL', + 'urlActive' => 'πρέπει να είναι ενεργό domain', + 'alpha' => 'πρέπει να περιέχει μόνο χαρακτήρες', + 'alphaNum' => 'πρέπει να περιέχει μόνο χαρακτήρες και/ή αριθμούς', + 'slug' => 'πρέπει να περιέχει μόνο χαρακτήρες, αριθμούς, παύλες και κάτω παύλες', + 'regex' => 'περιέχει μη έγκυρους χαρακτήρες', + 'date' => 'δεν είναι έγκυρη ημερομηνία', 'dateFormat' => "πρέπει να είναι ημερομηνία της μορφής '%s'", 'dateBefore' => "πρέπει να είναι ημερομηνία πριν από '%s'", 'dateAfter' => "πρέπει να είναι ημερομηνία μετά από '%s'", - 'contains' => "πρέπει να περιέχει %s", - 'boolean' => "πρέπει να είναι boolean", - 'lengthBetween' => "πρέπει να είναι μεταξύ %d και %d χαρακτήρων", - 'creditCard' => "πρέπει να είναι ένα έγκυρο νούμερο πιστωτικής κάρτας", - "lengthMin" => "πρέπει να περιέχει περισσότερους από %d χαρακτήρες", - "lengthMax" => "πρέπει να περιέχει λιγότερους από %d χαρακτήρες", - "instanceOf" => "πρέπει να είναι αντικείμενο της '%s'" -); + 'contains' => 'πρέπει να περιέχει %s', + 'boolean' => 'πρέπει να είναι boolean', + 'lengthBetween' => 'πρέπει να είναι μεταξύ %d και %d χαρακτήρων', + 'creditCard' => 'πρέπει να είναι ένα έγκυρο νούμερο πιστωτικής κάρτας', + 'lengthMin' => 'πρέπει να περιέχει περισσότερους από %d χαρακτήρες', + 'lengthMax' => 'πρέπει να περιέχει λιγότερους από %d χαρακτήρες', + 'instanceOf' => "πρέπει να είναι αντικείμενο της '%s'" +]; diff --git a/app/sprinkles/core/locale/valitron/en.php b/app/sprinkles/core/locale/valitron/en.php index 9dd9cd8db..413a3c487 100644 --- a/app/sprinkles/core/locale/valitron/en.php +++ b/app/sprinkles/core/locale/valitron/en.php @@ -1,34 +1,40 @@ "is required", +return [ + 'required' => 'is required', 'equals' => "must be the same as '%s'", 'different' => "must be different than '%s'", - 'accepted' => "must be accepted", - 'numeric' => "must be numeric", - 'integer' => "must be an integer (0-9)", - 'length' => "must be longer than %d", - 'min' => "must be at least %s", - 'max' => "must be no more than %s", - 'in' => "contains invalid value", - 'notIn' => "contains invalid value", - 'ip' => "is not a valid IP address", - 'email' => "is not a valid email address", - 'url' => "not a URL", - 'urlActive' => "must be an active domain", - 'alpha' => "must contain only letters a-z", - 'alphaNum' => "must contain only letters a-z and/or numbers 0-9", - 'slug' => "must contain only letters a-z, numbers 0-9, dashes and underscores", - 'regex' => "contains invalid characters", - 'date' => "is not a valid date", + 'accepted' => 'must be accepted', + 'numeric' => 'must be numeric', + 'integer' => 'must be an integer (0-9)', + 'length' => 'must be longer than %d', + 'min' => 'must be at least %s', + 'max' => 'must be no more than %s', + 'in' => 'contains invalid value', + 'notIn' => 'contains invalid value', + 'ip' => 'is not a valid IP address', + 'email' => 'is not a valid email address', + 'url' => 'not a URL', + 'urlActive' => 'must be an active domain', + 'alpha' => 'must contain only letters a-z', + 'alphaNum' => 'must contain only letters a-z and/or numbers 0-9', + 'slug' => 'must contain only letters a-z, numbers 0-9, dashes and underscores', + 'regex' => 'contains invalid characters', + 'date' => 'is not a valid date', 'dateFormat' => "must be date with format '%s'", 'dateBefore' => "must be date before '%s'", 'dateAfter' => "must be date after '%s'", - 'contains' => "must contain %s", - 'boolean' => "must be a boolean", - 'lengthBetween' => "must be between %d and %d characters", - 'creditCard' => "must be a valid credit card number", - "lengthMin" => "must contain greater than %d characters", - "lengthMax" => "must contain less than %d characters", - "instanceOf" => "must be an instance of '%s'" -); + 'contains' => 'must contain %s', + 'boolean' => 'must be a boolean', + 'lengthBetween' => 'must be between %d and %d characters', + 'creditCard' => 'must be a valid credit card number', + 'lengthMin' => 'must contain greater than %d characters', + 'lengthMax' => 'must contain less than %d characters', + 'instanceOf' => "must be an instance of '%s'" +]; diff --git a/app/sprinkles/core/locale/valitron/es.php b/app/sprinkles/core/locale/valitron/es.php index 3c177f6ea..cf00c3356 100644 --- a/app/sprinkles/core/locale/valitron/es.php +++ b/app/sprinkles/core/locale/valitron/es.php @@ -1,34 +1,40 @@ "es requerido", +return [ + 'required' => 'es requerido', 'equals' => "debe ser igual a '%s'", 'different' => "debe ser diferente a '%s'", - 'accepted' => "debe ser aceptado", - 'numeric' => "debe ser numérico", - 'integer' => "debe ser un entero (0-9)", - 'length' => "debe ser mas largo de %d", - 'min' => "debe ser mayor a %s", - 'max' => "debe ser menor a %s", - 'in' => "contiene un valor invalido", - 'notIn' => "contiene un valor invalido", - 'ip' => "no es una dirección IP", - 'email' => "no es un correo electrónico válido", - 'url' => "no es una URL", - 'urlActive' => "debe ser un dominio activo", - 'alpha' => "debe contener solo letras a-z", - 'alphaNum' => "debe contener solo letras a-z o números 0-9", - 'slug' => "debe contener solo letras a-z, números 0-9, diagonales y guiones bajos", - 'regex' => "contiene caracteres inválidos", - 'date' => "no es una fecha válida", + 'accepted' => 'debe ser aceptado', + 'numeric' => 'debe ser numérico', + 'integer' => 'debe ser un entero (0-9)', + 'length' => 'debe ser mas largo de %d', + 'min' => 'debe ser mayor a %s', + 'max' => 'debe ser menor a %s', + 'in' => 'contiene un valor invalido', + 'notIn' => 'contiene un valor invalido', + 'ip' => 'no es una dirección IP', + 'email' => 'no es un correo electrónico válido', + 'url' => 'no es una URL', + 'urlActive' => 'debe ser un dominio activo', + 'alpha' => 'debe contener solo letras a-z', + 'alphaNum' => 'debe contener solo letras a-z o números 0-9', + 'slug' => 'debe contener solo letras a-z, números 0-9, diagonales y guiones bajos', + 'regex' => 'contiene caracteres inválidos', + 'date' => 'no es una fecha válida', 'dateFormat' => "debe ser una fecha con formato '%s'", 'dateBefore' => "debe ser una fecha antes de '%s'", 'dateAfter' => "debe ser una fecha después de '%s'", - 'contains' => "debe contener %s", - 'boolean' => "debe ser booleano", - 'lengthBetween' => "debe ser entre %d y %d caracteres", - 'creditCard' => "debe ser un numero de tarjeta de crédito válido", - "lengthMin" => "debe contener mas de %d caracteres", - "lengthMax" => "debe contener menos de %d caracteres", - "instanceOf" => "debe ser una instancia de '%s'" -); + 'contains' => 'debe contener %s', + 'boolean' => 'debe ser booleano', + 'lengthBetween' => 'debe ser entre %d y %d caracteres', + 'creditCard' => 'debe ser un numero de tarjeta de crédito válido', + 'lengthMin' => 'debe contener mas de %d caracteres', + 'lengthMax' => 'debe contener menos de %d caracteres', + 'instanceOf' => "debe ser una instancia de '%s'" +]; diff --git a/app/sprinkles/core/locale/valitron/fr.php b/app/sprinkles/core/locale/valitron/fr.php index 2572201d5..61b3793c5 100644 --- a/app/sprinkles/core/locale/valitron/fr.php +++ b/app/sprinkles/core/locale/valitron/fr.php @@ -1,34 +1,40 @@ "est obligatoire", +return [ + 'required' => 'est obligatoire', 'equals' => "doit être identique à '%s'", 'different' => "doit être différent de '%s'", - 'accepted' => "doit être accepté", - 'numeric' => "doit être numérique", - 'integer' => "doit être un entier (0-9)", - 'length' => "doit être plus long que %d", - 'min' => "doit être plus grand que %s", - 'max' => "doit être plus petit que %s", - 'in' => "contient une valeur non valide", - 'notIn' => "contient une valeur non valide", + 'accepted' => 'doit être accepté', + 'numeric' => 'doit être numérique', + 'integer' => 'doit être un entier (0-9)', + 'length' => 'doit être plus long que %d', + 'min' => 'doit être plus grand que %s', + 'max' => 'doit être plus petit que %s', + 'in' => 'contient une valeur non valide', + 'notIn' => 'contient une valeur non valide', 'ip' => "n'est pas une adresse IP valide", 'email' => "n'est pas une adresse email valide", 'url' => "n'est pas une URL", - 'urlActive' => "doit être un domaine actif", - 'alpha' => "doit contenir uniquement les lettres a-z", - 'alphaNum' => "doit contenir uniquement des lettres de a-z et/ou des chiffres 0-9", - 'slug' => "doit contenir uniquement des lettres de a-z, des chiffres 0-9, des tirets et des traits soulignés", - 'regex' => "contient des caractères invalides", + 'urlActive' => 'doit être un domaine actif', + 'alpha' => 'doit contenir uniquement les lettres a-z', + 'alphaNum' => 'doit contenir uniquement des lettres de a-z et/ou des chiffres 0-9', + 'slug' => 'doit contenir uniquement des lettres de a-z, des chiffres 0-9, des tirets et des traits soulignés', + 'regex' => 'contient des caractères invalides', 'date' => "n'est pas une date valide", 'dateFormat' => "doit être une date avec le format '%s'", 'dateBefore' => "doit être une date avant '%s'", 'dateAfter' => "doit être une date après '%s'", - 'contains' => "doit contenir %s", - 'boolean' => "doit être un booléen", - 'lengthBetween' => "doit contenir entre %d et %d caractères", - 'creditCard' => "doit être un numéro de carte de crédit valide", - "lengthMin" => "doit contenir plus de %d caractères", - "lengthMax" => "doit contenir moins de %d caractères", - "instanceOf" => "doit être une instance de '%s'" -); + 'contains' => 'doit contenir %s', + 'boolean' => 'doit être un booléen', + 'lengthBetween' => 'doit contenir entre %d et %d caractères', + 'creditCard' => 'doit être un numéro de carte de crédit valide', + 'lengthMin' => 'doit contenir plus de %d caractères', + 'lengthMax' => 'doit contenir moins de %d caractères', + 'instanceOf' => "doit être une instance de '%s'" +]; diff --git a/app/sprinkles/core/locale/valitron/id.php b/app/sprinkles/core/locale/valitron/id.php index e4044cf30..bf5845397 100644 --- a/app/sprinkles/core/locale/valitron/id.php +++ b/app/sprinkles/core/locale/valitron/id.php @@ -1,33 +1,39 @@ "harus diisi", +return [ + 'required' => 'harus diisi', 'equals' => "harus sama dengan '%s'", 'different' => "harus berbeda dengan '%s'", - 'accepted' => "harus diterima (accepted)", - 'numeric' => "harus berupa nomor/angka", - 'integer' => "harus berupa nilai integer (0-9)", - 'length' => "harus lebih panjang dari %d", - 'min' => "harus lebih besar dari %s", - 'max' => "harus kurang dari %s", - 'in' => "berisi nilai/value yang tidak valid", - 'notIn' => "berisi nilai/value yang tidak valid", - 'ip' => "format alamat IP tidak benar", - 'email' => "format alamat email tidak benar", - 'url' => "bukan format URL yang benar", - 'urlActive' => "harus berupa domain aktif", - 'alpha' => "hanya boleh menggunakan huruf a-z", - 'alphaNum' => "hanya boleh menggunakan huruf a-z dan atau nomor 0-9", - 'slug' => "hanya boleh menggunakan huruf a-z, nomor 0-9, tanda minus (-), dan uderscore atau strip bawah (_)", - 'regex' => "berisi karakter yang tidak valid", - 'date' => "format tanggal tidak valid", + 'accepted' => 'harus diterima (accepted)', + 'numeric' => 'harus berupa nomor/angka', + 'integer' => 'harus berupa nilai integer (0-9)', + 'length' => 'harus lebih panjang dari %d', + 'min' => 'harus lebih besar dari %s', + 'max' => 'harus kurang dari %s', + 'in' => 'berisi nilai/value yang tidak valid', + 'notIn' => 'berisi nilai/value yang tidak valid', + 'ip' => 'format alamat IP tidak benar', + 'email' => 'format alamat email tidak benar', + 'url' => 'bukan format URL yang benar', + 'urlActive' => 'harus berupa domain aktif', + 'alpha' => 'hanya boleh menggunakan huruf a-z', + 'alphaNum' => 'hanya boleh menggunakan huruf a-z dan atau nomor 0-9', + 'slug' => 'hanya boleh menggunakan huruf a-z, nomor 0-9, tanda minus (-), dan uderscore atau strip bawah (_)', + 'regex' => 'berisi karakter yang tidak valid', + 'date' => 'format tanggal tidak valid', 'dateFormat' => "harus berupa tanggal dengan format '%s'", 'dateBefore' => "tanggal harus sebelum tanggal '%s'", 'dateAfter' => "tanggal harus sesudah tanggal '%s'", - 'contains' => "harus berisi %s", - 'boolean' => "harus berupa nilai boolean", - 'lengthBetween' => "harus diantara karakter %d dan %d", - 'creditCard' => "nomor kartu kredit harus valid", - "lengthMin" => "minimal berisi %d karakter", - "lengthMax" => "maksimal berisi %d karakter" -); + 'contains' => 'harus berisi %s', + 'boolean' => 'harus berupa nilai boolean', + 'lengthBetween' => 'harus diantara karakter %d dan %d', + 'creditCard' => 'nomor kartu kredit harus valid', + 'lengthMin' => 'minimal berisi %d karakter', + 'lengthMax' => 'maksimal berisi %d karakter' +]; diff --git a/app/sprinkles/core/locale/valitron/it.php b/app/sprinkles/core/locale/valitron/it.php index ee7a5c161..135bb1c1c 100644 --- a/app/sprinkles/core/locale/valitron/it.php +++ b/app/sprinkles/core/locale/valitron/it.php @@ -1,31 +1,37 @@ "è obbligatorio", +return [ + 'required' => 'è obbligatorio', 'equals' => "deve essere uguale a '%s'", 'different' => "deve essere differente da '%s'", - 'accepted' => "deve essere accettato", - 'numeric' => "deve essere numerico", - 'integer' => "deve essere un intero (0-9)", - 'length' => "deve avere una lunghezza di %d", - 'min' => "deve essere superiore a %s", - 'max' => "deve essere inferiore a %s", - 'in' => "contiene un valore non valido", - 'notIn' => "contiene un valore non valido", - 'ip' => "non è un indirizzo IP valido", - 'email' => "non è un indirizzo email valido", - 'url' => "non è una URL", - 'urlActive' => "deve essere un dominio attivo", - 'alpha' => "deve contenere solamente lettere (a-z)", - 'alphaNum' => "deve contenere solamente lettere (a-z) e/o numeri (0-9)", - 'slug' => "deve contenere solamente lettere (a-z), numeri (0-9), trattini (-) e trattini bassi (_)", - 'regex' => "contiene caratteri non validi", - 'date' => "non è una data valida", + 'accepted' => 'deve essere accettato', + 'numeric' => 'deve essere numerico', + 'integer' => 'deve essere un intero (0-9)', + 'length' => 'deve avere una lunghezza di %d', + 'min' => 'deve essere superiore a %s', + 'max' => 'deve essere inferiore a %s', + 'in' => 'contiene un valore non valido', + 'notIn' => 'contiene un valore non valido', + 'ip' => 'non è un indirizzo IP valido', + 'email' => 'non è un indirizzo email valido', + 'url' => 'non è una URL', + 'urlActive' => 'deve essere un dominio attivo', + 'alpha' => 'deve contenere solamente lettere (a-z)', + 'alphaNum' => 'deve contenere solamente lettere (a-z) e/o numeri (0-9)', + 'slug' => 'deve contenere solamente lettere (a-z), numeri (0-9), trattini (-) e trattini bassi (_)', + 'regex' => 'contiene caratteri non validi', + 'date' => 'non è una data valida', 'dateFormat' => "deve essere una data nel formato '%s'", 'dateBefore' => "deve essere una data precedente al '%s'", 'dateAfter' => "deve essere una data successiva al '%s'", - 'contains' => "deve contenere %s", - 'boolean' => "deve essere un booleano", - 'lengthBetween' => "deve essere compreso tra %d e %d caratteri", - 'creditCard' => "deve essere un numero di carta di credito valido" -); + 'contains' => 'deve contenere %s', + 'boolean' => 'deve essere un booleano', + 'lengthBetween' => 'deve essere compreso tra %d e %d caratteri', + 'creditCard' => 'deve essere un numero di carta di credito valido' +]; diff --git a/app/sprinkles/core/locale/valitron/ja.php b/app/sprinkles/core/locale/valitron/ja.php index 6fa494b9f..ae27d3193 100644 --- a/app/sprinkles/core/locale/valitron/ja.php +++ b/app/sprinkles/core/locale/valitron/ja.php @@ -1,33 +1,39 @@ "を入力してください", - 'equals' => "は「%s」と同じ内容を入力してください", - 'different' => "は「%s」と異なる内容を入力してください", - 'accepted' => "に同意してください", - 'numeric' => "は数値を入力してください", - 'integer' => "は半角数字で入力してください", - 'length' => "は%d文字で入力してください", - 'min' => "には%sより大きな値を入力してください", - 'max' => "には%sより小さな値を入力してください", - 'in' => "には選択できない値が含まれています", - 'notIn' => "には選択できない値が含まれています", - 'ip' => "はIPアドレスの書式として正しくありません", - 'email' => "はメールアドレスの書式として正しくありません", - 'url' => "はURLの書式として正しくありません", - 'urlActive' => "はアクティブなドメインではありません", - 'alpha' => "は半角英字で入力してください", - 'alphaNum' => "は半角英数字で入力してください", - 'slug' => "は半角英数字、もしくは「-」「_」の文字で入力してください", - 'regex' => "の書式が正しくありません", - 'date' => "は日付の書式として正しくありません", - 'dateFormat' => "は「%s」の書式で日付を入力してください", - 'dateBefore' => "は「%s」以前の日付を入力してください", - 'dateAfter' => "は「%s」以後の日付を入力してください", - 'contains' => "は「%s」を含んでいなければいけません", - 'boolean' => "は真偽値である必要があります", - 'lengthBetween' => "は%d〜%d文字で入力してください", - 'creditCard' => "はクレジットカード番号の書式として正しくありません", - "lengthMin" => "は%d文字以上入力してください", - "lengthMax" => "は%d文字以内で入力してください" -); +return [ + 'required' => 'を入力してください', + 'equals' => 'は「%s」と同じ内容を入力してください', + 'different' => 'は「%s」と異なる内容を入力してください', + 'accepted' => 'に同意してください', + 'numeric' => 'は数値を入力してください', + 'integer' => 'は半角数字で入力してください', + 'length' => 'は%d文字で入力してください', + 'min' => 'には%sより大きな値を入力してください', + 'max' => 'には%sより小さな値を入力してください', + 'in' => 'には選択できない値が含まれています', + 'notIn' => 'には選択できない値が含まれています', + 'ip' => 'はIPアドレスの書式として正しくありません', + 'email' => 'はメールアドレスの書式として正しくありません', + 'url' => 'はURLの書式として正しくありません', + 'urlActive' => 'はアクティブなドメインではありません', + 'alpha' => 'は半角英字で入力してください', + 'alphaNum' => 'は半角英数字で入力してください', + 'slug' => 'は半角英数字、もしくは「-」「_」の文字で入力してください', + 'regex' => 'の書式が正しくありません', + 'date' => 'は日付の書式として正しくありません', + 'dateFormat' => 'は「%s」の書式で日付を入力してください', + 'dateBefore' => 'は「%s」以前の日付を入力してください', + 'dateAfter' => 'は「%s」以後の日付を入力してください', + 'contains' => 'は「%s」を含んでいなければいけません', + 'boolean' => 'は真偽値である必要があります', + 'lengthBetween' => 'は%d〜%d文字で入力してください', + 'creditCard' => 'はクレジットカード番号の書式として正しくありません', + 'lengthMin' => 'は%d文字以上入力してください', + 'lengthMax' => 'は%d文字以内で入力してください' +]; diff --git a/app/sprinkles/core/locale/valitron/lv.php b/app/sprinkles/core/locale/valitron/lv.php index 9b5e54d31..cf4e44620 100644 --- a/app/sprinkles/core/locale/valitron/lv.php +++ b/app/sprinkles/core/locale/valitron/lv.php @@ -1,31 +1,37 @@ "ir obligāts lauks", +return [ + 'required' => 'ir obligāts lauks', 'equals' => "jāsakrīt ar '%s'", 'different' => "nedrīkst sakrist ar '%s' lauku", - 'accepted' => "laukam jābūt apstiprinātam", - 'numeric' => "jābūt skaitliskai vērtībai", - 'integer' => "jābūt ciparam (0-9)", - 'length' => "nedrīkst būt garāks par %d simboliem", - 'min' => "jābūt garākam par %s simboliem", - 'max' => "jābūt īsākam par %s simboliem", - 'in' => "lauks satur nederīgu vērtību", - 'notIn' => "lauks satur nederīgu vērtību", - 'ip' => " lauks nav derīga IP adrese", - 'email' => "lauks nav norādīta derīga epasta adrese", - 'url' => "lauks nav tīmekļa saite", - 'urlActive' => "saite neatrodas esošajā domēna vārdā", - 'alpha' => "lauks var saturēt tikai alfabēta burtus a-z", - 'alphaNum' => "lauks var saturēt tikai alfabēta burtus un/vai ciparus 0-9", - 'slug' => "lauks var saturēt tikai alfabēta burtus un/vai ciparus 0-9, domuzīmes and zemsvītras", - 'regex' => "lauks satur nederīgus simbolus", - 'date' => "lauks ir nederīgā datuma formātā", + 'accepted' => 'laukam jābūt apstiprinātam', + 'numeric' => 'jābūt skaitliskai vērtībai', + 'integer' => 'jābūt ciparam (0-9)', + 'length' => 'nedrīkst būt garāks par %d simboliem', + 'min' => 'jābūt garākam par %s simboliem', + 'max' => 'jābūt īsākam par %s simboliem', + 'in' => 'lauks satur nederīgu vērtību', + 'notIn' => 'lauks satur nederīgu vērtību', + 'ip' => ' lauks nav derīga IP adrese', + 'email' => 'lauks nav norādīta derīga epasta adrese', + 'url' => 'lauks nav tīmekļa saite', + 'urlActive' => 'saite neatrodas esošajā domēna vārdā', + 'alpha' => 'lauks var saturēt tikai alfabēta burtus a-z', + 'alphaNum' => 'lauks var saturēt tikai alfabēta burtus un/vai ciparus 0-9', + 'slug' => 'lauks var saturēt tikai alfabēta burtus un/vai ciparus 0-9, domuzīmes and zemsvītras', + 'regex' => 'lauks satur nederīgus simbolus', + 'date' => 'lauks ir nederīgā datuma formātā', 'dateFormat' => "laukam jābūt datuma formātā '%s'", 'dateBefore' => "lauka datumam jābūt pirms '%s'", 'dateAfter' => "lauka datumam jābūt pēc '%s'", - 'contains' => "laukam jāsatur %s", - 'boolean' => "laukam jābūt ir/nav vērtībai", - 'lengthBetween' => "lauka garumam jābūt no %d līdz %d simbolu garam", - 'creditCard' => "laukam jābūt derīgam kredītkartes numuram" -); + 'contains' => 'laukam jāsatur %s', + 'boolean' => 'laukam jābūt ir/nav vērtībai', + 'lengthBetween' => 'lauka garumam jābūt no %d līdz %d simbolu garam', + 'creditCard' => 'laukam jābūt derīgam kredītkartes numuram' +]; diff --git a/app/sprinkles/core/locale/valitron/pt-br.php b/app/sprinkles/core/locale/valitron/pt-br.php index 74c5660c3..2f8aa0380 100644 --- a/app/sprinkles/core/locale/valitron/pt-br.php +++ b/app/sprinkles/core/locale/valitron/pt-br.php @@ -1,28 +1,34 @@ "é obrigatório", +return [ + 'required' => 'é obrigatório', 'equals' => "deve ser o mesmo que '%s'", 'different' => "deve ser diferente de '%s'", - 'accepted' => "deve ser aceito", - 'numeric' => "deve ser um número", - 'integer' => "deve ser um inteiro (0-9)", - 'length' => "deve ter mais que %d caracteres", - 'min' => "deve ser maior que %s", - 'max' => "deve ser menor que %s", - 'in' => "contém um valor inválido", - 'notIn' => "contém um valor inválido", - 'ip' => "não é um IP válido", - 'email' => "não é um email válido", - 'url' => "não é uma URL válida", - 'urlActive' => "deve ser um domínio ativo", - 'alpha' => "deve conter as letras a-z", - 'alphaNum' => "deve conter apenas letras a-z e/ou números 0-9", - 'slug' => "deve conter apenas letras a-z, números 0-9, ou os caracteres - ou _", - 'regex' => "contém caracteres inválidos", - 'date' => "não é uma data válida", + 'accepted' => 'deve ser aceito', + 'numeric' => 'deve ser um número', + 'integer' => 'deve ser um inteiro (0-9)', + 'length' => 'deve ter mais que %d caracteres', + 'min' => 'deve ser maior que %s', + 'max' => 'deve ser menor que %s', + 'in' => 'contém um valor inválido', + 'notIn' => 'contém um valor inválido', + 'ip' => 'não é um IP válido', + 'email' => 'não é um email válido', + 'url' => 'não é uma URL válida', + 'urlActive' => 'deve ser um domínio ativo', + 'alpha' => 'deve conter as letras a-z', + 'alphaNum' => 'deve conter apenas letras a-z e/ou números 0-9', + 'slug' => 'deve conter apenas letras a-z, números 0-9, ou os caracteres - ou _', + 'regex' => 'contém caracteres inválidos', + 'date' => 'não é uma data válida', 'dateFormat' => "deve ser uma data no formato '%s'", 'dateBefore' => "deve ser uma data anterior a '%s'", 'dateAfter' => "deve ser uma data posterior a '%s'", - 'contains' => "deve conter %s" -); + 'contains' => 'deve conter %s' +]; diff --git a/app/sprinkles/core/locale/valitron/ro.php b/app/sprinkles/core/locale/valitron/ro.php index f7acce3bc..d3dc7c5f9 100644 --- a/app/sprinkles/core/locale/valitron/ro.php +++ b/app/sprinkles/core/locale/valitron/ro.php @@ -1,33 +1,40 @@ "este necesar", +/** + * UserFrosting (http://www.userfrosting.com) + * + * @link https://github.com/userfrosting/UserFrosting + * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + */ + +return [ + 'required' => 'este necesar', 'equals' => "trebuie sa fie la fel ca '%s'", 'different' => "trebuie sa fie diferit ca '%s'", - 'accepted' => "trebuie acceptat", - 'numeric' => "trebuie sa fie numeric", - 'integer' => "trebuie sa fie o cifra (0-9)", - 'length' => "trebuie sa fie mai lung de %d", - 'min' => "trebuie sa fie minim %s", - 'max' => "nu trebuie sa fie mai mare de %s", - 'in' => "contine valori invalide", - 'notIn' => "contine valori invalide", - 'ip' => "nu este o adresa de IP valida", - 'email' => "nu este o adresa de email valida", - 'url' => "nu este un URL", - 'urlActive' => "trebuie sa fie un domeniu activ", - 'alpha' => "poate contine doar litere a-z", - 'alphaNum' => "poate contine doar litere a-z si/sau numere 0-9", - 'slug' => "poate contine doar litere a-z, numere 0-9, minus si underscore", - 'regex' => "contine caractere invalide", - 'date' => "nu este o data valida", + 'accepted' => 'trebuie acceptat', + 'numeric' => 'trebuie sa fie numeric', + 'integer' => 'trebuie sa fie o cifra (0-9)', + 'length' => 'trebuie sa fie mai lung de %d', + 'min' => 'trebuie sa fie minim %s', + 'max' => 'nu trebuie sa fie mai mare de %s', + 'in' => 'contine valori invalide', + 'notIn' => 'contine valori invalide', + 'ip' => 'nu este o adresa de IP valida', + 'email' => 'nu este o adresa de email valida', + 'url' => 'nu este un URL', + 'urlActive' => 'trebuie sa fie un domeniu activ', + 'alpha' => 'poate contine doar litere a-z', + 'alphaNum' => 'poate contine doar litere a-z si/sau numere 0-9', + 'slug' => 'poate contine doar litere a-z, numere 0-9, minus si underscore', + 'regex' => 'contine caractere invalide', + 'date' => 'nu este o data valida', 'dateFormat' => "trebuie sa fie o data cu formatul '%s'", 'dateBefore' => "trebuie sa fie o data inainte de '%s'", 'dateAfter' => "trebuie sa fie o data dupa '%s'", - 'contains' => "trebuie sa contina %s", - 'boolean' => "trebuie sa fie valoare logica (boolean)", - 'lengthBetween' => "trebuie sa fie intre %d si %d caractere", - 'creditCard' => "trebuie sa fie un card de credit valid", - "lengthMin" => "trebuie sa contina mai mult de %d caractere", - "lengthMax" => "trebuie sa contina mai putin de %d caractere", - "instanceOf" => "trebuie sa fie o instanta a '%s'" -); + 'contains' => 'trebuie sa contina %s', + 'boolean' => 'trebuie sa fie valoare logica (boolean)', + 'lengthBetween' => 'trebuie sa fie intre %d si %d caractere', + 'creditCard' => 'trebuie sa fie un card de credit valid', + 'lengthMin' => 'trebuie sa contina mai mult de %d caractere', + 'lengthMax' => 'trebuie sa contina mai putin de %d caractere', + 'instanceOf' => "trebuie sa fie o instanta a '%s'" +]; diff --git a/app/sprinkles/core/locale/valitron/ru.php b/app/sprinkles/core/locale/valitron/ru.php index 78fe98fba..a7becb247 100644 --- a/app/sprinkles/core/locale/valitron/ru.php +++ b/app/sprinkles/core/locale/valitron/ru.php @@ -1,33 +1,39 @@ "обязательно для заполнения", +return [ + 'required' => 'обязательно для заполнения', 'equals' => "должно содержать '%s'", 'different' => "должно отличаться от '%s'", - 'accepted' => "должно быть указано", - 'numeric' => "должно содержать числовое значение", - 'integer' => "должно быть числом", - 'length' => "должно быть длиннее, чем %d", - 'min' => "должно быть больше, чем %s", - 'max' => "должно быть меньше, чем %s", - 'in' => "содержит неверное значение", - 'notIn' => "содержит неверное значение", - 'ip' => "не является валидным IP адресом", - 'email' => "не является валидным email адресом", - 'url' => "не является ссылкой", - 'urlActive' => "содержит не активную ссылку", - 'alpha' => "должно содержать только латинские символы", - 'alphaNum' => "должно содержать только латинские символы и/или цифры", - 'slug' => "должно содержать только латинские символы, цифры, тире и подчёркивания", - 'regex' => "содержит недопустимые символы", - 'date' => "не является датой", - 'dateFormat' => "должно содержать дату следующего формата: %s", - 'dateBefore' => "должно содержать дату не позднее, чем %s", - 'dateAfter' => "должно содержать дату не ранее, чем %s", - 'contains' => "должно содержать %s", - 'boolean' => "должно содержать логическое значение", - 'lengthBetween' => "должно содержать от %d до %d символов", - 'creditCard' => "должно быть номером кредитной карты", - "lengthMin" => "должно содержать более %d символов", - "lengthMax" => "должно содержать менее %d символов" -); + 'accepted' => 'должно быть указано', + 'numeric' => 'должно содержать числовое значение', + 'integer' => 'должно быть числом', + 'length' => 'должно быть длиннее, чем %d', + 'min' => 'должно быть больше, чем %s', + 'max' => 'должно быть меньше, чем %s', + 'in' => 'содержит неверное значение', + 'notIn' => 'содержит неверное значение', + 'ip' => 'не является валидным IP адресом', + 'email' => 'не является валидным email адресом', + 'url' => 'не является ссылкой', + 'urlActive' => 'содержит не активную ссылку', + 'alpha' => 'должно содержать только латинские символы', + 'alphaNum' => 'должно содержать только латинские символы и/или цифры', + 'slug' => 'должно содержать только латинские символы, цифры, тире и подчёркивания', + 'regex' => 'содержит недопустимые символы', + 'date' => 'не является датой', + 'dateFormat' => 'должно содержать дату следующего формата: %s', + 'dateBefore' => 'должно содержать дату не позднее, чем %s', + 'dateAfter' => 'должно содержать дату не ранее, чем %s', + 'contains' => 'должно содержать %s', + 'boolean' => 'должно содержать логическое значение', + 'lengthBetween' => 'должно содержать от %d до %d символов', + 'creditCard' => 'должно быть номером кредитной карты', + 'lengthMin' => 'должно содержать более %d символов', + 'lengthMax' => 'должно содержать менее %d символов' +]; diff --git a/app/sprinkles/core/locale/valitron/th.php b/app/sprinkles/core/locale/valitron/th.php index 95e6ba5db..ddf250987 100644 --- a/app/sprinkles/core/locale/valitron/th.php +++ b/app/sprinkles/core/locale/valitron/th.php @@ -1,34 +1,40 @@ "ต้องการ", +return [ + 'required' => 'ต้องการ', 'equals' => "จะต้องเหมือนกับ '%s'", 'different' => "จะต้องไม่ใช่ '%s'", - 'accepted' => "จะต้องยอมรับ", - 'numeric' => "จะต้องเป็นตัวเลข", - 'integer' => "จะต้องเป็นตัวเลขหลักเดียว (0-9)", - 'length' => "จะต้องมีความยาวมากกว่า %d", - 'min' => "จะต้องมีอย่างน้อย %s", - 'max' => "จะต้องมีไม่มากไปกว่า %s", - 'in' => "ประกอบด้วยค่าที่ไม่ถูกต้อง", - 'notIn' => "ประกอบด้วยค่าที่ไม่ถูกต้อง", - 'ip' => "ไม่ใช่ที่อยู่ไอพีที่ถูกต้อง", - 'email' => "ไม่ใช่ที่อยู่อีเมลที่ถูกต้อง", - 'url' => "ไม่ใช่ลิงก์", - 'urlActive' => "จะต้องเป็นโดเมนที่มีการใช้งานอยู่", - 'alpha' => "จะต้องประกอบไปด้วยตัวอักษร a-z เท่านั้น", - 'alphaNum' => "จะต้องประกอบไปด้วยตัวอักษร a-z และ/หรือ เลข 0-9", - 'slug' => "จะต้องประกอบไปด้วยตัวอักษร a-z เลข 0-9 ขีดกลาง และขีดล่าง", - 'regex' => "ประกอบด้วยอักขระที่ไม่ถูกต้อง", - 'date' => "ไม่ใช่วันที่ที่ถูกต้อง", + 'accepted' => 'จะต้องยอมรับ', + 'numeric' => 'จะต้องเป็นตัวเลข', + 'integer' => 'จะต้องเป็นตัวเลขหลักเดียว (0-9)', + 'length' => 'จะต้องมีความยาวมากกว่า %d', + 'min' => 'จะต้องมีอย่างน้อย %s', + 'max' => 'จะต้องมีไม่มากไปกว่า %s', + 'in' => 'ประกอบด้วยค่าที่ไม่ถูกต้อง', + 'notIn' => 'ประกอบด้วยค่าที่ไม่ถูกต้อง', + 'ip' => 'ไม่ใช่ที่อยู่ไอพีที่ถูกต้อง', + 'email' => 'ไม่ใช่ที่อยู่อีเมลที่ถูกต้อง', + 'url' => 'ไม่ใช่ลิงก์', + 'urlActive' => 'จะต้องเป็นโดเมนที่มีการใช้งานอยู่', + 'alpha' => 'จะต้องประกอบไปด้วยตัวอักษร a-z เท่านั้น', + 'alphaNum' => 'จะต้องประกอบไปด้วยตัวอักษร a-z และ/หรือ เลข 0-9', + 'slug' => 'จะต้องประกอบไปด้วยตัวอักษร a-z เลข 0-9 ขีดกลาง และขีดล่าง', + 'regex' => 'ประกอบด้วยอักขระที่ไม่ถูกต้อง', + 'date' => 'ไม่ใช่วันที่ที่ถูกต้อง', 'dateFormat' => "จะต้องเป็นวันที่ที่มีรูปแบบ '%s'", 'dateBefore' => "จะต้องเป็นวันที่ก่อน '%s'", 'dateAfter' => "จะต้องเป็นวันที่หลังจาก '%s'", - 'contains' => "จะต้องประกอบไปด้วย %s", - 'boolean' => "จะต้องเป็นใช่ หรือ ไม่ใช่", - 'lengthBetween' => "จะต้องอยู่ระหว่าง %d ถึง %d ตัวอักษร", - 'creditCard' => "จะต้องเป็นหมายเลขบัตรเครดิตที่ถูกต้อง", - "lengthMin" => "จะต้องมีความยาวมากกว่า %d ตัวอักษร", - "lengthMax" => "จะต้องมีความยาวน้อยกว่า %d ตัวอักษร", - "instanceOf" => "จะต้องเป็นกรณีของ '%s'" -); + 'contains' => 'จะต้องประกอบไปด้วย %s', + 'boolean' => 'จะต้องเป็นใช่ หรือ ไม่ใช่', + 'lengthBetween' => 'จะต้องอยู่ระหว่าง %d ถึง %d ตัวอักษร', + 'creditCard' => 'จะต้องเป็นหมายเลขบัตรเครดิตที่ถูกต้อง', + 'lengthMin' => 'จะต้องมีความยาวมากกว่า %d ตัวอักษร', + 'lengthMax' => 'จะต้องมีความยาวน้อยกว่า %d ตัวอักษร', + 'instanceOf' => "จะต้องเป็นกรณีของ '%s'" +]; diff --git a/app/sprinkles/core/locale/valitron/zh-cn.php b/app/sprinkles/core/locale/valitron/zh-cn.php index 4471ba827..6e38a4cfe 100644 --- a/app/sprinkles/core/locale/valitron/zh-cn.php +++ b/app/sprinkles/core/locale/valitron/zh-cn.php @@ -1,28 +1,34 @@ "不能为空", +return [ + 'required' => '不能为空', 'equals' => "必须和 '%s' 一致", 'different' => "必须和 '%s' 不一致", - 'accepted' => "必须接受", - 'numeric' => "只能是数字", - 'integer' => "只能是整数(0-9)", - 'length' => "长度必须大于 %d", - 'min' => "必须大于 %s", - 'max' => "必须小于 %s", - 'in' => "无效的值", - 'notIn' => "无效的值", - 'ip' => "无效IP地址", - 'email' => "无效邮箱地址", - 'url' => "无效的URL", - 'urlActive' => "必须是可用的域名", - 'alpha' => "只能包括英文字母(a-z)", - 'alphaNum' => "只能包括英文字母(a-z)和数字(0-9)", - 'slug' => "只能包括英文字母(a-z)、数字(0-9)、破折号和下划线", - 'regex' => "无效格式", - 'date' => "无效的日期", + 'accepted' => '必须接受', + 'numeric' => '只能是数字', + 'integer' => '只能是整数(0-9)', + 'length' => '长度必须大于 %d', + 'min' => '必须大于 %s', + 'max' => '必须小于 %s', + 'in' => '无效的值', + 'notIn' => '无效的值', + 'ip' => '无效IP地址', + 'email' => '无效邮箱地址', + 'url' => '无效的URL', + 'urlActive' => '必须是可用的域名', + 'alpha' => '只能包括英文字母(a-z)', + 'alphaNum' => '只能包括英文字母(a-z)和数字(0-9)', + 'slug' => '只能包括英文字母(a-z)、数字(0-9)、破折号和下划线', + 'regex' => '无效格式', + 'date' => '无效的日期', 'dateFormat' => "日期的格式应该为 '%s'", 'dateBefore' => "日期必须在 '%s' 之前", 'dateAfter' => "日期必须在 '%s' 之后", - 'contains' => "必须包含 %s" -); + 'contains' => '必须包含 %s' +]; diff --git a/app/sprinkles/core/locale/valitron/zh-tw.php b/app/sprinkles/core/locale/valitron/zh-tw.php index df702c566..108a37ce7 100644 --- a/app/sprinkles/core/locale/valitron/zh-tw.php +++ b/app/sprinkles/core/locale/valitron/zh-tw.php @@ -1,28 +1,34 @@ "不能為空", +return [ + 'required' => '不能為空', 'equals' => "必須和 '%s' 一致", 'different' => "必須和 '%s' 不一致", - 'accepted' => "必須接受", - 'numeric' => "只能是數字", - 'integer' => "只能是整數(0-9)", - 'length' => "長度必須大於 %d", - 'min' => "必須大於 %s", - 'max' => "必須小於 %s", - 'in' => "無效的值", - 'notIn' => "無效的值", - 'ip' => "無效IP地址", - 'email' => "無效郵箱地址", - 'url' => "無效的URL", - 'urlActive' => "必須是可用的域名", - 'alpha' => "只能包括英文字母(a-z)", - 'alphaNum' => "只能包括英文字母(a-z)和數字(0-9)", - 'slug' => "只能包括英文字母(a-z)、數字(0-9)、破折號和下劃線", - 'regex' => "無效格式", - 'date' => "無效的日期", + 'accepted' => '必須接受', + 'numeric' => '只能是數字', + 'integer' => '只能是整數(0-9)', + 'length' => '長度必須大於 %d', + 'min' => '必須大於 %s', + 'max' => '必須小於 %s', + 'in' => '無效的值', + 'notIn' => '無效的值', + 'ip' => '無效IP地址', + 'email' => '無效郵箱地址', + 'url' => '無效的URL', + 'urlActive' => '必須是可用的域名', + 'alpha' => '只能包括英文字母(a-z)', + 'alphaNum' => '只能包括英文字母(a-z)和數字(0-9)', + 'slug' => '只能包括英文字母(a-z)、數字(0-9)、破折號和下劃線', + 'regex' => '無效格式', + 'date' => '無效的日期', 'dateFormat' => "日期的格式應該為 '%s'", 'dateBefore' => "日期必須在 '%s' 之前", 'dateAfter' => "日期必須在 '%s' 之後", - 'contains' => "必須包含 %s" -); + 'contains' => '必須包含 %s' +]; diff --git a/app/sprinkles/core/locale/zh_CN/errors.php b/app/sprinkles/core/locale/zh_CN/errors.php index 9192e32e9..1acd339f9 100644 --- a/app/sprinkles/core/locale/zh_CN/errors.php +++ b/app/sprinkles/core/locale/zh_CN/errors.php @@ -4,46 +4,46 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Chinese message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\zh_CN * @author @BruceGui (https://github.com/BruceGui) */ - return [ - "ERROR" => [ - "@TRANSLATION" => "错误", + 'ERROR' => [ + '@TRANSLATION' => '错误', - "400" => [ - "TITLE" => "错误 400: 无效请求", - "DESCRIPTION" => "这好像不是你的错.", + '400' => [ + 'TITLE' => '错误 400: 无效请求', + 'DESCRIPTION' => '这好像不是你的错.', ], - "404" => [ - "TITLE" => "错误 404: 页面丢失", - "DESCRIPTION" => "我们无法找到你想要的东西.", - "DETAIL" => "我们正努力寻找网页...", - "EXPLAIN" => "我们无法找到你想要的网页.", - "RETURN" => '不管怎样, 点击 这里 返回前一页.' + '404' => [ + 'TITLE' => '错误 404: 页面丢失', + 'DESCRIPTION' => '我们无法找到你想要的东西.', + 'DETAIL' => '我们正努力寻找网页...', + 'EXPLAIN' => '我们无法找到你想要的网页.', + 'RETURN' => '不管怎样, 点击 这里 返回前一页.' ], - "CONFIG" => [ - "TITLE" => "UserFrosting 配置问题!", - "DESCRIPTION" => "一些 UserFrosting 配置要求没有达到.", - "DETAIL" => "这里有些东西不正确.", - "RETURN" => '请更正如下问题, 然后 重新加载.' + 'CONFIG' => [ + 'TITLE' => 'UserFrosting 配置问题!', + 'DESCRIPTION' => '一些 UserFrosting 配置要求没有达到.', + 'DETAIL' => '这里有些东西不正确.', + 'RETURN' => '请更正如下问题, 然后 重新加载.' ], - "DESCRIPTION" => "我们发现一股强力干扰.", - "DETAIL" => "下面是我们得到的信息:", + 'DESCRIPTION' => '我们发现一股强力干扰.', + 'DETAIL' => '下面是我们得到的信息:', - "ENCOUNTERED" => "嗯...发生了一些情况. 然而我们并不知道这是什么.", + 'ENCOUNTERED' => '嗯...发生了一些情况. 然而我们并不知道这是什么.', - "RETURN" => '点击返回上一页.', + 'RETURN' => '点击返回上一页.', - "SERVER" => "哦, 看起来我们的服务器出错了. 如果你是管理员, 请检查PHP及UF的logs.", + 'SERVER' => '哦, 看起来我们的服务器出错了. 如果你是管理员, 请检查PHP及UF的logs.', - "TITLE" => "强力干扰" + 'TITLE' => '强力干扰' ] ]; diff --git a/app/sprinkles/core/locale/zh_CN/messages.php b/app/sprinkles/core/locale/zh_CN/messages.php index ecbde8423..564630035 100644 --- a/app/sprinkles/core/locale/zh_CN/messages.php +++ b/app/sprinkles/core/locale/zh_CN/messages.php @@ -4,102 +4,102 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Chinese message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\zh_CN * @author @BruceGui (https://github.com/BruceGui) */ - return [ - "@PLURAL_RULE" => 0, + '@PLURAL_RULE' => 0, - "ABOUT" => "关于", + 'ABOUT' => '关于', - "CAPTCHA" => [ - "@TRANSLATION" => "验证码", - "FAIL" => "Y验证码输入错误.", - "SPECIFY" => "输入验证码", - "VERIFY" => "验证" + 'CAPTCHA' => [ + '@TRANSLATION' => '验证码', + 'FAIL' => 'Y验证码输入错误.', + 'SPECIFY' => '输入验证码', + 'VERIFY' => '验证' ], - "CSRF_MISSING" => " CSRF 标记丢失. 请尝试重新加载页面?", + 'CSRF_MISSING' => ' CSRF 标记丢失. 请尝试重新加载页面?', - "DB_INVALID" => "无法连接到数据库. 如果你是管理员, 请检查错误日志文件.", - "DESCRIPTION" => "描述", - "DOWNLOAD" => [ - "@TRANSLATION" => "下载", - "CSV" => "下载 CSV 文件" + 'DB_INVALID' => '无法连接到数据库. 如果你是管理员, 请检查错误日志文件.', + 'DESCRIPTION' => '描述', + 'DOWNLOAD' => [ + '@TRANSLATION' => '下载', + 'CSV' => '下载 CSV 文件' ], - "EMAIL" => [ - "@TRANSLATION" => "邮件", - "YOUR" => "你的邮件地址" + 'EMAIL' => [ + '@TRANSLATION' => '邮件', + 'YOUR' => '你的邮件地址' ], - "HOME" => "首页", + 'HOME' => '首页', - "LEGAL" => "法律政策", + 'LEGAL' => '法律政策', - "LOCALE" => [ - "@TRANSLATION" => "本地" + 'LOCALE' => [ + '@TRANSLATION' => '本地' ], - "MAIL_ERROR" => "尝试发送邮件发送致命错误, 联系网站管理员. 如果你是管理员,请检查UF邮件错误日志.", + 'MAIL_ERROR' => '尝试发送邮件发送致命错误, 联系网站管理员. 如果你是管理员,请检查UF邮件错误日志.', - "NAME" => "名字", - "NAVIGATION" => "导航", + 'NAME' => '名字', + 'NAVIGATION' => '导航', - "PAGINATION" => [ - "GOTO" => "跳到页", - "SHOW" => "显示" + 'PAGINATION' => [ + 'GOTO' => '跳到页', + 'SHOW' => '显示' ], - "PRIVACY" => "隐私政策", + 'PRIVACY' => '隐私政策', - "SLUG" => "Slug", - "SLUG_CONDITION" => "Slug/Conditions", - "SLUG_IN_USE" => "A {{slug}} slug already exists", - "STATUS" => "状态", - "SUGGEST" => "建议", + 'SLUG' => 'Slug', + 'SLUG_CONDITION' => 'Slug/Conditions', + 'SLUG_IN_USE' => 'A {{slug}} slug already exists', + 'STATUS' => '状态', + 'SUGGEST' => '建议', - "UNKNOWN" => "未知", + 'UNKNOWN' => '未知', // Actions words - "ACTIONS" => "动作", - "ACTIVATE" => "激活", - "ACTIVE" => "Active", - "ADD" => "添加", - "CANCEL" => "取消", - "CONFIRM" => "确认", - "CREATE" => "创建", - "DELETE" => "删除", - "DELETE_CONFIRM" => "你确定要删除这个?", - "DELETE_CONFIRM_YES" => "是的, 删除", - "DELETE_CONFIRM_NAMED" => "你确定要删除 {{name}}?", - "DELETE_CONFIRM_YES_NAMED" => "是的, 删除 {{name}}", - "DELETE_CANNOT_UNDONE" => "这个动作无法撤销.", - "DELETE_NAMED" => "删除 {{name}}", - "DENY" => "拒绝", - "DISABLE" => "禁用", - "DISABLED" => "禁用", - "EDIT" => "编辑", - "ENABLE" => "启用", - "ENABLED" => "启用", - "OVERRIDE" => "覆盖", - "RESET" => "重置", - "SAVE" => "保存", - "SEARCH" => "搜寻", - "SORT" => "排序", - "SUBMIT" => "提交", - "PRINT" => "打印", - "REMOVE" => "删除", - "UNACTIVATED" => "未激活", - "UPDATE" => "更新", - "YES" => "是", - "NO" => "不是", - "OPTIONAL" => "可选择的", + 'ACTIONS' => '动作', + 'ACTIVATE' => '激活', + 'ACTIVE' => 'Active', + 'ADD' => '添加', + 'CANCEL' => '取消', + 'CONFIRM' => '确认', + 'CREATE' => '创建', + 'DELETE' => '删除', + 'DELETE_CONFIRM' => '你确定要删除这个?', + 'DELETE_CONFIRM_YES' => '是的, 删除', + 'DELETE_CONFIRM_NAMED' => '你确定要删除 {{name}}?', + 'DELETE_CONFIRM_YES_NAMED' => '是的, 删除 {{name}}', + 'DELETE_CANNOT_UNDONE' => '这个动作无法撤销.', + 'DELETE_NAMED' => '删除 {{name}}', + 'DENY' => '拒绝', + 'DISABLE' => '禁用', + 'DISABLED' => '禁用', + 'EDIT' => '编辑', + 'ENABLE' => '启用', + 'ENABLED' => '启用', + 'OVERRIDE' => '覆盖', + 'RESET' => '重置', + 'SAVE' => '保存', + 'SEARCH' => '搜寻', + 'SORT' => '排序', + 'SUBMIT' => '提交', + 'PRINT' => '打印', + 'REMOVE' => '删除', + 'UNACTIVATED' => '未激活', + 'UPDATE' => '更新', + 'YES' => '是', + 'NO' => '不是', + 'OPTIONAL' => '可选择的', // Misc. - "BUILT_WITH_UF" => "使用 UserFrosting", - "ADMINLTE_THEME_BY" => "主题作者 Almsaeed Studio.保留所有权" + 'BUILT_WITH_UF' => '使用 UserFrosting', + 'ADMINLTE_THEME_BY' => '主题作者 Almsaeed Studio.保留所有权' ]; diff --git a/app/sprinkles/core/locale/zh_CN/validate.php b/app/sprinkles/core/locale/zh_CN/validate.php index f4b3ed8da..667094fdf 100644 --- a/app/sprinkles/core/locale/zh_CN/validate.php +++ b/app/sprinkles/core/locale/zh_CN/validate.php @@ -4,26 +4,26 @@ * * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) - * + */ + +/** * Chinese message token translations for the 'core' sprinkle. * - * @package userfrosting\i18n\zh_CN * @author @BruceGui (https://github.com/BruceGui) */ - return [ - "VALIDATE" => [ - "ARRAY" => " {{label}} 的值必须在一个数组中.", - "BOOLEAN" => " {{label}} 的值必须是 '0' 或 '1'.", - "INTEGER" => " {{label}} 必须是整数.", - "INVALID_EMAIL" => "无效的邮箱地址.", - "LENGTH_RANGE" => "{{label}} 的长度必须在 {{min}} - {{max}} 之间.", - "NO_LEAD_WS" => "{{label}} 的值不能以空格、TAB或其他空白开始.", - "NO_TRAIL_WS" => " {{label}} 的值不能以空格、TAB或其他空白结束.", - "REQUIRED" => "请为 {{label}} 确定一个值.", - "SPRUNJE" => [ - "BAD_FILTER" => "{{name}} 不是一个有效的 Sprunje 过滤器.", - "BAD_SORT" => "{{name}} 不是一个有效的 Sprunje 排序." + 'VALIDATE' => [ + 'ARRAY' => ' {{label}} 的值必须在一个数组中.', + 'BOOLEAN' => " {{label}} 的值必须是 '0' 或 '1'.", + 'INTEGER' => ' {{label}} 必须是整数.', + 'INVALID_EMAIL' => '无效的邮箱地址.', + 'LENGTH_RANGE' => '{{label}} 的长度必须在 {{min}} - {{max}} 之间.', + 'NO_LEAD_WS' => '{{label}} 的值不能以空格、TAB或其他空白开始.', + 'NO_TRAIL_WS' => ' {{label}} 的值不能以空格、TAB或其他空白结束.', + 'REQUIRED' => '请为 {{label}} 确定一个值.', + 'SPRUNJE' => [ + 'BAD_FILTER' => '{{name}} 不是一个有效的 Sprunje 过滤器.', + 'BAD_SORT' => '{{name}} 不是一个有效的 Sprunje 排序.' ] ] ]; diff --git a/app/sprinkles/core/routes/routes.php b/app/sprinkles/core/routes/routes.php index af360064f..dd198778e 100755 --- a/app/sprinkles/core/routes/routes.php +++ b/app/sprinkles/core/routes/routes.php @@ -5,7 +5,6 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ - global $app; $config = $app->getContainer()->get('config'); diff --git a/app/sprinkles/core/src/Alert/AlertStream.php b/app/sprinkles/core/src/Alert/AlertStream.php index dda2c73f2..1d01075cd 100644 --- a/app/sprinkles/core/src/Alert/AlertStream.php +++ b/app/sprinkles/core/src/Alert/AlertStream.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Alert; use UserFrosting\Fortress\ServerSideValidator; @@ -33,7 +34,7 @@ abstract class AlertStream /** * Create a new message stream. * - * @param string $messagesKey + * @param string $messagesKey * @param \UserFrosting\I18n\MessageTranslator|null $translator */ public function __construct($messagesKey, MessageTranslator $translator = null) @@ -45,49 +46,52 @@ public function __construct($messagesKey, MessageTranslator $translator = null) /** * Set the translator to be used for all message streams. Must be done before `addMessageTranslated` can be used. * - * @param \UserFrosting\I18n\MessageTranslator $translator A MessageTranslator to be used to translate messages when added via `addMessageTranslated`. + * @param \UserFrosting\I18n\MessageTranslator $translator A MessageTranslator to be used to translate messages when added via `addMessageTranslated`. * @return self */ public function setTranslator(MessageTranslator $translator) { $this->messageTranslator = $translator; + return $this; } /** * Adds a raw text message to the cache message stream. * - * @param string $type The type of message, indicating how it will be styled when outputted. Should be set to "success", "danger", "warning", or "info". - * @param string $message The message to be added to the message stream. - * @return self this MessageStream object. + * @param string $type The type of message, indicating how it will be styled when outputted. Should be set to "success", "danger", "warning", or "info". + * @param string $message The message to be added to the message stream. + * @return self this MessageStream object. */ public function addMessage($type, $message) { $messages = $this->messages(); - $messages[] = array( - "type" => $type, - "message" => $message - ); + $messages[] = [ + 'type' => $type, + 'message' => $message + ]; $this->saveMessages($messages); + return $this; } /** * Adds a text message to the cache message stream, translated into the currently selected language. * - * @param string $type The type of message, indicating how it will be styled when outputted. Should be set to "success", "danger", "warning", or "info". - * @param string $messageId The message id for the message to be added to the message stream. - * @param array[string] $placeholders An optional hash of placeholder names => placeholder values to substitute into the translated message. + * @param string $type The type of message, indicating how it will be styled when outputted. Should be set to "success", "danger", "warning", or "info". + * @param string $messageId The message id for the message to be added to the message stream. + * @param array[string] $placeholders An optional hash of placeholder names => placeholder values to substitute into the translated message. * @throws \RuntimeException - * @return self this MessageStream object. + * @return self this MessageStream object. */ - public function addMessageTranslated($type, $messageId, $placeholders = array()) + public function addMessageTranslated($type, $messageId, $placeholders = []) { if (!$this->messageTranslator) { - throw new \RuntimeException("No translator has been set! Please call MessageStream::setTranslator first."); + throw new \RuntimeException('No translator has been set! Please call MessageStream::setTranslator first.'); } $message = $this->messageTranslator->translate($messageId, $placeholders); + return $this->addMessage($type, $message); } @@ -102,6 +106,7 @@ public function getAndClearMessages() { $messages = $this->messages(); $this->resetMessageStream(); + return $messages; } @@ -114,7 +119,7 @@ public function addValidationErrors(ServerSideValidator $validator) { foreach ($validator->errors() as $idx => $field) { foreach ($field as $eidx => $error) { - $this->addMessage("danger", $error); + $this->addMessage('danger', $error); } } } diff --git a/app/sprinkles/core/src/Alert/CacheAlertStream.php b/app/sprinkles/core/src/Alert/CacheAlertStream.php index 433d719f0..76c8f010c 100644 --- a/app/sprinkles/core/src/Alert/CacheAlertStream.php +++ b/app/sprinkles/core/src/Alert/CacheAlertStream.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Alert; use Illuminate\Cache\Repository as Cache; @@ -35,10 +36,10 @@ class CacheAlertStream extends AlertStream /** * Create a new message stream. * - * @param string $messagesKey Store the messages under this key + * @param string $messagesKey Store the messages under this key * @param MessageTranslator|null $translator - * @param Cache $cache - * @param Repository $config + * @param Cache $cache + * @param Repository $config */ public function __construct($messagesKey, MessageTranslator $translator = null, Cache $cache, Repository $config) { @@ -72,7 +73,7 @@ public function resetMessageStream() /** * Save messages to the stream * - * @param string $messages The message + * @param string $messages The message */ protected function saveMessages($messages) { diff --git a/app/sprinkles/core/src/Alert/SessionAlertStream.php b/app/sprinkles/core/src/Alert/SessionAlertStream.php index 01bcbb6d0..7b5ae746d 100644 --- a/app/sprinkles/core/src/Alert/SessionAlertStream.php +++ b/app/sprinkles/core/src/Alert/SessionAlertStream.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Alert; use UserFrosting\I18n\MessageTranslator; @@ -27,9 +28,9 @@ class SessionAlertStream extends AlertStream /** * Create a new message stream. * - * @param string $messagesKey Store the messages under this key + * @param string $messagesKey Store the messages under this key * @param MessageTranslator|null $translator - * @param Session $session + * @param Session $session */ public function __construct($messagesKey, MessageTranslator $translator = null, Session $session) { @@ -58,7 +59,7 @@ public function resetMessageStream() /** * Save messages to the stream * - * @param string $messages The message + * @param string $messages The message */ protected function saveMessages($messages) { diff --git a/app/sprinkles/core/src/Bakery/BakeCommand.php b/app/sprinkles/core/src/Bakery/BakeCommand.php index 3144bc07e..115a3eadb 100644 --- a/app/sprinkles/core/src/Bakery/BakeCommand.php +++ b/app/sprinkles/core/src/Bakery/BakeCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; @@ -42,9 +43,9 @@ class BakeCommand extends BaseCommand */ protected function configure() { - $this->setName("bake") - ->setDescription("UserFrosting installation command") - ->setHelp("This command combine the debug, migrate and build-assets commands."); + $this->setName('bake') + ->setDescription('UserFrosting installation command') + ->setHelp('This command combine the debug, migrate and build-assets commands.'); } /** diff --git a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php index d88e0a1bb..210cbc0af 100644 --- a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php +++ b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; @@ -24,8 +25,8 @@ class ClearCacheCommand extends BaseCommand */ protected function configure() { - $this->setName("clear-cache") - ->setDescription("Clears the application cache. Includes cache service, Twig and Router cached data"); + $this->setName('clear-cache') + ->setDescription('Clears the application cache. Includes cache service, Twig and Router cached data'); } /** @@ -33,28 +34,28 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Clearing cache"); + $this->io->title('Clearing cache'); // Clear normal cache - $this->io->writeln(" > Clearing Illuminate cache instance", OutputInterface::VERBOSITY_VERBOSE); + $this->io->writeln(' > Clearing Illuminate cache instance', OutputInterface::VERBOSITY_VERBOSE); $this->clearIlluminateCache(); // Clear Twig cache - $this->io->writeln(" > Clearing Twig cached data", OutputInterface::VERBOSITY_VERBOSE); + $this->io->writeln(' > Clearing Twig cached data', OutputInterface::VERBOSITY_VERBOSE); if (!$this->clearTwigCache()) { - $this->io->error("Failed to clear Twig cached data. Make sure you have write access to the `app/cache/twig` directory."); + $this->io->error('Failed to clear Twig cached data. Make sure you have write access to the `app/cache/twig` directory.'); exit(1); } // Clear router cache - $this->io->writeln(" > Clearing Router cache file", OutputInterface::VERBOSITY_VERBOSE); + $this->io->writeln(' > Clearing Router cache file', OutputInterface::VERBOSITY_VERBOSE); if (!$this->clearRouterCache()) { $file = $this->ci->config['settings.routerCacheFile']; $this->io->error("Failed to delete Router cache file. Make sure you have write access to the `$file` file."); exit(1); } - $this->io->success("Cache cleared !"); + $this->io->success('Cache cleared !'); } /** @@ -73,6 +74,7 @@ protected function clearIlluminateCache() protected function clearTwigCache() { $cacheHelper = new CacheHelper($this->ci); + return $cacheHelper->clearCache(); } diff --git a/app/sprinkles/core/src/Bakery/DebugCommand.php b/app/sprinkles/core/src/Bakery/DebugCommand.php index 9608019a6..b4b30ba72 100644 --- a/app/sprinkles/core/src/Bakery/DebugCommand.php +++ b/app/sprinkles/core/src/Bakery/DebugCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; @@ -26,8 +27,8 @@ class DebugCommand extends BaseCommand */ protected function configure() { - $this->setName("debug") - ->setDescription("Test the UserFrosting installation and setup the database") + $this->setName('debug') + ->setDescription('Test the UserFrosting installation and setup the database') ->setHelp("This command is used to check if the various dependencies of UserFrosting are met and display useful debugging information. \nIf any error occurs, check out the online documentation for more info about that error. \nThis command also provide the necessary tools to setup the database credentials"); } @@ -37,14 +38,14 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { // Display header, - $this->io->title("UserFrosting"); - $this->io->writeln("UserFrosing version : " . \UserFrosting\VERSION); - $this->io->writeln("OS Name : " . php_uname('s')); - $this->io->writeln("Project Root : " . \UserFrosting\ROOT_DIR); + $this->io->title('UserFrosting'); + $this->io->writeln('UserFrosing version : ' . \UserFrosting\VERSION); + $this->io->writeln('OS Name : ' . php_uname('s')); + $this->io->writeln('Project Root : ' . \UserFrosting\ROOT_DIR); // Need to touch the config service first to load dotenv values $config = $this->ci->config; - $this->io->writeln("Environment mode : " . getenv("UF_MODE")); + $this->io->writeln('Environment mode : ' . getenv('UF_MODE')); // Perform tasks $this->checkPhpVersion(); @@ -55,7 +56,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->checkDatabase(); // If all went well and there's no fatal errors, we are ready to bake - $this->io->success("Ready to bake !"); + $this->io->success('Ready to bake !'); } /** @@ -64,15 +65,15 @@ protected function execute(InputInterface $input, OutputInterface $output) */ protected function checkPhpVersion() { - $this->io->writeln("PHP Version : " . phpversion()); + $this->io->writeln('PHP Version : ' . phpversion()); if (version_compare(phpversion(), \UserFrosting\PHP_MIN_VERSION, '<')) { - $this->io->error("UserFrosting requires php version ".\UserFrosting\PHP_MIN_VERSION." or above. You'll need to update you PHP version before you can continue."); + $this->io->error('UserFrosting requires php version '.\UserFrosting\PHP_MIN_VERSION." or above. You'll need to update you PHP version before you can continue."); exit(1); } // Check for deprecated versions if (version_compare(phpversion(), \UserFrosting\PHP_RECOMMENDED_VERSION, '<')) { - $this->io->warning("While your PHP version is still supported by UserFrosting, we recommends version ".\UserFrosting\PHP_RECOMMENDED_VERSION." or above as ".phpversion()." will soon be unsupported. See http://php.net/supported-versions.php for more info."); + $this->io->warning('While your PHP version is still supported by UserFrosting, we recommends version '.\UserFrosting\PHP_RECOMMENDED_VERSION.' or above as '.phpversion().' will soon be unsupported. See http://php.net/supported-versions.php for more info.'); } } @@ -85,7 +86,7 @@ protected function checkNodeVersion() $this->io->writeln("Node Version : $npmVersion"); if (version_compare($npmVersion, 'v4', '<')) { - $this->io->error("UserFrosting requires Node version 4.x or above. Check the documentation for more details."); + $this->io->error('UserFrosting requires Node version 4.x or above. Check the documentation for more details.'); exit(1); } } @@ -99,7 +100,7 @@ protected function checkNpmVersion() $this->io->writeln("NPM Version : $npmVersion"); if (version_compare($npmVersion, '3', '<')) { - $this->io->error("UserFrosting requires npm version 3.x or above. Check the documentation for more details."); + $this->io->error('UserFrosting requires npm version 3.x or above. Check the documentation for more details.'); exit(1); } } @@ -119,11 +120,11 @@ protected function listSprinkles() // List installed sprinkles $sprinkles = json_decode($sprinklesFile)->base; - $this->io->section("Loaded sprinkles"); + $this->io->section('Loaded sprinkles'); $this->io->listing($sprinkles); // Throw fatal error if the `core` sprinkle is missing - if (!in_array("core", $sprinkles)) { + if (!in_array('core', $sprinkles)) { $this->io->error("The `core` sprinkle is missing from the 'sprinkles.json' file."); exit(1); } @@ -135,11 +136,12 @@ protected function listSprinkles() */ protected function checkDatabase() { - $this->io->section("Testing database connection..."); + $this->io->section('Testing database connection...'); try { $this->testDB(); - $this->io->writeln("Database connection successful"); + $this->io->writeln('Database connection successful'); + return; } catch (\Exception $e) { $error = $e->getMessage(); @@ -157,14 +159,14 @@ protected function showConfig() $config = $this->ci->config; // Display database info - $this->io->section("Database config"); + $this->io->section('Database config'); $this->io->writeln([ - "DRIVER : " . $config['db.default.driver'], - "HOST : " . $config['db.default.host'], - "PORT : " . $config['db.default.port'], - "DATABASE : " . $config['db.default.database'], - "USERNAME : " . $config['db.default.username'], - "PASSWORD : " . ($config['db.default.password'] ? "*********" : "") + 'DRIVER : ' . $config['db.default.driver'], + 'HOST : ' . $config['db.default.host'], + 'PORT : ' . $config['db.default.port'], + 'DATABASE : ' . $config['db.default.database'], + 'USERNAME : ' . $config['db.default.username'], + 'PASSWORD : ' . ($config['db.default.password'] ? '*********' : '') ]); } } diff --git a/app/sprinkles/core/src/Bakery/MigrateCommand.php b/app/sprinkles/core/src/Bakery/MigrateCommand.php index bfbe547a4..3340b2593 100644 --- a/app/sprinkles/core/src/Bakery/MigrateCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; @@ -28,9 +29,9 @@ class MigrateCommand extends BaseCommand */ protected function configure() { - $this->setName("migrate") - ->setDescription("Perform database migration") - ->setHelp("This command runs all the pending database migrations.") + $this->setName('migrate') + ->setDescription('Perform database migration') + ->setHelp('This command runs all the pending database migrations.') ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') @@ -66,16 +67,16 @@ protected function execute(InputInterface $input, OutputInterface $output) // If all went well, there's no fatal errors and we have migrated // something, show some success if (empty($migrated)) { - $this->io->success("Nothing to migrate"); + $this->io->success('Nothing to migrate'); } else { - $this->io->success("Migration successful !"); + $this->io->success('Migration successful !'); } } /** * Setup migrator and the shared options between other command * - * @param InputInterface $input + * @param InputInterface $input * @return \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator The migrator instance */ protected function setupMigrator(InputInterface $input) @@ -90,7 +91,7 @@ protected function setupMigrator(InputInterface $input) // Set connection to the selected database $database = $input->getOption('database'); - if ($database != "") { + if ($database != '') { $this->io->note("Running {$this->getName()} with `$database` database connection"); $this->ci->db->getDatabaseManager()->setDefaultConnection($database); } diff --git a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php index 7d95f8d6c..2f421d86d 100644 --- a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php @@ -5,12 +5,12 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputOption; -use UserFrosting\Sprinkle\Core\Bakery\MigrateCommand; /** * migrate:refresh Bakery Command. @@ -25,8 +25,8 @@ class MigrateRefreshCommand extends MigrateCommand */ protected function configure() { - $this->setName("migrate:refresh") - ->setDescription("Rollback the last migration operation and run it up again") + $this->setName('migrate:refresh') + ->setDescription('Rollback the last migration operation and run it up again') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') ->addOption('steps', 's', InputOption::VALUE_REQUIRED, 'Number of batch to rollback', 1); @@ -37,7 +37,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Migration refresh"); + $this->io->title('Migration refresh'); // Get options $steps = $input->getOption('steps'); @@ -59,7 +59,8 @@ protected function execute(InputInterface $input, OutputInterface $output) // Stop if nothing was rolledback if (empty($rolledback)) { - $this->io->success("Nothing to refresh"); + $this->io->success('Nothing to refresh'); + return; } @@ -70,9 +71,9 @@ protected function execute(InputInterface $input, OutputInterface $output) // If all went well, there's no fatal errors and we have migrated // something, show some success if (empty($migrated)) { - $this->io->success("Nothing to refresh"); + $this->io->success('Nothing to refresh'); } else { - $this->io->success("Refresh successful !"); + $this->io->success('Refresh successful !'); } } } diff --git a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php index cb059d34d..f7160cc68 100644 --- a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php @@ -5,12 +5,12 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputOption; -use UserFrosting\Sprinkle\Core\Bakery\MigrateCommand; /** * migrate:reset Bakery Command @@ -25,8 +25,8 @@ class MigrateResetCommand extends MigrateCommand */ protected function configure() { - $this->setName("migrate:reset") - ->setDescription("Reset the whole database to an empty state, rolling back all migrations.") + $this->setName('migrate:reset') + ->setDescription('Reset the whole database to an empty state, rolling back all migrations.') ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') ->addOption('hard', null, InputOption::VALUE_NONE, 'Force drop all tables in the database, even if they were not created or listed by the migrator') @@ -38,7 +38,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Migration reset"); + $this->io->title('Migration reset'); // Check if the hard option is used if ($input->getOption('hard')) { @@ -75,16 +75,16 @@ protected function performReset(InputInterface $input) // Delete the repository if (!$pretend && $migrator->repositoryExists()) { - $this->io->writeln("Deleting migration repository"); + $this->io->writeln('Deleting migration repository'); $migrator->getRepository()->deleteRepository(); } // If all went well, there's no fatal errors and we have migrated // something, show some success if (empty($resetted)) { - $this->io->success("Nothing to reset"); + $this->io->success('Nothing to reset'); } else { - $this->io->success("Reset successful !"); + $this->io->success('Reset successful !'); } } @@ -118,6 +118,6 @@ protected function performHardReset(InputInterface $input) $schema->drop($table); } - $this->io->success("Hard reset successful !"); + $this->io->success('Hard reset successful !'); } } diff --git a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php index 44bbf618c..76ad14842 100644 --- a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php @@ -5,12 +5,12 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputOption; -use UserFrosting\Sprinkle\Core\Bakery\MigrateCommand; /** * migrate:rollback Bakery Command @@ -25,8 +25,8 @@ class MigrateRollbackCommand extends MigrateCommand */ protected function configure() { - $this->setName("migrate:rollback") - ->setDescription("Rollback last database migration") + $this->setName('migrate:rollback') + ->setDescription('Rollback last database migration') ->addOption('pretend', 'p', InputOption::VALUE_NONE, 'Run migrations in "dry run" mode.') ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force the operation to run when in production.') ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.') @@ -39,7 +39,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Migration rollback"); + $this->io->title('Migration rollback'); // Get options $steps = $input->getOption('steps'); @@ -69,9 +69,9 @@ protected function execute(InputInterface $input, OutputInterface $output) // If all went well, there's no fatal errors and we have migrated // something, show some success if (empty($migrated)) { - $this->io->success("Nothing to rollback"); + $this->io->success('Nothing to rollback'); } else { - $this->io->success("Rollback successful !"); + $this->io->success('Rollback successful !'); } } } diff --git a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php index d4b1c60e6..adfc6d257 100644 --- a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Illuminate\Support\Collection; @@ -26,9 +27,9 @@ class MigrateStatusCommand extends BaseCommand */ protected function configure() { - $this->setName("migrate:status") - ->setDescription("Show the list of installed and pending migration.") - ->setHelp("Show the list of installed and pending migration. This command also show if an installed migration is available in the Filesystem, so it can be run down by the rollback command") + $this->setName('migrate:status') + ->setDescription('Show the list of installed and pending migration.') + ->setHelp('Show the list of installed and pending migration. This command also show if an installed migration is available in the Filesystem, so it can be run down by the rollback command') ->addOption('database', 'd', InputOption::VALUE_REQUIRED, 'The database connection to use.'); } @@ -37,7 +38,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Migration status"); + $this->io->title('Migration status'); // Get migrator $migrator = $this->ci->migrator; @@ -58,22 +59,22 @@ protected function execute(InputInterface $input, OutputInterface $output) $pending = $migrator->pendingMigrations($available, $ranArray); // Display ran migrations - $this->io->section("Installed migrations"); + $this->io->section('Installed migrations'); if (count($ranArray) > 0) { $this->io->table( ['Migration', 'Available?', 'Batch'], $this->getStatusFor($ran, $available) ); } else { - $this->io->note("No installed migrations"); + $this->io->note('No installed migrations'); } // Display pending migrations - $this->io->section("Pending migrations"); + $this->io->section('Pending migrations'); if (count($pending) > 0) { $this->io->listing($pending); } else { - $this->io->note("No pending migrations"); + $this->io->note('No pending migrations'); } } @@ -81,9 +82,9 @@ protected function execute(InputInterface $input, OutputInterface $output) * Return an array of [migration, available] association. * A migration is available if it's in the available stack (class is in the Filesystem) * - * @param Collection $ran The ran migrations - * @param array $available The available migrations - * @return array An array of [migration, available] association + * @param Collection $ran The ran migrations + * @param array $available The available migrations + * @return array An array of [migration, available] association */ protected function getStatusFor(Collection $ran, array $available) { @@ -93,6 +94,7 @@ protected function getStatusFor(Collection $ran, array $available) } else { $available = 'No'; } + return [$migration->migration, $available, $migration->batch]; })->toArray(); } diff --git a/app/sprinkles/core/src/Bakery/RouteListCommand.php b/app/sprinkles/core/src/Bakery/RouteListCommand.php index 95ccddf22..0a0f63f44 100644 --- a/app/sprinkles/core/src/Bakery/RouteListCommand.php +++ b/app/sprinkles/core/src/Bakery/RouteListCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Illuminate\Support\Arr; @@ -49,7 +50,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Registered Routes"); + $this->io->title('Registered Routes'); // Get routes list $this->routes = $this->ci->router->getRoutes(); @@ -81,7 +82,7 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Get the route information for a given route. * - * @param Route $route + * @param Route $route * @param InputInterface $input [description] * @return array */ @@ -98,7 +99,7 @@ protected function getRouteInformation(Route $route, InputInterface $input) /** * Sort the routes by a given element. * - * @param string $sort + * @param string $sort * @param array $routes * @return array */ @@ -112,15 +113,15 @@ protected function sortRoutes($sort, $routes) /** * Filter the route by URI and / or name. * - * @param array $route + * @param array $route * @param InputInterface $input [description] * @return array|null */ protected function filterRoute(array $route, InputInterface $input) { - if (($input->getOption('name') && ! Str::contains($route['name'], $input->getOption('name'))) || - $input->getOption('uri') && ! Str::contains($route['uri'], $input->getOption('uri')) || - $input->getOption('method') && ! Str::contains($route['method'], strtoupper($input->getOption('method')))) { + if (($input->getOption('name') && !Str::contains($route['name'], $input->getOption('name'))) || + $input->getOption('uri') && !Str::contains($route['uri'], $input->getOption('uri')) || + $input->getOption('method') && !Str::contains($route['method'], strtoupper($input->getOption('method')))) { return; } diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index 117c2163c..101a1a6a5 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; @@ -70,7 +71,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } // Display the class we are going to use as info - $this->io->writeln("Seeding class `".get_class($seedClass)."`"); + $this->io->writeln('Seeding class `'.get_class($seedClass).'`'); // Add seed class to list $seeds[] = $seedClass; diff --git a/app/sprinkles/core/src/Bakery/SeedListCommand.php b/app/sprinkles/core/src/Bakery/SeedListCommand.php index 8dc8978d9..a86d76bbf 100644 --- a/app/sprinkles/core/src/Bakery/SeedListCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedListCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; @@ -35,7 +36,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $this->io->title("Database Seeds List"); + $this->io->title('Database Seeds List'); $seeder = new Seeder($this->ci); $seeds = $seeder->getSeeds(); $this->io->table(['Name', 'Namespace', 'Sprinkle'], $seeds); diff --git a/app/sprinkles/core/src/Bakery/SetupCommand.php b/app/sprinkles/core/src/Bakery/SetupCommand.php index 80158c5ff..26dd546a1 100644 --- a/app/sprinkles/core/src/Bakery/SetupCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; @@ -24,9 +25,9 @@ class SetupCommand extends BaseCommand */ protected function configure() { - $this->setName("setup") - ->setDescription("UserFrosting Configuration Wizard") - ->setHelp("This command combine the setup:env, setup:db and setup:smtp commands."); + $this->setName('setup') + ->setDescription('UserFrosting Configuration Wizard') + ->setHelp('This command combine the setup:env, setup:db and setup:smtp commands.'); } /** diff --git a/app/sprinkles/core/src/Bakery/SetupDbCommand.php b/app/sprinkles/core/src/Bakery/SetupDbCommand.php index c70035990..58278512c 100644 --- a/app/sprinkles/core/src/Bakery/SetupDbCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupDbCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use Illuminate\Database\Capsule\Manager as Capsule; @@ -33,16 +34,16 @@ class SetupDbCommand extends BaseCommand */ protected function configure() { - $this->setName("setup:db") - ->setDescription("UserFrosting Database Configuration Wizard") - ->setHelp("Helper command to setup the database configuration. This can also be done manually by editing the app/.env file or using global server environment variables.") - ->addOption('force', null, InputOption::VALUE_NONE, "Force setup if db is already configured") + $this->setName('setup:db') + ->setDescription('UserFrosting Database Configuration Wizard') + ->setHelp('Helper command to setup the database configuration. This can also be done manually by editing the app/.env file or using global server environment variables.') + ->addOption('force', null, InputOption::VALUE_NONE, 'Force setup if db is already configured') ->addOption('db_driver', null, InputOption::VALUE_OPTIONAL, "The database driver {$this->getDatabaseDriversList()}") - ->addOption('db_name', null, InputOption::VALUE_OPTIONAL, "The database name") - ->addOption('db_host', null, InputOption::VALUE_OPTIONAL, "The database hostname") - ->addOption('db_port', null, InputOption::VALUE_OPTIONAL, "The database port") - ->addOption('db_user', null, InputOption::VALUE_OPTIONAL, "The database user") - ->addOption('db_password', null, InputOption::VALUE_OPTIONAL, "The database password"); + ->addOption('db_name', null, InputOption::VALUE_OPTIONAL, 'The database name') + ->addOption('db_host', null, InputOption::VALUE_OPTIONAL, 'The database hostname') + ->addOption('db_port', null, InputOption::VALUE_OPTIONAL, 'The database port') + ->addOption('db_user', null, InputOption::VALUE_OPTIONAL, 'The database user') + ->addOption('db_password', null, InputOption::VALUE_OPTIONAL, 'The database password'); } /** @@ -59,8 +60,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->title("UserFrosting's Database Setup Wizard"); // Check if db is already setup - if (!$input->getOption('force') && $this->testDatabase($config["db.default"], false)) { - $this->io->note("Database already setup. Use the `php bakery setup:db --force` command to run db setup again."); + if (!$input->getOption('force') && $this->testDatabase($config['db.default'], false)) { + $this->io->note('Database already setup. Use the `php bakery setup:db --force` command to run db setup again.'); + return; } @@ -73,18 +75,18 @@ protected function execute(InputInterface $input, OutputInterface $output) // Get keys $keys = [ - 'DB_HOST' => ($dotenvEditor->keyExists('DB_HOST')) ? $dotenvEditor->getValue('DB_HOST') : '', - 'DB_NAME' => ($dotenvEditor->keyExists('DB_NAME')) ? $dotenvEditor->getValue('DB_NAME') : '', - 'DB_USER' => ($dotenvEditor->keyExists('DB_USER')) ? $dotenvEditor->getValue('DB_USER') : '', + 'DB_HOST' => ($dotenvEditor->keyExists('DB_HOST')) ? $dotenvEditor->getValue('DB_HOST') : '', + 'DB_NAME' => ($dotenvEditor->keyExists('DB_NAME')) ? $dotenvEditor->getValue('DB_NAME') : '', + 'DB_USER' => ($dotenvEditor->keyExists('DB_USER')) ? $dotenvEditor->getValue('DB_USER') : '', 'DB_PASSWORD' => ($dotenvEditor->keyExists('DB_PASSWORD')) ? $dotenvEditor->getValue('DB_PASSWORD') : '' ]; // There may be some custom config or global env values defined on the server. // We'll check for that and ask for confirmation in this case. - if ($config["db.default.host"] != $keys['DB_HOST'] || - $config["db.default.database"] != $keys['DB_NAME'] || - $config["db.default.username"] != $keys['DB_USER'] || - $config["db.default.password"] != $keys['DB_PASSWORD']) { + if ($config['db.default.host'] != $keys['DB_HOST'] || + $config['db.default.database'] != $keys['DB_NAME'] || + $config['db.default.username'] != $keys['DB_USER'] || + $config['db.default.password'] != $keys['DB_PASSWORD']) { $this->io->warning("Current database configuration differ from the configuration defined in `{$this->envPath}`. Global system environment variables might be defined."); if (!$this->io->confirm('Continue?', false)) { @@ -99,22 +101,22 @@ protected function execute(InputInterface $input, OutputInterface $output) if (!$this->testDatabase($dbParams)) { exit(1); } else { - $this->io->success("Database connection successful"); + $this->io->success('Database connection successful'); } // Time to save - $this->io->section("Saving data"); + $this->io->section('Saving data'); // Prepare file content // N.B.: Can't use the `$dbParams` keys directly since they differ from // the config one later used to update the config $fileContent = [ - "DB_DRIVER" => $dbParams['driver'], - "DB_HOST" => $dbParams['host'], - "DB_PORT" => $dbParams['port'], - "DB_NAME" => $dbParams['database'], - "DB_USER" => $dbParams['username'], - "DB_PASSWORD" => $dbParams['password'] + 'DB_DRIVER' => $dbParams['driver'], + 'DB_HOST' => $dbParams['host'], + 'DB_PORT' => $dbParams['port'], + 'DB_NAME' => $dbParams['database'], + 'DB_USER' => $dbParams['username'], + 'DB_PASSWORD' => $dbParams['password'] ]; foreach ($fileContent as $key => $value) { @@ -125,7 +127,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // At this point, `$this->uf` is still using the old configs. // We need to refresh the `db.default` config values $newConfig = array_merge($this->ci->config['db.default'], $dbParams); - $this->ci->config->set("db.default", $newConfig); + $this->ci->config->set('db.default', $newConfig); // Success $this->io->success("Database config successfully saved in `{$this->envPath}`"); @@ -135,7 +137,7 @@ protected function execute(InputInterface $input, OutputInterface $output) * Ask for database crendentials * * @param InputInterface $args Command arguments - * @return array The databse credentials + * @return array The databse credentials */ protected function askForDatabase(InputInterface $args) { @@ -148,7 +150,7 @@ protected function askForDatabase(InputInterface $args) $selectedDriver = $args->getOption('db_driver'); $driver = $drivers->where('driver', $selectedDriver)->first(); } else { - $selectedDriver = $this->io->choice("Database type", $driversList); + $selectedDriver = $this->io->choice('Database type', $driversList); $driver = $drivers->where('name', $selectedDriver)->first(); } @@ -160,12 +162,12 @@ protected function askForDatabase(InputInterface $args) // Ask further questions based on driver if ($driver['driver'] == 'sqlite') { - $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); + $name = ($args->getOption('db_name')) ?: $this->io->ask('Database name', $driver['defaultDBName']); return [ - 'driver' => $driver['driver'], - 'host' => '', - 'port' => '', + 'driver' => $driver['driver'], + 'host' => '', + 'port' => '', 'database' => $name, 'username' => '', 'password' => '' @@ -173,23 +175,23 @@ protected function askForDatabase(InputInterface $args) } else { $defaultPort = $driver['defaultPort']; - $host = ($args->getOption('db_host')) ?: $this->io->ask("Hostname", "localhost"); - $port = ($args->getOption('db_port')) ?: $this->io->ask("Port", $defaultPort); - $name = ($args->getOption('db_name')) ?: $this->io->ask("Database name", $driver['defaultDBName']); - $user = ($args->getOption('db_user')) ?: $this->io->ask("Username", "userfrosting"); - $password = ($args->getOption('db_password')) ?: $this->io->askHidden("Password", function ($password) { + $host = ($args->getOption('db_host')) ?: $this->io->ask('Hostname', 'localhost'); + $port = ($args->getOption('db_port')) ?: $this->io->ask('Port', $defaultPort); + $name = ($args->getOption('db_name')) ?: $this->io->ask('Database name', $driver['defaultDBName']); + $user = ($args->getOption('db_user')) ?: $this->io->ask('Username', 'userfrosting'); + $password = ($args->getOption('db_password')) ?: $this->io->askHidden('Password', function ($password) { // Use custom validator to accept empty password return $password; }); return [ - 'driver' => $driver['driver'], - 'host' => $host, - 'port' => $port, + 'driver' => $driver['driver'], + 'host' => $host, + 'port' => $port, 'database' => $name, 'username' => $user, 'password' => $password, - 'charset' => $this->ci->config['db.default.charset'] // Used when replacing config later + 'charset' => $this->ci->config['db.default.charset'] // Used when replacing config later ]; } } @@ -197,14 +199,14 @@ protected function askForDatabase(InputInterface $args) /** * Test new database connecion * - * @param array $dbParams Database params - * @param bool $displayMessage Display io message - * @return bool Return true if db is successful + * @param array $dbParams Database params + * @param bool $displayMessage Display io message + * @return bool Return true if db is successful */ protected function testDatabase($dbParams, $displayMessage = true) { // Setup a new db connection - $capsule = new Capsule; + $capsule = new Capsule(); $capsule->addConnection($dbParams); // Test the db connexion. @@ -213,11 +215,12 @@ protected function testDatabase($dbParams, $displayMessage = true) $conn->getPdo(); } catch (\PDOException $e) { if ($displayMessage) { - $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; - $message .= "Exception: " . $e->getMessage() . PHP_EOL.PHP_EOL; - $message .= "Please check your database configuration and/or google the exception shown above and run the command again."; + $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; + $message .= 'Exception: ' . $e->getMessage() . PHP_EOL.PHP_EOL; + $message .= 'Please check your database configuration and/or google the exception shown above and run the command again.'; $this->io->error($message); } + return false; } @@ -233,28 +236,28 @@ protected function databaseDrivers() { return collect([ [ - "driver" => "mysql", - "name" => "MySQL / MariaDB", - "defaultDBName" => "userfrosting", - "defaultPort" => 3306 + 'driver' => 'mysql', + 'name' => 'MySQL / MariaDB', + 'defaultDBName' => 'userfrosting', + 'defaultPort' => 3306 ], [ - "driver" => "pgsql", - "name" => "ProgreSQL", - "defaultDBName" => "userfrosting", - "defaultPort" => 5432 + 'driver' => 'pgsql', + 'name' => 'ProgreSQL', + 'defaultDBName' => 'userfrosting', + 'defaultPort' => 5432 ], [ - "driver" => "sqlsrv", - "name" => "SQL Server", - "defaultDBName" => "userfrosting", - "defaultPort" => 1433 + 'driver' => 'sqlsrv', + 'name' => 'SQL Server', + 'defaultDBName' => 'userfrosting', + 'defaultPort' => 1433 ], [ - "driver" => "sqlite", - "name" => "SQLite", - "defaultDBName" => \UserFrosting\DB_DIR . \UserFrosting\DS . 'userfrosting.db', - "defaultPort" => null + 'driver' => 'sqlite', + 'name' => 'SQLite', + 'defaultDBName' => \UserFrosting\DB_DIR . \UserFrosting\DS . 'userfrosting.db', + 'defaultPort' => null ] ]); } @@ -268,6 +271,7 @@ protected function getDatabaseDriversList() { $dbDriverList = $this->databaseDrivers(); $dbDriverList = $dbDriverList->pluck('driver'); + return $dbDriverList; } } diff --git a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php index 7430248a0..38f738759 100644 --- a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use UserFrosting\Support\DotenvEditor\DotenvEditor; @@ -36,10 +37,10 @@ class SetupEnvCommand extends BaseCommand */ protected function configure() { - $this->setName("setup:env") - ->setDescription("UserFrosting Environment Configuration Wizard") - ->setHelp("Helper command to setup environement mode. This can also be done manually by editing the app/.env file or using global server environment variables.") - ->addOption('mode', null, InputOption::VALUE_OPTIONAL, "The environment to use"); + $this->setName('setup:env') + ->setDescription('UserFrosting Environment Configuration Wizard') + ->setHelp('Helper command to setup environement mode. This can also be done manually by editing the app/.env file or using global server environment variables.') + ->addOption('mode', null, InputOption::VALUE_OPTIONAL, 'The environment to use'); } /** @@ -50,7 +51,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // Display header, $this->io->title("UserFrosting's Environment Setup Wizard"); $this->io->note("Environment mode will be saved in `{$this->envPath}`"); - $this->io->write("Select desired envrionement mode. Production should only be used when deploying a live app."); + $this->io->write('Select desired envrionement mode. Production should only be used when deploying a live app.'); // Get an instance of the DotenvEditor $dotenvEditor = new DotenvEditor(\UserFrosting\APP_DIR, false); @@ -71,7 +72,7 @@ protected function execute(InputInterface $input, OutputInterface $output) * Ask for env mode * * @param InputInterface $args Command arguments - * @return string The new env mode + * @return string The new env mode */ protected function askForEnv(InputInterface $args) { @@ -79,7 +80,7 @@ protected function askForEnv(InputInterface $args) if ($args->getOption('mode')) { return $args->getOption('mode'); } else { - $newEnvMode = $this->io->choice("Environment Mode", [ + $newEnvMode = $this->io->choice('Environment Mode', [ 'default', 'production', 'debug', diff --git a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php index ee808f398..090f16049 100644 --- a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Bakery; use UserFrosting\Support\DotenvEditor\DotenvEditor; @@ -50,7 +51,7 @@ protected function configure() $this->setName('setup:smtp') ->setDescription('UserFrosting SMTP Configuration Wizard') ->setHelp('Helper command to setup outgoing email configuration. This can also be done manually by editing the app/.env file or using global server environment variables.') - ->addOption('force', null, InputOption::VALUE_NONE, "Force setup if SMTP appears to be already configured") + ->addOption('force', null, InputOption::VALUE_NONE, 'Force setup if SMTP appears to be already configured') ->addOption('smtp_host', null, InputOption::VALUE_OPTIONAL, 'The SMTP server hostname') ->addOption('smtp_user', null, InputOption::VALUE_OPTIONAL, 'The SMTP server user') ->addOption('smtp_password', null, InputOption::VALUE_OPTIONAL, 'The SMTP server password'); @@ -76,14 +77,15 @@ protected function execute(InputInterface $input, OutputInterface $output) // Check if db is already setup if (!$input->getOption('force') && $this->isSmtpConfigured($dotenvEditor)) { - $this->io->note("SMTP already setup. Use the `php bakery setup:smtp --force` command to run SMTP setup again."); + $this->io->note('SMTP already setup. Use the `php bakery setup:smtp --force` command to run SMTP setup again.'); + return; } // Get keys $keys = [ - 'SMTP_HOST' => ($dotenvEditor->keyExists('SMTP_HOST')) ? $dotenvEditor->getValue('SMTP_HOST') : '', - 'SMTP_USER' => ($dotenvEditor->keyExists('SMTP_USER')) ? $dotenvEditor->getValue('SMTP_USER') : '', + 'SMTP_HOST' => ($dotenvEditor->keyExists('SMTP_HOST')) ? $dotenvEditor->getValue('SMTP_HOST') : '', + 'SMTP_USER' => ($dotenvEditor->keyExists('SMTP_USER')) ? $dotenvEditor->getValue('SMTP_USER') : '', 'SMTP_PASSWORD' => ($dotenvEditor->keyExists('SMTP_PASSWORD')) ? $dotenvEditor->getValue('SMTP_PASSWORD') : '' ]; @@ -120,7 +122,7 @@ protected function execute(InputInterface $input, OutputInterface $output) * Ask with setup method to use * * @param InputInterface $input - * @return array The SMTP connection info + * @return array The SMTP connection info */ protected function askForSmtpMethod(InputInterface $input) { @@ -152,7 +154,7 @@ protected function askForSmtpMethod(InputInterface $input) * Ask for SMTP credential * * @param InputInterface $input Command arguments - * @return array The SMTP connection info + * @return array The SMTP connection info */ protected function askForSmtp(InputInterface $input) { @@ -165,8 +167,8 @@ protected function askForSmtp(InputInterface $input) }); return [ - 'SMTP_HOST' => $smtpHost, - 'SMTP_USER' => $smtpUser, + 'SMTP_HOST' => $smtpHost, + 'SMTP_USER' => $smtpUser, 'SMTP_PASSWORD' => $smtpPassword ]; } @@ -175,7 +177,7 @@ protected function askForSmtp(InputInterface $input) * Ask for Gmail * * @param InputInterface $input Command arguments - * @return array The SMTP connection info + * @return array The SMTP connection info */ protected function askForGmail(InputInterface $input) { @@ -186,8 +188,8 @@ protected function askForGmail(InputInterface $input) }); return [ - 'SMTP_HOST' => 'smtp.gmail.com', - 'SMTP_USER' => $smtpUser, + 'SMTP_HOST' => 'smtp.gmail.com', + 'SMTP_USER' => $smtpUser, 'SMTP_PASSWORD' => $smtpPassword ]; } @@ -196,7 +198,7 @@ protected function askForGmail(InputInterface $input) * Process the "no email support" setup option * * @param InputInterface $input - * @return array The SMTP connection info + * @return array The SMTP connection info */ protected function askForNone(InputInterface $input) { @@ -205,8 +207,8 @@ protected function askForNone(InputInterface $input) if ($this->io->confirm('Continue ?', false)) { return [ - 'SMTP_HOST' => '', - 'SMTP_USER' => '', + 'SMTP_HOST' => '', + 'SMTP_USER' => '', 'SMTP_PASSWORD' => '' ]; } else { @@ -218,7 +220,7 @@ protected function askForNone(InputInterface $input) * Check if the app/.env SMTP portion is defined or not. * * @param DotenvEditor $dotenvEditor - * @return bool true if SMTP is configured in .env file + * @return bool true if SMTP is configured in .env file */ protected function isSmtpConfigured(DotenvEditor $dotenvEditor) { diff --git a/app/sprinkles/core/src/Controller/CoreController.php b/app/sprinkles/core/src/Controller/CoreController.php index da71ea71f..6026f6e59 100644 --- a/app/sprinkles/core/src/Controller/CoreController.php +++ b/app/sprinkles/core/src/Controller/CoreController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Controller; use Psr\Http\Message\ServerRequestInterface as Request; @@ -25,9 +26,9 @@ class CoreController extends SimpleController * * By default, this is the page that non-authenticated users will first see when they navigate to your website's root. * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageIndex(Request $request, Response $response, $args) { @@ -38,9 +39,9 @@ public function pageIndex(Request $request, Response $response, $args) * Renders a sample "about" page for UserFrosting. * * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageAbout(Request $request, Response $response, $args) { @@ -51,9 +52,9 @@ public function pageAbout(Request $request, Response $response, $args) * Renders terms of service page. * * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pageLegal(Request $request, Response $response, $args) { @@ -64,9 +65,9 @@ public function pageLegal(Request $request, Response $response, $args) * Renders privacy page. * * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function pagePrivacy(Request $request, Response $response, $args) { @@ -78,9 +79,9 @@ public function pagePrivacy(Request $request, Response $response, $args) * * The alert stream contains messages which have been generated by calls to `MessageStream::addMessage` and `MessageStream::addMessageTranslated`. * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function jsonAlerts(Request $request, Response $response, $args) { @@ -90,9 +91,9 @@ public function jsonAlerts(Request $request, Response $response, $args) /** * Handle all requests for raw assets. * Request type: GET - * @param Request $request - * @param Response $response - * @param array $args + * @param Request $request + * @param Response $response + * @param array $args */ public function getAsset(Request $request, Response $response, $args) { @@ -100,7 +101,7 @@ public function getAsset(Request $request, Response $response, $args) $assetLoader = $this->ci->assetLoader; if (!isset($args['url']) || !$assetLoader->loadAsset($args['url'])) { - throw new NotFoundException; + throw new NotFoundException(); } return $response diff --git a/app/sprinkles/core/src/Controller/SimpleController.php b/app/sprinkles/core/src/Controller/SimpleController.php index b0fc15241..31eb35990 100644 --- a/app/sprinkles/core/src/Controller/SimpleController.php +++ b/app/sprinkles/core/src/Controller/SimpleController.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Controller; use Interop\Container\ContainerInterface; diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index 488b66998..1e8ec85f6 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core; use RocketTheme\Toolbox\Event\Event; @@ -42,9 +43,9 @@ public function __construct(ContainerInterface $ci) public static function getSubscribedEvents() { return [ - 'onSprinklesInitialized' => ['onSprinklesInitialized', 0], + 'onSprinklesInitialized' => ['onSprinklesInitialized', 0], 'onSprinklesRegisterServices' => ['onSprinklesRegisterServices', 0], - 'onAddGlobalMiddleware' => ['onAddGlobalMiddleware', 0] + 'onAddGlobalMiddleware' => ['onAddGlobalMiddleware', 0] ]; } diff --git a/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php b/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php index 332f0f645..d34627d87 100644 --- a/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php +++ b/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Csrf; use Interop\Container\ContainerInterface; @@ -23,7 +24,7 @@ interface CsrfProviderInterface * Returns the CSRF Guard which will be added to the app later * * @param ContainerInterface $ci - * @return mixed The csrf guard + * @return mixed The csrf guard */ public static function setupService(ContainerInterface $ci); @@ -31,9 +32,9 @@ public static function setupService(ContainerInterface $ci); * Register middleware. * Add the guard to the app as a middleware * - * @param App $app - * @param Request $request - * @param mixed $guard + * @param App $app + * @param Request $request + * @param mixed $guard */ public static function registerMiddleware(App $app, Request $request, $guard); } diff --git a/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php b/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php index ea5e55f9f..226a7ae56 100644 --- a/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php +++ b/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Csrf; use Interop\Container\ContainerInterface; @@ -20,7 +21,7 @@ class SlimCsrfProvider implements CsrfProviderInterface { /** - * @inheritDoc + * {@inheritdoc} * @return \Slim\Csrf\Guard */ public static function setupService(ContainerInterface $ci) @@ -38,7 +39,7 @@ public static function setupService(ContainerInterface $ci) $csrfStorage = $ci->session[$csrfKey]; $onFailure = function ($request, $response, $next) { - $e = new BadRequestException("The CSRF code was invalid or not provided."); + $e = new BadRequestException('The CSRF code was invalid or not provided.'); $e->addUserMessage('CSRF_MISSING'); throw $e; @@ -49,7 +50,7 @@ public static function setupService(ContainerInterface $ci) } /** - * @inheritDoc + * {@inheritdoc} */ public static function registerMiddleware(App $app, Request $request, $guard) { diff --git a/app/sprinkles/core/src/Database/Builder.php b/app/sprinkles/core/src/Database/Builder.php index 7f75d3abe..23ad12fb1 100644 --- a/app/sprinkles/core/src/Database/Builder.php +++ b/app/sprinkles/core/src/Database/Builder.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database; use Illuminate\Database\Query\Builder as LaravelBuilder; @@ -24,8 +25,8 @@ class Builder extends LaravelBuilder /** * Perform a "begins with" pattern match on a specified column in a query. * - * @param string $field The column to match - * @param string $value The value to match + * @param string $field The column to match + * @param string $value The value to match * @return self */ public function beginsWith($field, $value) @@ -36,8 +37,8 @@ public function beginsWith($field, $value) /** * Perform an "ends with" pattern match on a specified column in a query. * - * @param string $field The column to match - * @param string $value The value to match + * @param string $field The column to match + * @param string $value The value to match * @return self */ public function endsWith($field, $value) @@ -48,7 +49,7 @@ public function endsWith($field, $value) /** * Add columns to be excluded from the query. * - * @param array|string $column The column(s) to exclude + * @param array|string $column The column(s) to exclude * @return self */ public function exclude($column) @@ -63,8 +64,8 @@ public function exclude($column) /** * Perform a pattern match on a specified column in a query. * - * @param string $field The column to match - * @param string $value The value to match + * @param string $field The column to match + * @param string $value The value to match * @return self */ public function like($field, $value) @@ -75,8 +76,8 @@ public function like($field, $value) /** * Perform a pattern match on a specified column in a query. * - * @param string $field The column to match - * @param string $value The value to match + * @param string $field The column to match + * @param string $value The value to match * @return self */ public function orLike($field, $value) @@ -87,7 +88,7 @@ public function orLike($field, $value) /** * Execute the query as a "select" statement. * - * @param array $columns + * @param array $columns * @return \Illuminate\Support\Collection */ public function get($columns = ['*']) @@ -132,7 +133,7 @@ protected function removeExcludedSelectColumns() /** * Find any wildcard columns ('*'), remove it from the column list and replace with an explicit list of columns. * - * @param array $columns + * @param array $columns * @return array */ protected function replaceWildcardColumns(array $columns) @@ -153,7 +154,7 @@ protected function replaceWildcardColumns(array $columns) /** * Return a list of wildcard columns from the list of columns, mapping columns to their corresponding tables. * - * @param array $columns + * @param array $columns * @return array */ protected function findWildcardTables(array $columns) @@ -180,7 +181,7 @@ protected function findWildcardTables(array $columns) /** * Gets the fully qualified column names for a specified table. * - * @param string $table + * @param string $table * @return array */ protected function getQualifiedColumnNames($table = null) @@ -193,8 +194,8 @@ protected function getQualifiedColumnNames($table = null) /** * Fully qualify any unqualified columns in a list with this builder's table name. * - * @param array $columns - * @param string $table + * @param array $columns + * @param string $table * @return array */ protected function convertColumnsToFullyQualified($columns, $table = null) diff --git a/app/sprinkles/core/src/Database/DatabaseInvalidException.php b/app/sprinkles/core/src/Database/DatabaseInvalidException.php index 08f8a3160..0eba67b0d 100644 --- a/app/sprinkles/core/src/Database/DatabaseInvalidException.php +++ b/app/sprinkles/core/src/Database/DatabaseInvalidException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database; use UserFrosting\Support\Exception\ForbiddenException; diff --git a/app/sprinkles/core/src/Database/EloquentBuilder.php b/app/sprinkles/core/src/Database/EloquentBuilder.php index 4066825ac..09c8c6378 100644 --- a/app/sprinkles/core/src/Database/EloquentBuilder.php +++ b/app/sprinkles/core/src/Database/EloquentBuilder.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database; use Illuminate\Database\Eloquent\Builder as LaravelEloquentBuilder; @@ -21,7 +22,7 @@ class EloquentBuilder extends LaravelEloquentBuilder /** * Add subselect queries to sum the relations. * - * @param mixed $relations + * @param mixed $relations * @return self */ public function withSum($relations) @@ -34,7 +35,7 @@ public function withSum($relations) /** * Add subselect queries to max the relations. * - * @param mixed $relations + * @param mixed $relations * @return self */ public function withMax($relations) @@ -47,7 +48,7 @@ public function withMax($relations) /** * Add subselect queries to min the relations. * - * @param mixed $relations + * @param mixed $relations * @return self */ public function withMin($relations) @@ -60,7 +61,7 @@ public function withMin($relations) /** * Add subselect queries to min the relations. * - * @param mixed $relations + * @param mixed $relations * @return self */ public function withAvg($relations) @@ -73,8 +74,8 @@ public function withAvg($relations) /** * use the MySQL aggregate functions including AVG COUNT, SUM, MAX and MIN. * - * @param array $relations - * @param string $function + * @param array $relations + * @param string $function * @return self */ public function withAggregate($relations, $function = 'COUNT') diff --git a/app/sprinkles/core/src/Database/Migration.php b/app/sprinkles/core/src/Database/Migration.php index 0f9f3cba1..8b76eb041 100644 --- a/app/sprinkles/core/src/Database/Migration.php +++ b/app/sprinkles/core/src/Database/Migration.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database; use Illuminate\Database\Schema\Builder; diff --git a/app/sprinkles/core/src/Database/MigrationInterface.php b/app/sprinkles/core/src/Database/MigrationInterface.php index 4af0ec53f..802441832 100644 --- a/app/sprinkles/core/src/Database/MigrationInterface.php +++ b/app/sprinkles/core/src/Database/MigrationInterface.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database; /** diff --git a/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php b/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php index 6bdac0fc8..b634577b5 100644 --- a/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php +++ b/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; diff --git a/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php b/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php index f13a8c80d..6ae7df00d 100644 --- a/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php +++ b/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; diff --git a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php index ef7736add..8fea97d1a 100644 --- a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php +++ b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php @@ -5,11 +5,11 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Migrator; use Illuminate\Database\Capsule\Manager as Capsule; use Illuminate\Database\Schema\Blueprint; -use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRepositoryInterface; /** * MigrationRepository Class @@ -38,10 +38,10 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface /** * Create a new database migration repository instance. * - * @param Capsule $db - * @param string $table + * @param Capsule $db + * @param string $table */ - public function __construct(Capsule $db, $table = "migrations") + public function __construct(Capsule $db, $table = 'migrations') { $this->table = $table; $this->db = $db; @@ -50,9 +50,9 @@ public function __construct(Capsule $db, $table = "migrations") /** * Get the list of ran migrations * - * @param int $steps Number of batch to return + * @param int $steps Number of batch to return * @param string $order asc|desc - * @return array An array of migration class names in the order they where ran + * @return array An array of migration class names in the order they where ran */ public function getMigrationsList($steps = -1, $order = 'asc') { @@ -62,7 +62,7 @@ public function getMigrationsList($steps = -1, $order = 'asc') /** * Get list of migrations. * - * @param int $steps Number of batch to return + * @param int $steps Number of batch to return * @param string $order asc|desc * @return array */ @@ -81,7 +81,7 @@ public function getMigrations($steps = -1, $order = 'asc') /** * Get details about a specific migration * - * @param string $migration The migration class + * @param string $migration The migration class * @return \stdClass The migration info */ public function getMigration($migration) @@ -104,11 +104,11 @@ public function getLast() /** * Log that a migration was run. * - * @param string $file - * @param int $batch - * @param string $sprinkle + * @param string $file + * @param int $batch + * @param string $sprinkle */ - public function log($file, $batch, $sprinkle = "") + public function log($file, $batch, $sprinkle = '') { $record = ['migration' => $file, 'batch' => $batch, 'sprinkle' => $sprinkle]; @@ -118,7 +118,7 @@ public function log($file, $batch, $sprinkle = "") /** * Remove a migration from the log. * - * @param string $migration + * @param string $migration */ public function delete($migration) { diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php index 28c67d939..693ae58b6 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Migrator; use ReflectionClass; @@ -51,7 +52,7 @@ class MigrationDependencyAnalyser /** * Constructor * - * @param array $pending The pending migrations + * @param array $pending The pending migrations * @param array $installed The installed migrations */ public function __construct(array $pending = [], array $installed = []) @@ -88,7 +89,7 @@ public function analyse() * in the `fullfillable` property. * * @param string $migrationName The migration classname - * @return bool True/False if the migration is fulfillable + * @return bool True/False if the migration is fulfillable */ protected function validateClassDependencies($migrationName) { @@ -164,28 +165,30 @@ public function getUnfulfillable() * Mark a dependency as fulfillable. Removes it from the pending list and add it to the fulfillable list * * @param string $migration The migration classname - * @return bool True, it's fulfillable + * @return bool True, it's fulfillable */ protected function markAsFulfillable($migration) { $this->fulfillable->push($migration); + return true; } /** * Mark a dependency as unfulfillable. Removes it from the pending list and add it to the unfulfillable list * - * @param string $migration The migration classname + * @param string $migration The migration classname * @param string|array $dependency The problematic dependecy - * @return bool False, it's not fullfillable + * @return bool False, it's not fullfillable */ protected function markAsUnfulfillable($migration, $dependency) { if (is_array($dependency)) { - $dependency = implode(", ", $dependency); + $dependency = implode(', ', $dependency); } $this->unfulfillable->put($migration, $dependency); + return false; } @@ -194,7 +197,7 @@ protected function markAsUnfulfillable($migration, $dependency) * Also handles the old deprecated behaviour where dependencies where not in a static property * * @param string $migration The migration class - * @return array The dependency list + * @return array The dependency list */ protected function getMigrationDependencies($migration) { @@ -215,6 +218,7 @@ protected function getMigrationDependencies($migration) Debug::warning("`$migration` uses a non static `dependencies` property. Please change the `dependencies` property to a static property."); } $instance = new $migration(); + return $instance->dependencies; } else { return []; diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php index 4a95ec83b..af5ae7167 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php @@ -5,12 +5,12 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Migrator; use Illuminate\Support\Str; use UserFrosting\UniformResourceLocator\Resource; use UserFrosting\UniformResourceLocator\ResourceLocator; -use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocatorInterface; /** * MigrationLocator Class @@ -34,7 +34,7 @@ class MigrationLocator implements MigrationLocatorInterface /** * Class Constructor * - * @param ResourceLocator $locator The locator services + * @param ResourceLocator $locator The locator services */ public function __construct(ResourceLocator $locator) { @@ -54,14 +54,15 @@ public function getMigrations() foreach ($migrationFiles as $migrationFile) { $migrations[] = $this->getMigrationDetails($migrationFile); } + return $migrations; } /** * Return an array of migration details inclusing the classname and the sprinkle name * - * @param Resource $file The migration file - * @return string The migration full class path + * @param resource $file The migration file + * @return string The migration full class path */ protected function getMigrationDetails(Resource $file) { diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php index d55310508..fab0a435b 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Migrator; /** diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php index 627e0e6e3..a8ee19042 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Migrator; /** @@ -17,16 +18,16 @@ interface MigrationRepositoryInterface /** * Get the list of ran migrations * - * @param int $steps Number of batch to return + * @param int $steps Number of batch to return * @param string $order asc|desc - * @return array An array of migration class names in the order they where ran + * @return array An array of migration class names in the order they where ran */ public function getMigrationsList($steps = -1, $order = 'asc'); /** * Get list of migrations. * - * @param int $steps Number of batch to return + * @param int $steps Number of batch to return * @param string $order asc|desc * @return array */ @@ -42,15 +43,15 @@ public function getLast(); /** * Log that a migration was run. * - * @param string $file - * @param int $batch + * @param string $file + * @param int $batch */ public function log($file, $batch); /** * Remove a migration from the log. * - * @param string $migration + * @param string $migration */ public function delete($migration); diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php index ce1c1fd2a..837238c50 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php @@ -5,9 +5,8 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Sprinkle\Core\Database\Migrator; -use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationDependencyAnalyser; +namespace UserFrosting\Sprinkle\Core\Database\Migrator; /** * MigrationRollbackDependencyAnalyser Class @@ -23,7 +22,7 @@ class MigrationRollbackDependencyAnalyser extends MigrationDependencyAnalyser * Constructor * * @param array $installed The installed migrations - * @param array $rollback The migrations to rollback + * @param array $rollback The migrations to rollback */ public function __construct(array $installed = [], array $rollback = []) { @@ -39,7 +38,7 @@ public function __construct(array $installed = [], array $rollback = []) * rolledback, unfulfillable cannot. * * @param string $migrationName The migration classname - * @return bool True/False if the migration is fulfillable + * @return bool True/False if the migration is fulfillable */ protected function validateClassDependencies($migrationName) { diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index e63a6cd53..b6233dde1 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -5,13 +5,12 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Migrator; use Illuminate\Support\Arr; use Illuminate\Database\Capsule\Manager as Capsule; use UserFrosting\Sprinkle\Core\Database\MigrationInterface; -use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocatorInterface; -use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRepositoryInterface; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationDependencyAnalyser as Analyser; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationRollbackDependencyAnalyser as RollbackAnalyser; use UserFrosting\Sprinkle\Core\Facades\Config; @@ -55,9 +54,9 @@ class Migrator /** * Constructor * - * @param Capsule $db The database instance + * @param Capsule $db The database instance * @param MigrationRepositoryInterface $repository The migration repository - * @param MigrationLocatorInterface $locator The Migration locator + * @param MigrationLocatorInterface $locator The Migration locator */ public function __construct(Capsule $db, MigrationRepositoryInterface $repository, MigrationLocatorInterface $locator) { @@ -100,7 +99,7 @@ public function run(array $options = []) // Any migration without a fulfilled dependency will cause this script to throw an exception if ($unfulfillable = $analyser->getUnfulfillable()) { - $messages = ["Unfulfillable migrations found :: "]; + $messages = ['Unfulfillable migrations found :: ']; foreach ($unfulfillable as $migration => $dependency) { $messages[] = "=> $migration (Missing dependency : $dependency)"; } @@ -115,7 +114,7 @@ public function run(array $options = []) * Get the migration classes that have not yet run. * * @param array $available The available migrations returned by the migration locator - * @param array $ran The list of already ran migrations returned by the migration repository + * @param array $ran The list of already ran migrations returned by the migration repository * @return array The list of pending migrations, ie the available migrations not ran yet */ public function pendingMigrations(array $available, array $ran) @@ -128,8 +127,8 @@ public function pendingMigrations(array $available, array $ran) /** * Run an array of migrations. * - * @param array $migrations An array of migrations classes names to be run (unsorted, unvalidated) - * @param array $options The options for the current operation [step, pretend] + * @param array $migrations An array of migrations classes names to be run (unsorted, unvalidated) + * @param array $options The options for the current operation [step, pretend] */ protected function runPending(array $migrations, array $options = []) { @@ -159,9 +158,9 @@ protected function runPending(array $migrations, array $options = []) /** * Run "up" a migration class * - * @param string $migrationClassName The migration class name - * @param int $batch The current bacth number - * @param bool $pretend If this operation should be pretended / faked + * @param string $migrationClassName The migration class name + * @param int $batch The current bacth number + * @param bool $pretend If this operation should be pretended / faked */ protected function runUp($migrationClassName, $batch, $pretend) { @@ -185,13 +184,13 @@ protected function runUp($migrationClassName, $batch, $pretend) $this->note("Migrated: {$migrationClassName}"); - /** + /* * If the migration has a `seed` method, run it * @deprecated Since 4.2.0. Use a seeder instead */ if (method_exists($migration, 'seed')) { if (Config::get('debug.deprecation')) { - Debug::warning("Migration `seed` method has been deprecated and will be removed in future versions. Please use a Seeder instead."); + Debug::warning('Migration `seed` method has been deprecated and will be removed in future versions. Please use a Seeder instead.'); } $this->runMigration($migration, 'seed'); $this->note("Seeded: {$migrationClassName}"); @@ -247,8 +246,8 @@ public function rollbackMigration($migrationClassName, array $options = []) /** * Get the migrations for a rollback operation. * - * @param array $options The options for the current operation - * @return array An ordered array of migrations to rollback + * @param array $options The options for the current operation + * @return array An ordered array of migrations to rollback */ protected function getMigrationsForRollback(array $options) { @@ -264,7 +263,7 @@ protected function getMigrationsForRollback(array $options) * Rollback the given migrations. * * @param array $migrations An array of migrations to rollback formated as an eloquent collection - * @param array $options The options for the current operation + * @param array $options The options for the current operation * @return array The list of rolledback migration classes */ protected function rollbackMigrations(array $migrations, array $options) @@ -309,7 +308,7 @@ protected function rollbackMigrations(array $migrations, array $options) /** * Check if migrations can be rolledback. * - * @param array $migrations The migrations classes to rollback + * @param array $migrations The migrations classes to rollback * @throws \Exception If rollback can't be performed */ protected function checkRollbackDependencies(array $migrations) @@ -333,7 +332,7 @@ protected function checkRollbackDependencies(array $migrations) /** * Rolls all of the currently applied migrations back. * - * @param bool $pretend Should this operation be pretended + * @param bool $pretend Should this operation be pretended * @return array An array of all the rolledback migration classes */ public function reset($pretend = false) @@ -358,8 +357,8 @@ public function reset($pretend = false) /** * Run "down" a migration instance. * - * @param string $migrationClassName The migration class name - * @param bool $pretend Is the operation should be pretended + * @param string $migrationClassName The migration class name + * @param bool $pretend Is the operation should be pretended */ protected function runDown($migrationClassName, $pretend) { @@ -385,8 +384,8 @@ protected function runDown($migrationClassName, $pretend) * Run a migration inside a transaction if the database supports it. * Note : As of Laravel 5.4, only PostgresGrammar supports it * - * @param MigrationInterface $migration The migration instance - * @param string $method The method used [up, down] + * @param MigrationInterface $migration The migration instance + * @param string $method The method used [up, down] */ protected function runMigration(MigrationInterface $migration, $method) { @@ -407,8 +406,8 @@ protected function runMigration(MigrationInterface $migration, $method) /** * Pretend to run the migrations. * - * @param MigrationInterface $migration The migration instance - * @param string $method The method used [up, down] + * @param MigrationInterface $migration The migration instance + * @param string $method The method used [up, down] */ protected function pretendToRun(MigrationInterface $migration, $method) { @@ -424,8 +423,8 @@ protected function pretendToRun(MigrationInterface $migration, $method) * Get all of the queries that would be run for a migration. * * @param MigrationInterface $migration The migration instance - * @param string $method The method used [up, down] - * @return array The queries executed by the processed schema + * @param string $method The method used [up, down] + * @return array The queries executed by the processed schema */ protected function getQueries(MigrationInterface $migration, $method) { @@ -440,7 +439,7 @@ protected function getQueries(MigrationInterface $migration, $method) /** * Resolve a migration instance from it's class name. * - * @param string $migrationClassName The class name + * @param string $migrationClassName The class name * @return MigrationInterface The migration class instance */ public function resolve($migrationClassName) @@ -561,7 +560,7 @@ protected function getSchemaGrammar() /** * Raise a note event for the migrator. * - * @param string $message The message + * @param string $message The message */ protected function note($message) { diff --git a/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php b/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php index 70e11f8aa..6b4b55896 100644 --- a/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php +++ b/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Models\Concerns; use Illuminate\Support\Arr; @@ -34,10 +35,10 @@ trait HasRelationships /** * Overrides the default Eloquent hasMany relationship to return a HasManySyncable. * - * @param string $related - * @param string $foreignKey - * @param string $localKey - * @return \UserFrosting\Sprinkle\Core\Database\Relations\HasManySyncable + * @param string $related + * @param string $foreignKey + * @param string $localKey + * @return HasManySyncable */ public function hasMany($related, $foreignKey = null, $localKey = null) { @@ -58,12 +59,12 @@ public function hasMany($related, $foreignKey = null, $localKey = null) /** * Overrides the default Eloquent morphMany relationship to return a MorphManySyncable. * - * @param string $related - * @param string $name - * @param string $type - * @param string $id - * @param string $localKey - * @return \UserFrosting\Sprinkle\Core\Database\Relations\MorphManySyncable + * @param string $related + * @param string $name + * @param string $type + * @param string $id + * @param string $localKey + * @return MorphManySyncable */ public function morphMany($related, $name, $type = null, $id = null, $localKey = null) { @@ -83,17 +84,17 @@ public function morphMany($related, $name, $type = null, $id = null, $localKey = * Define a many-to-many 'through' relationship. * This is basically hasManyThrough for many-to-many relationships. * - * @param string $related - * @param string $through - * @param string $firstJoiningTable - * @param string $firstForeignKey - * @param string $firstRelatedKey - * @param string $secondJoiningTable - * @param string $secondForeignKey - * @param string $secondRelatedKey - * @param string $throughRelation - * @param string $relation - * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyThrough + * @param string $related + * @param string $through + * @param string $firstJoiningTable + * @param string $firstForeignKey + * @param string $firstRelatedKey + * @param string $secondJoiningTable + * @param string $secondForeignKey + * @param string $secondRelatedKey + * @param string $throughRelation + * @param string $relation + * @return BelongsToManyThrough */ public function belongsToManyThrough( $related, @@ -115,7 +116,7 @@ public function belongsToManyThrough( } // Create models for through and related - $through = new $through; + $through = new $through(); $related = $this->newRelatedInstance($related); if (is_null($throughRelation)) { @@ -160,12 +161,12 @@ public function belongsToManyThrough( * Define a unique many-to-many relationship. Similar to a regular many-to-many relationship, but removes duplicate child objects. * Can also be used to implement ternary relationships. * - * @param string $related - * @param string $table - * @param string $foreignKey - * @param string $relatedKey - * @param string $relation - * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyUnique + * @param string $related + * @param string $table + * @param string $foreignKey + * @param string $relatedKey + * @param string $relation + * @return BelongsToManyUnique */ public function belongsToManyUnique($related, $table = null, $foreignKey = null, $relatedKey = null, $relation = null) { @@ -205,13 +206,13 @@ public function belongsToManyUnique($related, $table = null, $foreignKey = null, /** * Define a unique morphs-to-many relationship. Similar to a regular morphs-to-many relationship, but removes duplicate child objects. * - * @param string $related - * @param string $name - * @param string $table - * @param string $foreignKey - * @param string $otherKey - * @param bool $inverse - * @return \UserFrosting\Sprinkle\Core\Database\Relations\MorphToManyUnique + * @param string $related + * @param string $name + * @param string $table + * @param string $foreignKey + * @param string $otherKey + * @param bool $inverse + * @return MorphToManyUnique */ public function morphToManyUnique($related, $name, $table = null, $foreignKey = null, $otherKey = null, $inverse = false) { @@ -222,7 +223,7 @@ public function morphToManyUnique($related, $name, $table = null, $foreignKey = // instances, as well as the relationship instances we need for these. $foreignKey = $foreignKey ?: $name.'_id'; - $instance = new $related; + $instance = new $related(); $otherKey = $otherKey ?: $instance->getForeignKey(); @@ -251,13 +252,13 @@ public function morphToManyUnique($related, $name, $table = null, $foreignKey = * This has been superseded by the belongsToManyUnique relationship's `withTernary` method since 4.1.7. * * @deprecated since 4.1.6 - * @param string $related - * @param string $constraintKey - * @param string $table - * @param string $foreignKey - * @param string $relatedKey - * @param string $relation - * @return \UserFrosting\Sprinkle\Core\Database\Relations\BelongsToManyConstrained + * @param string $related + * @param string $constraintKey + * @param string $table + * @param string $foreignKey + * @param string $relatedKey + * @param string $relation + * @return BelongsToManyConstrained */ public function belongsToManyConstrained($related, $constraintKey, $table = null, $foreignKey = null, $relatedKey = null, $relation = null) { @@ -306,9 +307,10 @@ protected function getBelongsToManyCaller() $caller = Arr::first(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), function ($key, $trace) use ($self) { $caller = $trace['function']; - return ! in_array($caller, HasRelationships::$manyMethodsExtended) && $caller != $self; + + return !in_array($caller, HasRelationships::$manyMethodsExtended) && $caller != $self; }); - return ! is_null($caller) ? $caller['function'] : null; + return !is_null($caller) ? $caller['function'] : null; } } diff --git a/app/sprinkles/core/src/Database/Models/Model.php b/app/sprinkles/core/src/Database/Models/Model.php index 0c88ac487..abe9e9772 100644 --- a/app/sprinkles/core/src/Database/Models/Model.php +++ b/app/sprinkles/core/src/Database/Models/Model.php @@ -5,12 +5,13 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Models; use Interop\Container\ContainerInterface; use Illuminate\Database\Capsule\Manager as DB; use Illuminate\Database\Eloquent\Model as LaravelModel; -use UserFrosting\Sprinkle\Core\Database\Builder ; +use UserFrosting\Sprinkle\Core\Database\Builder; use UserFrosting\Sprinkle\Core\Database\Models\Concerns\HasRelationships; /** @@ -44,7 +45,7 @@ public function __construct(array $attributes = []) /** * Determine if an attribute exists on the model - even if it is null. * - * @param string $key + * @param string $key * @return bool */ public function attributeExists($key) @@ -55,10 +56,10 @@ public function attributeExists($key) /** * Determines whether a model exists by checking a unique column, including checking soft-deleted records * - * @param mixed $value - * @param string $identifier - * @param bool $checkDeleted set to true to include soft-deleted records - * @return \UserFrosting\Sprinkle\Core\Database\Models\Model|null + * @param mixed $value + * @param string $identifier + * @param bool $checkDeleted set to true to include soft-deleted records + * @return \UserFrosting\Sprinkle\Core\Database\Models\Model|null */ public static function findUnique($value, $identifier, $checkDeleted = true) { @@ -74,7 +75,7 @@ public static function findUnique($value, $identifier, $checkDeleted = true) /** * Determine if an relation exists on the model - even if it is null. * - * @param string $key + * @param string $key * @return bool */ public function relationExists($key) @@ -99,7 +100,7 @@ public function store() /** * Overrides Laravel's base Model to return our custom Eloquent builder object. * - * @param Builder $query + * @param Builder $query * @return \UserFrosting\Sprinkle\Core\Database\EloquentBuilder */ public function newEloquentBuilder($query) @@ -155,6 +156,7 @@ public static function queryBuilder() { // Set query builder to fetch result sets as associative arrays (instead of creating stdClass objects) DB::connection()->setFetchMode(\PDO::FETCH_ASSOC); + return DB::table(static::$table); } } diff --git a/app/sprinkles/core/src/Database/Models/Throttle.php b/app/sprinkles/core/src/Database/Models/Throttle.php index 779dbf6aa..d02c1bdb8 100644 --- a/app/sprinkles/core/src/Database/Models/Throttle.php +++ b/app/sprinkles/core/src/Database/Models/Throttle.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Models; /** @@ -21,12 +22,12 @@ class Throttle extends Model /** * @var string The name of the table for the current model. */ - protected $table = "throttles"; + protected $table = 'throttles'; protected $fillable = [ - "type", - "ip", - "request_data" + 'type', + 'ip', + 'request_data' ]; /** diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php index ba87a8b41..8207fda30 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Relations; use Illuminate\Database\Eloquent\Model; @@ -30,13 +31,13 @@ class BelongsToManyConstrained extends BelongsToMany /** * Create a new belongs to many constrained relationship instance. * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param \Illuminate\Database\Eloquent\Model $parent - * @param string $constraintKey - * @param string $table - * @param string $foreignKey - * @param string $relatedKey - * @param string $relationName + * @param \Illuminate\Database\Eloquent\Builder $query + * @param \Illuminate\Database\Eloquent\Model $parent + * @param string $constraintKey + * @param string $table + * @param string $foreignKey + * @param string $relatedKey + * @param string $relationName */ public function __construct(Builder $query, Model $parent, $constraintKey, $table, $foreignKey, $relatedKey, $relationName = null) { @@ -47,7 +48,7 @@ public function __construct(Builder $query, Model $parent, $constraintKey, $tabl /** * Set the constraints for an eager load of the relation. * - * @param array $models + * @param array $models */ public function addEagerConstraints(array $models) { @@ -61,8 +62,8 @@ public function addEagerConstraints(array $models) /** * Gets a list of unique pivot key values from an array of models. * - * @param array $models - * @param string $pivotKey + * @param array $models + * @param string $pivotKey * @return array */ protected function getPivotKeys(array $models, $pivotKey) @@ -71,6 +72,7 @@ protected function getPivotKeys(array $models, $pivotKey) foreach ($models as $model) { $pivotKeys[] = $model->getRelation('pivot')->{$pivotKey}; } + return array_unique($pivotKeys); } @@ -79,9 +81,9 @@ protected function getPivotKeys(array $models, $pivotKey) * in the parent object to the child objects. * * @see Called in https://github.com/laravel/framework/blob/2f4135d8db5ded851d1f4f611124c53b768a3c08/src/Illuminate/Database/Eloquent/Builder.php - * @param array $models - * @param \Illuminate\Database\Eloquent\Collection $results - * @param string $relation + * @param array $models + * @param \Illuminate\Database\Eloquent\Collection $results + * @param string $relation * @return array */ public function match(array $models, Collection $results, $relation) @@ -109,8 +111,8 @@ public function match(array $models, Collection $results, $relation) /** * Filter an array of models, only taking models whose $constraintKey value matches $pivotValue. * - * @param array $items - * @param mixed $pivotValue + * @param array $items + * @param mixed $pivotValue * @return array */ protected function findMatchingPivots($items, $pivotValue) @@ -121,6 +123,7 @@ protected function findMatchingPivots($items, $pivotValue) $result[] = $item; } } + return $result; } } diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php index 636202bf3..3fd2c7cb8 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Relations; use Illuminate\Database\Eloquent\Model; @@ -34,13 +35,13 @@ class BelongsToManyThrough extends BelongsToMany /** * Create a new belongs to many relationship instance. * - * @param \Illuminate\Database\Eloquent\Builder $query - * @param \Illuminate\Database\Eloquent\Model $parent - * @param \Illuminate\Database\Eloquent\Relations\Relation $intermediateRelation - * @param string $table - * @param string $foreignKey - * @param string $relatedKey - * @param string $relationName + * @param \Illuminate\Database\Eloquent\Builder $query + * @param \Illuminate\Database\Eloquent\Model $parent + * @param \Illuminate\Database\Eloquent\Relations\Relation $intermediateRelation + * @param string $table + * @param string $foreignKey + * @param string $relatedKey + * @param string $relationName */ public function __construct(Builder $query, Model $parent, Relation $intermediateRelation, $table, $foreignKey, $relatedKey, $relationName = null) { @@ -75,8 +76,8 @@ public function getExistenceCompareKey() /** * Add a "via" query to load the intermediate models through which the child models are related. * - * @param string $viaRelationName - * @param callable $viaCallback + * @param string $viaRelationName + * @param callable $viaCallback * @return self */ public function withVia($viaRelationName = null, $viaCallback = null) @@ -100,7 +101,7 @@ public function withVia($viaRelationName = null, $viaCallback = null) /** * Set the constraints for an eager load of the relation. * - * @param array $models + * @param array $models */ public function addEagerConstraints(array $models) { @@ -131,9 +132,9 @@ protected function addWhereConstraints() /** * Match the eagerly loaded results to their parents * - * @param array $models - * @param \Illuminate\Database\Eloquent\Collection $results - * @param string $relation + * @param array $models + * @param \Illuminate\Database\Eloquent\Collection $results + * @param string $relation * @return array */ public function match(array $models, Collection $results, $relation) @@ -175,7 +176,7 @@ public function match(array $models, Collection $results, $relation) /** * Unset tertiary pivots on a collection or array of models. * - * @param \Illuminate\Database\Eloquent\Collection $models + * @param \Illuminate\Database\Eloquent\Collection $models */ protected function unsetTertiaryPivots(Collection $models) { @@ -187,7 +188,7 @@ protected function unsetTertiaryPivots(Collection $models) /** * Set the join clause for the relation query. * - * @param \Illuminate\Database\Eloquent\Builder|null $query + * @param \Illuminate\Database\Eloquent\Builder|null $query * @return self */ protected function performJoin($query = null) diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php index 6423ba713..a0478d80e 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Relations; use Illuminate\Database\Eloquent\Relations\BelongsToMany; diff --git a/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php b/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php index 8855df2ac..3093de0b6 100644 --- a/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php +++ b/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Relations\Concerns; /** @@ -18,9 +19,9 @@ trait Syncable * Synchronizes an array of data for related models with a parent model. * * @param mixed[] $data - * @param bool $deleting Delete models from the database that are not represented in the input data. - * @param bool $forceCreate Ignore mass assignment restrictions on child models. - * @param string $relatedKeyName The primary key used to determine which child models are new, updated, or deleted. + * @param bool $deleting Delete models from the database that are not represented in the input data. + * @param bool $forceCreate Ignore mass assignment restrictions on child models. + * @param string $relatedKeyName The primary key used to determine which child models are new, updated, or deleted. */ public function sync($data, $deleting = true, $forceCreate = false, $relatedKeyName = null) { @@ -104,7 +105,7 @@ public function sync($data, $deleting = true, $forceCreate = false, $relatedKeyN /** * Cast the given keys to integers if they are numeric and string otherwise. * - * @param array $keys + * @param array $keys * @return array */ protected function castKeys(array $keys) @@ -117,7 +118,7 @@ protected function castKeys(array $keys) /** * Cast the given key to an integer if it is numeric. * - * @param mixed $key + * @param mixed $key * @return mixed */ protected function castKey($key) diff --git a/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php b/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php index ae730bf2f..c87668b0b 100644 --- a/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php +++ b/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Relations\Concerns; use Illuminate\Database\Eloquent\Builder; @@ -119,8 +120,8 @@ public function limit($value) * Set the limit on the number of intermediate models to load. * * @deprecated since 4.1.7 - * @param int $value - * @return $this + * @param int $value + * @return $this */ public function withLimit($value) { @@ -131,8 +132,8 @@ public function withLimit($value) * Set the offset when loading the intermediate models. * * @deprecated since 4.1.7 - * @param int $value - * @return $this + * @param int $value + * @return $this */ public function withOffset($value) { @@ -142,15 +143,15 @@ public function withOffset($value) /** * Add a query to load the nested tertiary models for this relationship. * - * @param string $tertiaryRelated - * @param string $tertiaryRelationName - * @param string $tertiaryKey - * @param callable $tertiaryCallback + * @param string $tertiaryRelated + * @param string $tertiaryRelationName + * @param string $tertiaryKey + * @param callable $tertiaryCallback * @return self */ public function withTertiary($tertiaryRelated, $tertiaryRelationName = null, $tertiaryKey = null, $tertiaryCallback = null) { - $this->tertiaryRelated = new $tertiaryRelated; + $this->tertiaryRelated = new $tertiaryRelated(); // Try to guess the tertiary related key from the tertiaryRelated model. $this->tertiaryKey = $tertiaryKey ?: $this->tertiaryRelated->getForeignKey(); @@ -188,8 +189,8 @@ public function count() * Add the constraints for a relationship count query. * * @see \Illuminate\Database\Eloquent\Relations\Relation - * @param Builder $query - * @param Builder $parentQuery + * @param Builder $query + * @param Builder $parentQuery * @return Builder */ public function getRelationExistenceCountQuery(Builder $query, Builder $parentQuery) @@ -204,9 +205,9 @@ public function getRelationExistenceCountQuery(Builder $query, Builder $parentQu /** * Match the eagerly loaded results to their parents * - * @param array $models - * @param Collection $results - * @param string $relation + * @param array $models + * @param Collection $results + * @param string $relation * @return array */ public function match(array $models, Collection $results, $relation) @@ -244,7 +245,7 @@ public function match(array $models, Collection $results, $relation) * Execute the query as a "select" statement, getting all requested models * and matching up any tertiary models. * - * @param array $columns + * @param array $columns * @return Collection */ public function get($columns = ['*']) @@ -262,9 +263,9 @@ public function get($columns = ['*']) * If we are applying either a limit or offset, we'll first determine a limited/offset list of model ids * to select from in the final query. * - * @param Builder $query - * @param int $limit - * @param int $offset + * @param Builder $query + * @param int $limit + * @param int $offset * @return Builder */ public function getPaginatedQuery(Builder $query, $limit = null, $offset = null) @@ -321,8 +322,8 @@ public function getEager() * Get the hydrated models and eager load their relations, optionally * condensing the set of models before performing the eager loads. * - * @param array $columns - * @param bool $condenseModels + * @param array $columns + * @param bool $condenseModels * @return Collection */ public function getModels($columns = ['*'], $condenseModels = true) @@ -396,8 +397,8 @@ protected function condenseModels(array $models) * that maps parent ids to arrays of related ids, which in turn map to arrays * of tertiary models corresponding to each relationship. * - * @param Collection $results - * @param string $parentKey + * @param Collection $results + * @param string $parentKey * @return array */ protected function buildDictionary(Collection $results, $parentKey = null) @@ -459,7 +460,7 @@ protected function buildDictionary(Collection $results, $parentKey = null) /** * Build dictionary of tertiary models keyed by the corresponding related model keys. * - * @param array $models + * @param array $models * @return array */ protected function buildTertiaryDictionary(array $models) @@ -486,8 +487,8 @@ protected function buildTertiaryDictionary(array $models) /** * Transfer the pivot to the tertiary model * - * @param Model $model - * @param Model $tertiaryModel + * @param Model $model + * @param Model $tertiaryModel */ protected function transferPivotsToTertiary($model, $tertiaryModel) { @@ -509,7 +510,7 @@ protected function transferPivotsToTertiary($model, $tertiaryModel) /** * Get the tertiary models for the relationship. * - * @param array $models + * @param array $models * @return Collection */ protected function getTertiaryModels(array $models) @@ -538,8 +539,8 @@ protected function getTertiaryModels(array $models) /** * Match a collection of child models into a collection of parent models using a dictionary. * - * @param array $dictionary - * @param Collection $results + * @param array $dictionary + * @param Collection $results */ protected function matchTertiaryModels(array $dictionary, Collection $results) { @@ -559,7 +560,7 @@ protected function matchTertiaryModels(array $dictionary, Collection $results) /** * Unset tertiary pivots on a collection or array of models. * - * @param Collection $models + * @param Collection $models */ protected function unsetTertiaryPivots(Collection $models) { diff --git a/app/sprinkles/core/src/Database/Relations/HasManySyncable.php b/app/sprinkles/core/src/Database/Relations/HasManySyncable.php index cd7e756b1..3acaac712 100644 --- a/app/sprinkles/core/src/Database/Relations/HasManySyncable.php +++ b/app/sprinkles/core/src/Database/Relations/HasManySyncable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Relations; use Illuminate\Database\Eloquent\Relations\HasMany; diff --git a/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php b/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php index 2644b8fa9..12d3e5fd8 100644 --- a/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php +++ b/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Relations; use Illuminate\Database\Eloquent\Relations\MorphMany; diff --git a/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php b/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php index 7e488632f..26637bfa6 100644 --- a/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php +++ b/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Relations; use Illuminate\Database\Eloquent\Relations\MorphToMany; diff --git a/app/sprinkles/core/src/Database/Seeder/BaseSeed.php b/app/sprinkles/core/src/Database/Seeder/BaseSeed.php index ce308e69a..ef625d2c3 100644 --- a/app/sprinkles/core/src/Database/Seeder/BaseSeed.php +++ b/app/sprinkles/core/src/Database/Seeder/BaseSeed.php @@ -5,10 +5,10 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Seeder; use Interop\Container\ContainerInterface; -use UserFrosting\Sprinkle\Core\Database\Seeder\SeedInterface; /** * Seeder Class diff --git a/app/sprinkles/core/src/Database/Seeder/SeedInterface.php b/app/sprinkles/core/src/Database/Seeder/SeedInterface.php index 31b5e3043..7253d08df 100644 --- a/app/sprinkles/core/src/Database/Seeder/SeedInterface.php +++ b/app/sprinkles/core/src/Database/Seeder/SeedInterface.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Seeder; /** diff --git a/app/sprinkles/core/src/Database/Seeder/Seeder.php b/app/sprinkles/core/src/Database/Seeder/Seeder.php index 12eeaf099..8a14fb9a8 100644 --- a/app/sprinkles/core/src/Database/Seeder/Seeder.php +++ b/app/sprinkles/core/src/Database/Seeder/Seeder.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Database\Seeder; use Interop\Container\ContainerInterface; @@ -53,14 +54,14 @@ public function getSeeds() /** * Get a single seed info * - * @param string $name The seed name - * @return array The details about a seed file [name, class, sprinkle] + * @param string $name The seed name * @throws \Exception If seed not found + * @return array The details about a seed file [name, class, sprinkle] */ public function getSeed($name) { // Get seed resource - $seedResource = $this->ci->locator->getResource($this->scheme . $name . ".php"); + $seedResource = $this->ci->locator->getResource($this->scheme . $name . '.php'); // Make sure we found something if (!$seedResource) { @@ -74,9 +75,9 @@ public function getSeed($name) /** * Return the class instance of a seed * - * @param string $name The seed name + * @param string $name The seed name + * @throws \Exception If class doesn't exist or is not right interface * @return SeedInterface The seed class instance - * @throws \Exception If class doesn't exist or is not right interface */ public function getSeedClass($name) { @@ -103,7 +104,7 @@ public function getSeedClass($name) /** * Execute a seed class * - * @param SeedInterface $seed The seed to execute + * @param SeedInterface $seed The seed to execute */ public function executeSeed(SeedInterface $seed) { @@ -122,14 +123,15 @@ protected function loadSeeders(array $seedFiles) foreach ($seedFiles as $seedFile) { $seeds[] = $this->getSeedDetails($seedFile); } + return $seeds; } /** * Return an array of seed details inclusing the classname and the sprinkle name * - * @param Resource $file The seed file - * @return array The details about a seed file [name, class, sprinkle] + * @param resource $file The seed file + * @return array The details about a seed file [name, class, sprinkle] */ protected function getSeedDetails(Resource $file) { @@ -144,8 +146,8 @@ protected function getSeedDetails(Resource $file) // Build the class name and namespace return [ - 'name' => $name, - 'class' => "\\UserFrosting\\Sprinkle\\$sprinkleName\\Database\\Seeds\\$className", + 'name' => $name, + 'class' => "\\UserFrosting\\Sprinkle\\$sprinkleName\\Database\\Seeds\\$className", 'sprinkle' => $sprinkleName ]; } diff --git a/app/sprinkles/core/src/Error/ExceptionHandlerManager.php b/app/sprinkles/core/src/Error/ExceptionHandlerManager.php index abf956e24..400a507c6 100755 --- a/app/sprinkles/core/src/Error/ExceptionHandlerManager.php +++ b/app/sprinkles/core/src/Error/ExceptionHandlerManager.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error; use Interop\Container\ContainerInterface; @@ -37,21 +38,21 @@ class ExceptionHandlerManager /** * Constructor * - * @param ContainerInterface $ci The global container object, which holds all your services. - * @param bool $displayErrorDetails Set to true to display full details + * @param ContainerInterface $ci The global container object, which holds all your services. + * @param bool $displayErrorDetails Set to true to display full details */ public function __construct(ContainerInterface $ci, $displayErrorDetails = false) { $this->ci = $ci; - $this->displayErrorDetails = (bool)$displayErrorDetails; + $this->displayErrorDetails = (bool) $displayErrorDetails; } /** * Invoke error handler * - * @param ServerRequestInterface $request The most recent Request object - * @param ResponseInterface $response The most recent Response object - * @param \Throwable $exception The caught Exception object + * @param ServerRequestInterface $request The most recent Request object + * @param ResponseInterface $response The most recent Response object + * @param \Throwable $exception The caught Exception object * @return ResponseInterface */ public function __invoke(ServerRequestInterface $request, ResponseInterface $response, $exception) @@ -76,14 +77,14 @@ public function __invoke(ServerRequestInterface $request, ResponseInterface $res * * The exception handler must implement \UserFrosting\Sprinkle\Core\Handler\ExceptionHandlerInterface. * - * @param string $exceptionClass The fully qualified class name of the exception to handle. - * @param string $handlerClass The fully qualified class name of the assigned handler. + * @param string $exceptionClass The fully qualified class name of the exception to handle. + * @param string $handlerClass The fully qualified class name of the assigned handler. * @throws \InvalidArgumentException If the registered handler fails to implement ExceptionHandlerInterface */ public function registerHandler($exceptionClass, $handlerClass) { if (!is_a($handlerClass, '\UserFrosting\Sprinkle\Core\Error\Handler\ExceptionHandlerInterface', true)) { - throw new \InvalidArgumentException("Registered exception handler must implement ExceptionHandlerInterface!"); + throw new \InvalidArgumentException('Registered exception handler must implement ExceptionHandlerInterface!'); } $this->exceptionHandlers[$exceptionClass] = $handlerClass; diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php index 46dd8aa5b..aa0f0f9b9 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Handler; use Interop\Container\ContainerInterface; @@ -73,9 +74,9 @@ class ExceptionHandler implements ExceptionHandlerInterface * Create a new ExceptionHandler object. * * @param ContainerInterface $ci - * @param ServerRequestInterface $request The most recent Request object - * @param ResponseInterface $response The most recent Response object - * @param \Throwable $exception The caught Exception object + * @param ServerRequestInterface $request The most recent Request object + * @param ResponseInterface $response The most recent Response object + * @param \Throwable $exception The caught Exception object * @param bool $displayErrorDetails */ public function __construct( @@ -151,7 +152,7 @@ public function renderGenericResponse() try { $template = $this->ci->view->getEnvironment()->loadTemplate("pages/error/$httpCode.html.twig"); } catch (\Twig_Error_Loader $e) { - $template = $this->ci->view->getEnvironment()->loadTemplate("pages/abstract/error.html.twig"); + $template = $this->ci->view->getEnvironment()->loadTemplate('pages/abstract/error.html.twig'); } return $this->response @@ -241,6 +242,7 @@ protected function determineStatusCode() if ($this->request->getMethod() === 'OPTIONS') { return 200; } + return 500; } @@ -252,7 +254,7 @@ protected function determineStatusCode() protected function determineUserMessages() { return [ - new UserMessage("ERROR.SERVER") + new UserMessage('ERROR.SERVER') ]; } diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php index 0611d5e54..50b4e9f48 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Handler; use Interop\Container\ContainerInterface; diff --git a/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php index b31180c7e..24799433d 100644 --- a/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Handler; use UserFrosting\Support\Exception\HttpException; @@ -41,6 +42,7 @@ protected function determineStatusCode() } elseif ($this->exception instanceof HttpException) { return $this->exception->getHttpErrorCode(); } + return 500; } @@ -57,7 +59,7 @@ protected function determineUserMessages() // Fallback return [ - new UserMessage("ERROR.SERVER") + new UserMessage('ERROR.SERVER') ]; } } diff --git a/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php index b99afd6bf..4f1f089d6 100644 --- a/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php @@ -5,10 +5,10 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Handler; use Psr\Http\Message\ResponseInterface; -use UserFrosting\Sprinkle\Core\Error\Handler\HttpExceptionHandler; /** * Handler for NotFoundExceptions. diff --git a/app/sprinkles/core/src/Error/Handler/PhpMailerExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/PhpMailerExceptionHandler.php index 45f0e8d59..18499dbf8 100644 --- a/app/sprinkles/core/src/Error/Handler/PhpMailerExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/PhpMailerExceptionHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Handler; use UserFrosting\Support\Message\UserMessage; @@ -24,7 +25,7 @@ class PhpMailerExceptionHandler extends ExceptionHandler protected function determineUserMessages() { return [ - new UserMessage("ERROR.MAIL") + new UserMessage('ERROR.MAIL') ]; } } diff --git a/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php b/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php index c46221abd..50c1feffd 100644 --- a/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Renderer; use Psr\Http\Message\ResponseInterface; @@ -43,10 +44,10 @@ abstract class ErrorRenderer implements ErrorRendererInterface /** * Create a new ErrorRenderer object. * - * @param ServerRequestInterface $request The most recent Request object - * @param ResponseInterface $response The most recent Response object - * @param \Throwable $exception The caught Exception object - * @param bool $displayErrorDetails + * @param ServerRequestInterface $request The most recent Request object + * @param ResponseInterface $response The most recent Response object + * @param \Throwable $exception The caught Exception object + * @param bool $displayErrorDetails */ public function __construct(ServerRequestInterface $request, ResponseInterface $response, $exception, $displayErrorDetails = false) { @@ -65,6 +66,7 @@ public function renderWithBody() { $body = new Body(fopen('php://temp', 'r+')); $body->write($this->render()); + return $body; } } diff --git a/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php b/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php index 8e485bda1..14567b180 100755 --- a/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php +++ b/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Renderer; use Psr\Http\Message\ResponseInterface; @@ -16,10 +17,10 @@ interface ErrorRendererInterface { /** - * @param ServerRequestInterface $request The most recent Request object - * @param ResponseInterface $response The most recent Response object - * @param \Throwable $exception The caught Exception object - * @param bool $displayErrorDetails + * @param ServerRequestInterface $request The most recent Request object + * @param ResponseInterface $response The most recent Response object + * @param \Throwable $exception The caught Exception object + * @param bool $displayErrorDetails */ public function __construct(ServerRequestInterface $request, ResponseInterface $response, $exception, $displayErrorDetails = false); diff --git a/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php b/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php index a5b24ceef..1d0ef0559 100644 --- a/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Renderer; class HtmlRenderer extends ErrorRenderer @@ -40,12 +41,12 @@ public function render() $output = sprintf( "" . - "%s

%s

%s", + '%s

%s

%s', $title, $title, $html @@ -57,7 +58,7 @@ public function render() /** * Render a summary of the exception. * - * @param \Exception $exception + * @param \Exception $exception * @return string */ public function renderException(\Exception $exception) @@ -133,7 +134,7 @@ public function renderResponseHeaders() /** * Render HTML representation of a table of data. * - * @param mixed[] $data the array of data to render. + * @param mixed[] $data the array of data to render. * @return string */ protected function renderTable($data) diff --git a/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php b/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php index 223de29cb..ffaf917e8 100755 --- a/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Renderer; /** @@ -18,11 +19,12 @@ class JsonRenderer extends ErrorRenderer public function render() { $message = $this->exception->getMessage(); + return $this->formatExceptionPayload($message); } /** - * @param string $message + * @param string $message * @return string */ public function formatExceptionPayload($message) @@ -41,17 +43,17 @@ public function formatExceptionPayload($message) } /** - * @param \Exception|\Throwable $e + * @param \Exception|\Throwable $e * @return array */ public function formatExceptionFragment($e) { return [ - 'type' => get_class($e), - 'code' => $e->getCode(), + 'type' => get_class($e), + 'code' => $e->getCode(), 'message' => $e->getMessage(), - 'file' => $e->getFile(), - 'line' => $e->getLine(), + 'file' => $e->getFile(), + 'line' => $e->getLine(), ]; } } diff --git a/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php b/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php index 9467fac43..d73b9bce5 100755 --- a/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Renderer; /** @@ -41,7 +42,7 @@ public function formatExceptionBody() } /** - * @param \Exception|\Throwable $e + * @param \Exception|\Throwable $e * @return string */ public function formatExceptionFragment($e) diff --git a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php index f91a34be2..f731057ab 100644 --- a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Renderer; use InvalidArgumentException; @@ -70,13 +71,13 @@ class WhoopsRenderer extends ErrorRenderer * @var array[] */ private $blacklist = [ - '_GET' => [], - '_POST' => [], - '_FILES' => [], - '_COOKIE' => [], + '_GET' => [], + '_POST' => [], + '_FILES' => [], + '_COOKIE' => [], '_SESSION' => [], - '_SERVER' => ['DB_PASSWORD', 'SMTP_PASSWORD'], - '_ENV' => ['DB_PASSWORD', 'SMTP_PASSWORD'], + '_SERVER' => ['DB_PASSWORD', 'SMTP_PASSWORD'], + '_ENV' => ['DB_PASSWORD', 'SMTP_PASSWORD'], ]; /** @@ -96,12 +97,12 @@ class WhoopsRenderer extends ErrorRenderer * @var array */ protected $editors = [ - "sublime" => "subl://open?url=file://%file&line=%line", - "textmate" => "txmt://open?url=file://%file&line=%line", - "emacs" => "emacs://open?url=file://%file&line=%line", - "macvim" => "mvim://open/?url=file://%file&line=%line", - "phpstorm" => "phpstorm://open?file=%file&line=%line", - "idea" => "idea://open?file=%file&line=%line", + 'sublime' => 'subl://open?url=file://%file&line=%line', + 'textmate' => 'txmt://open?url=file://%file&line=%line', + 'emacs' => 'emacs://open?url=file://%file&line=%line', + 'macvim' => 'mvim://open/?url=file://%file&line=%line', + 'phpstorm' => 'phpstorm://open?file=%file&line=%line', + 'idea' => 'idea://open?file=%file&line=%line', ]; /** @@ -184,19 +185,19 @@ public function render() } } - $templateFile = $this->getResource("views/layout.html.php"); - $cssFile = $this->getResource("css/whoops.base.css"); - $zeptoFile = $this->getResource("js/zepto.min.js"); - $prettifyFile = $this->getResource("js/prettify.min.js"); - $clipboard = $this->getResource("js/clipboard.min.js"); - $jsFile = $this->getResource("js/whoops.base.js"); + $templateFile = $this->getResource('views/layout.html.php'); + $cssFile = $this->getResource('css/whoops.base.css'); + $zeptoFile = $this->getResource('js/zepto.min.js'); + $prettifyFile = $this->getResource('js/prettify.min.js'); + $clipboard = $this->getResource('js/clipboard.min.js'); + $jsFile = $this->getResource('js/whoops.base.js'); if ($this->customCss) { $customCssFile = $this->getResource($this->customCss); } $inspector = $this->getInspector(); - $frames = $inspector->getFrames(); + $frames = $inspector->getFrames(); // Detect frames that belong to the application. if ($this->getApplicationPaths()) { @@ -219,63 +220,63 @@ public function render() } // Nicely format the session object - $session = isset($_SESSION) ? $this->masked($_SESSION, '_SESSION') : []; + $session = isset($_SESSION) ? $this->masked($_SESSION, '_SESSION') : []; $session = ['session' => Util::prettyPrintArray($session)]; // List of variables that will be passed to the layout template. $vars = [ - "page_title" => $this->getPageTitle(), + 'page_title' => $this->getPageTitle(), // @todo: Asset compiler - "stylesheet" => file_get_contents($cssFile), - "zepto" => file_get_contents($zeptoFile), - "prettify" => file_get_contents($prettifyFile), - "clipboard" => file_get_contents($clipboard), - "javascript" => file_get_contents($jsFile), + 'stylesheet' => file_get_contents($cssFile), + 'zepto' => file_get_contents($zeptoFile), + 'prettify' => file_get_contents($prettifyFile), + 'clipboard' => file_get_contents($clipboard), + 'javascript' => file_get_contents($jsFile), // Template paths: - "header" => $this->getResource("views/header.html.php"), - "header_outer" => $this->getResource("views/header_outer.html.php"), - "frame_list" => $this->getResource("views/frame_list.html.php"), - "frames_description" => $this->getResource("views/frames_description.html.php"), - "frames_container" => $this->getResource("views/frames_container.html.php"), - "panel_details" => $this->getResource("views/panel_details.html.php"), - "panel_details_outer" => $this->getResource("views/panel_details_outer.html.php"), - "panel_left" => $this->getResource("views/panel_left.html.php"), - "panel_left_outer" => $this->getResource("views/panel_left_outer.html.php"), - "frame_code" => $this->getResource("views/frame_code.html.php"), - "env_details" => $this->getResource("views/env_details.html.php"), - - "title" => $this->getPageTitle(), - "name" => explode("\\", $inspector->getExceptionName()), - "message" => $inspector->getExceptionMessage(), - "previousMessages" => $inspector->getPreviousExceptionMessages(), - "docref_url" => $inspector->getExceptionDocrefUrl(), - "code" => $code, - "previousCodes" => $inspector->getPreviousExceptionCodes(), - "plain_exception" => Formatter::formatExceptionPlain($inspector), - "frames" => $frames, - "has_frames" => !!count($frames), - "handler" => $this, - "handlers" => [$this], - "prettify" => true, - - "active_frames_tab" => count($frames) && $frames->offsetGet(0)->isApplication() ? 'application' : 'all', - "has_frames_tabs" => $this->getApplicationPaths(), - - "tables" => [ - "GET Data" => $this->masked($_GET, '_GET'), - "POST Data" => $this->masked($_POST, '_POST'), - "Files" => isset($_FILES) ? $this->masked($_FILES, '_FILES') : [], - "Cookies" => $this->masked($_COOKIE, '_COOKIE'), - "Session" => $session, - "Server/Request Data" => $this->masked($_SERVER, '_SERVER'), - "Environment Variables" => $this->masked($_ENV, '_ENV'), + 'header' => $this->getResource('views/header.html.php'), + 'header_outer' => $this->getResource('views/header_outer.html.php'), + 'frame_list' => $this->getResource('views/frame_list.html.php'), + 'frames_description' => $this->getResource('views/frames_description.html.php'), + 'frames_container' => $this->getResource('views/frames_container.html.php'), + 'panel_details' => $this->getResource('views/panel_details.html.php'), + 'panel_details_outer' => $this->getResource('views/panel_details_outer.html.php'), + 'panel_left' => $this->getResource('views/panel_left.html.php'), + 'panel_left_outer' => $this->getResource('views/panel_left_outer.html.php'), + 'frame_code' => $this->getResource('views/frame_code.html.php'), + 'env_details' => $this->getResource('views/env_details.html.php'), + + 'title' => $this->getPageTitle(), + 'name' => explode('\\', $inspector->getExceptionName()), + 'message' => $inspector->getExceptionMessage(), + 'previousMessages' => $inspector->getPreviousExceptionMessages(), + 'docref_url' => $inspector->getExceptionDocrefUrl(), + 'code' => $code, + 'previousCodes' => $inspector->getPreviousExceptionCodes(), + 'plain_exception' => Formatter::formatExceptionPlain($inspector), + 'frames' => $frames, + 'has_frames' => (bool) count($frames), + 'handler' => $this, + 'handlers' => [$this], + 'prettify' => true, + + 'active_frames_tab' => count($frames) && $frames->offsetGet(0)->isApplication() ? 'application' : 'all', + 'has_frames_tabs' => $this->getApplicationPaths(), + + 'tables' => [ + 'GET Data' => $this->masked($_GET, '_GET'), + 'POST Data' => $this->masked($_POST, '_POST'), + 'Files' => isset($_FILES) ? $this->masked($_FILES, '_FILES') : [], + 'Cookies' => $this->masked($_COOKIE, '_COOKIE'), + 'Session' => $session, + 'Server/Request Data' => $this->masked($_SERVER, '_SERVER'), + 'Environment Variables' => $this->masked($_ENV, '_ENV'), ], ]; if (isset($customCssFile)) { - $vars["stylesheet"] .= file_get_contents($customCssFile); + $vars['stylesheet'] .= file_get_contents($customCssFile); } // Add extra entries list of data tables: @@ -283,12 +284,12 @@ public function render() $extraTables = array_map(function ($table) use ($inspector) { return $table instanceof \Closure ? $table($inspector) : $table; }, $this->getDataTables()); - $vars["tables"] = array_merge($extraTables, $vars["tables"]); + $vars['tables'] = array_merge($extraTables, $vars['tables']); $plainTextHandler = new PlainTextHandler(); $plainTextHandler->setException($this->getException()); $plainTextHandler->setInspector($this->getInspector()); - $vars["preface"] = ""; + $vars['preface'] = ""; $this->templateHelper->setVariables($vars); @@ -296,6 +297,7 @@ public function render() $this->templateHelper->render($templateFile); $result = ob_get_clean(); + return $result; } @@ -318,9 +320,9 @@ public function addDataTable($label, array $data) * it should produce a simple associative array. Any nested arrays will * be flattened with print_r. * - * @throws InvalidArgumentException If $callback is not callable * @param string $label * @param callable $callback Callable returning an associative array + * @throws InvalidArgumentException If $callback is not callable */ public function addDataTableCallback($label, /* callable */ $callback) { @@ -345,7 +347,7 @@ public function addDataTableCallback($label, /* callable */ $callback) * blacklist a sensitive value within one of the superglobal arrays. * * @param string $superGlobalName The name of the superglobal array, e.g. '_GET' - * @param string $key The key within the superglobal + * @param string $key The key within the superglobal */ public function blacklist($superGlobalName, $key) { @@ -419,15 +421,15 @@ public function addEditor($identifier, $resolver) * @example * $run->setEditor('sublime'); * - * @throws InvalidArgumentException If invalid argument identifier provided * @param string|callable $editor + * @throws InvalidArgumentException If invalid argument identifier provided */ public function setEditor($editor) { if (!is_callable($editor) && !isset($this->editors[$editor])) { throw new InvalidArgumentException( "Unknown editor identifier: $editor. Known editors:" . - implode(",", array_keys($this->editors)) + implode(',', array_keys($this->editors)) ); } @@ -440,9 +442,9 @@ public function setEditor($editor) * a string that may be used as the href property for that * file reference. * - * @throws InvalidArgumentException If editor resolver does not return a string * @param string $filePath * @param int $line + * @throws InvalidArgumentException If editor resolver does not return a string * @return string|bool */ public function getEditorHref($filePath, $line) @@ -457,12 +459,12 @@ public function getEditorHref($filePath, $line) // %line and %file placeholders: if (!isset($editor['url']) || !is_string($editor['url'])) { throw new UnexpectedValueException( - __METHOD__ . " should always resolve to a string or a valid editor array; got something else instead." + __METHOD__ . ' should always resolve to a string or a valid editor array; got something else instead.' ); } - $editor['url'] = str_replace("%line", rawurlencode($line), $editor['url']); - $editor['url'] = str_replace("%file", rawurlencode($filePath), $editor['url']); + $editor['url'] = str_replace('%line', rawurlencode($line), $editor['url']); + $editor['url'] = str_replace('%file', rawurlencode($filePath), $editor['url']); return $editor['url']; } @@ -472,9 +474,9 @@ public function getEditorHref($filePath, $line) * act as an Ajax request. The editor must be a * valid callable function/closure * - * @throws UnexpectedValueException If editor resolver does not return a boolean * @param string $filePath * @param int $line + * @throws UnexpectedValueException If editor resolver does not return a boolean * @return bool */ public function getEditorAjax($filePath, $line) @@ -484,9 +486,10 @@ public function getEditorAjax($filePath, $line) // Check that the ajax is a bool if (!isset($editor['ajax']) || !is_bool($editor['ajax'])) { throw new UnexpectedValueException( - __METHOD__ . " should always resolve to a bool; got something else instead." + __METHOD__ . ' should always resolve to a bool; got something else instead.' ); } + return $editor['ajax']; } @@ -510,8 +513,8 @@ public function getPageTitle() * Adds a path to the list of paths to be searched for * resources. * + * @param string $path * @throws InvalidArgumentException If $path is not a valid directory - * @param string $path */ public function addResourcePath($path) { @@ -611,7 +614,7 @@ protected function getEditor($filePath, $line) if (is_string($this->editor) && isset($this->editors[$this->editor]) && !is_callable($this->editors[$this->editor])) { return [ 'ajax' => false, - 'url' => $this->editors[$this->editor], + 'url' => $this->editors[$this->editor], ]; } @@ -625,13 +628,13 @@ protected function getEditor($filePath, $line) if (is_string($callback)) { return [ 'ajax' => false, - 'url' => $callback, + 'url' => $callback, ]; } return [ 'ajax' => isset($callback['ajax']) ? $callback['ajax'] : false, - 'url' => isset($callback['url']) ? $callback['url'] : $callback, + 'url' => isset($callback['url']) ? $callback['url'] : $callback, ]; } @@ -660,8 +663,8 @@ protected function getInspector() * way back to the first, enabling a cascading-type system of overrides * for all resources. * + * @param string $resource * @throws RuntimeException If resource cannot be found in any of the available paths - * @param string $resource * @return string */ protected function getResource($resource) @@ -680,6 +683,7 @@ protected function getResource($resource) if (is_file($fullPath)) { // Cache the result: $this->resourceCache[$resource] = $fullPath; + return $fullPath; } } @@ -687,7 +691,7 @@ protected function getResource($resource) // If we got this far, nothing was found. throw new RuntimeException( "Could not find resource '$resource' in any resource paths." - . "(searched: " . join(", ", $this->searchPaths). ")" + . '(searched: ' . join(', ', $this->searchPaths). ')' ); } @@ -697,9 +701,9 @@ protected function getResource($resource) * * We intentionally dont rely on $GLOBALS as it depends on 'auto_globals_jit' php.ini setting. * - * @param array $superGlobal One of the superglobal arrays - * @param string $superGlobalName the name of the superglobal array, e.g. '_GET' - * @return array $values without sensitive data + * @param array $superGlobal One of the superglobal arrays + * @param string $superGlobalName the name of the superglobal array, e.g. '_GET' + * @return array $values without sensitive data */ private function masked(array $superGlobal, $superGlobalName) { @@ -711,6 +715,7 @@ private function masked(array $superGlobal, $superGlobalName) $values[$key] = str_repeat('*', strlen($superGlobal[$key])); } } + return $values; } } diff --git a/app/sprinkles/core/src/Error/Renderer/XmlRenderer.php b/app/sprinkles/core/src/Error/Renderer/XmlRenderer.php index 52e71cfe8..36e7ed6ee 100755 --- a/app/sprinkles/core/src/Error/Renderer/XmlRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/XmlRenderer.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Error\Renderer; /** @@ -22,15 +23,15 @@ public function render() if ($this->displayErrorDetails) { do { $xml .= " \n"; - $xml .= " " . get_class($e) . "\n"; - $xml .= " " . $e->getCode() . "\n"; - $xml .= " " . $this->createCdataSection($e->getMessage()) . "\n"; - $xml .= " " . $e->getFile() . "\n"; - $xml .= " " . $e->getLine() . "\n"; + $xml .= ' ' . get_class($e) . "\n"; + $xml .= ' ' . $e->getCode() . "\n"; + $xml .= ' ' . $this->createCdataSection($e->getMessage()) . "\n"; + $xml .= ' ' . $e->getFile() . "\n"; + $xml .= ' ' . $e->getLine() . "\n"; $xml .= " \n"; } while ($e = $e->getPrevious()); } - $xml .= ""; + $xml .= ''; return $xml; } diff --git a/app/sprinkles/core/src/Facades/Config.php b/app/sprinkles/core/src/Facades/Config.php index d0436e7c2..514f60011 100644 --- a/app/sprinkles/core/src/Facades/Config.php +++ b/app/sprinkles/core/src/Facades/Config.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Facades; use UserFrosting\System\Facade; diff --git a/app/sprinkles/core/src/Facades/Debug.php b/app/sprinkles/core/src/Facades/Debug.php index 86ef45093..4dc0f93f8 100644 --- a/app/sprinkles/core/src/Facades/Debug.php +++ b/app/sprinkles/core/src/Facades/Debug.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Facades; use UserFrosting\System\Facade; diff --git a/app/sprinkles/core/src/Facades/Storage.php b/app/sprinkles/core/src/Facades/Storage.php index 22b97fc78..32c296e49 100644 --- a/app/sprinkles/core/src/Facades/Storage.php +++ b/app/sprinkles/core/src/Facades/Storage.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Facades; use UserFrosting\System\Facade; diff --git a/app/sprinkles/core/src/Facades/Translator.php b/app/sprinkles/core/src/Facades/Translator.php index e6fccccee..814f680b6 100644 --- a/app/sprinkles/core/src/Facades/Translator.php +++ b/app/sprinkles/core/src/Facades/Translator.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Facades; use UserFrosting\System\Facade; diff --git a/app/sprinkles/core/src/Filesystem/FilesystemManager.php b/app/sprinkles/core/src/Filesystem/FilesystemManager.php index e9ca41fd6..b993bc859 100644 --- a/app/sprinkles/core/src/Filesystem/FilesystemManager.php +++ b/app/sprinkles/core/src/Filesystem/FilesystemManager.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Filesystem; use League\Flysystem\FilesystemInterface; @@ -28,8 +29,7 @@ class FilesystemManager extends LaravelFilesystemManager /** * Create a new filesystem manager instance. * - * @param \UserFrosting\Support\Repository\Repository $config - * @return void + * @param \UserFrosting\Support\Repository\Repository $config */ public function __construct(ConfigRepository $config) { @@ -39,7 +39,7 @@ public function __construct(ConfigRepository $config) /** * Call a custom driver creator. * - * @param array $config + * @param array $config * @return \Illuminate\Contracts\Filesystem\Filesystem */ protected function callCustomCreator(array $config) @@ -56,10 +56,9 @@ protected function callCustomCreator(array $config) /** * Create a cache store instance. * - * @param mixed $config - * @return \League\Flysystem\Cached\CacheInterface - * + * @param mixed $config * @throws \InvalidArgumentException + * @return \League\Flysystem\Cached\CacheInterface */ // N.B.: Introduced after laravel 5.4 /*protected function createCacheStore($config) @@ -78,7 +77,7 @@ protected function callCustomCreator(array $config) /** * Get the filesystem connection configuration. * - * @param string $name + * @param string $name * @return array */ protected function getConfig($name) diff --git a/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php b/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php index ec567adc6..8ed008749 100644 --- a/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php +++ b/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Http\Concerns; use Psr\Http\Message\ServerRequestInterface; @@ -36,8 +37,8 @@ trait DeterminesContentType * Slim's error handling requirements. Consider a fully-feature solution such * as willdurand/negotiation for any other situation. * - * @param ServerRequestInterface $request - * @param bool $ajaxDebug + * @param ServerRequestInterface $request + * @param bool $ajaxDebug * @return string */ protected function determineContentType(ServerRequestInterface $request, $ajaxDebug = false) @@ -54,7 +55,7 @@ protected function determineContentType(ServerRequestInterface $request, $ajaxDe if ($count) { $current = current($selectedContentTypes); - /** + /* * Ensure other supported content types take precedence over text/plain * when multiple content types are provided via Accept header. */ diff --git a/app/sprinkles/core/src/Log/DatabaseHandler.php b/app/sprinkles/core/src/Log/DatabaseHandler.php index 4aa2dd2d8..4ddfc5ee1 100644 --- a/app/sprinkles/core/src/Log/DatabaseHandler.php +++ b/app/sprinkles/core/src/Log/DatabaseHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Log; use Monolog\Logger; @@ -31,10 +32,10 @@ class DatabaseHandler extends AbstractProcessingHandler /** * Create a new DatabaseHandler object. * - * @param ClassMapper $classMapper Maps the modelIdentifier to the specific Eloquent model. - * @param string $modelIdentifier - * @param int $level The minimum logging level at which this handler will be triggered - * @param bool $bubble Whether the messages that are handled can bubble up the stack or not + * @param ClassMapper $classMapper Maps the modelIdentifier to the specific Eloquent model. + * @param string $modelIdentifier + * @param int $level The minimum logging level at which this handler will be triggered + * @param bool $bubble Whether the messages that are handled can bubble up the stack or not */ public function __construct(ClassMapper $classMapper, $modelIdentifier, $level = Logger::DEBUG, $bubble = true) { diff --git a/app/sprinkles/core/src/Log/MixedFormatter.php b/app/sprinkles/core/src/Log/MixedFormatter.php index 0eaaf40e8..4111256bb 100644 --- a/app/sprinkles/core/src/Log/MixedFormatter.php +++ b/app/sprinkles/core/src/Log/MixedFormatter.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Log; use Monolog\Formatter\LineFormatter; @@ -19,13 +20,12 @@ */ class MixedFormatter extends LineFormatter { - /** * Return the JSON representation of a value * - * @throws \RuntimeException if encoding fails and errors are not ignored * @param mixed $data * @param bool $ignoreErrors + * @throws \RuntimeException if encoding fails and errors are not ignored * @return string */ protected function toJson($data, $ignoreErrors = false) diff --git a/app/sprinkles/core/src/Mail/EmailRecipient.php b/app/sprinkles/core/src/Mail/EmailRecipient.php index 0b9381a9a..fb2843a88 100755 --- a/app/sprinkles/core/src/Mail/EmailRecipient.php +++ b/app/sprinkles/core/src/Mail/EmailRecipient.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Mail; /** @@ -16,7 +17,6 @@ */ class EmailRecipient { - /** * @var string The email address for this recipient. */ @@ -45,11 +45,11 @@ class EmailRecipient /** * Create a new EmailRecipient instance. * - * @param string $email The primary recipient email address. - * @param string $name The primary recipient name. - * @param array $params An array of template parameters to render the email message with for this particular recipient. + * @param string $email The primary recipient email address. + * @param string $name The primary recipient name. + * @param array $params An array of template parameters to render the email message with for this particular recipient. */ - public function __construct($email, $name = "", $params = []) + public function __construct($email, $name = '', $params = []) { $this->email = $email; $this->name = $name; @@ -60,13 +60,13 @@ public function __construct($email, $name = "", $params = []) * Add a CC for this primary recipient. * * @param string $email The CC recipient email address. - * @param string $name The CC recipient name. + * @param string $name The CC recipient name. */ - public function cc($email, $name = "") + public function cc($email, $name = '') { $this->cc[] = [ - "email" => $email, - "name" => $name + 'email' => $email, + 'name' => $name ]; } @@ -74,13 +74,13 @@ public function cc($email, $name = "") * Add a BCC for this primary recipient. * * @param string $email The BCC recipient email address. - * @param string $name The BCC recipient name. + * @param string $name The BCC recipient name. */ - public function bcc($email, $name = "") + public function bcc($email, $name = '') { $this->bcc[] = [ - "email" => $email, - "name" => $name + 'email' => $email, + 'name' => $name ]; } diff --git a/app/sprinkles/core/src/Mail/MailMessage.php b/app/sprinkles/core/src/Mail/MailMessage.php index cd4909693..9fd18f33b 100644 --- a/app/sprinkles/core/src/Mail/MailMessage.php +++ b/app/sprinkles/core/src/Mail/MailMessage.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Mail; /** @@ -19,7 +20,7 @@ abstract class MailMessage /** * @var string The current sender email address. */ - protected $fromEmail = ""; + protected $fromEmail = ''; /** * @var string The current sender name. @@ -44,7 +45,7 @@ abstract class MailMessage /** * Gets the fully rendered text of the message body. * - * @param array $params + * @param array $params * @return string */ abstract public function renderBody($params = []); @@ -52,7 +53,7 @@ abstract public function renderBody($params = []); /** * Gets the fully rendered text of the message subject. * - * @param array $params + * @param array $params * @return string */ abstract public function renderSubject($params = []); @@ -65,6 +66,7 @@ abstract public function renderSubject($params = []); public function addEmailRecipient(EmailRecipient $recipient) { $this->recipients[] = $recipient; + return $this; } @@ -73,7 +75,7 @@ public function addEmailRecipient(EmailRecipient $recipient) */ public function clearRecipients() { - $this->recipients = array(); + $this->recipients = []; } /** @@ -84,7 +86,7 @@ public function clearRecipients() */ public function from($fromInfo = []) { - $this->setFromEmail(isset($fromInfo['email']) ? $fromInfo['email'] : ""); + $this->setFromEmail(isset($fromInfo['email']) ? $fromInfo['email'] : ''); $this->setFromName(isset($fromInfo['name']) ? $fromInfo['name'] : null); $this->setReplyEmail(isset($fromInfo['reply_email']) ? $fromInfo['reply_email'] : null); $this->setReplyName(isset($fromInfo['reply_name']) ? $fromInfo['reply_name'] : null); @@ -150,6 +152,7 @@ public function getReplyName() public function setFromEmail($fromEmail) { $this->fromEmail = $fromEmail; + return $this; } @@ -161,6 +164,7 @@ public function setFromEmail($fromEmail) public function setFromName($fromName) { $this->fromName = $fromName; + return $this; } @@ -172,6 +176,7 @@ public function setFromName($fromName) public function setReplyEmail($replyEmail) { $this->replyEmail = $replyEmail; + return $this; } @@ -183,6 +188,7 @@ public function setReplyEmail($replyEmail) public function setReplyName($replyName) { $this->replyName = $replyName; + return $this; } } diff --git a/app/sprinkles/core/src/Mail/Mailer.php b/app/sprinkles/core/src/Mail/Mailer.php index b007a8bf0..b4ea8ecb7 100755 --- a/app/sprinkles/core/src/Mail/Mailer.php +++ b/app/sprinkles/core/src/Mail/Mailer.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Mail; use Monolog\Logger; @@ -31,8 +32,8 @@ class Mailer /** * Create a new Mailer instance. * - * @param Logger $logger A Monolog logger, used to dump debugging info for SMTP server transactions. - * @param mixed[] $config An array of configuration parameters for phpMailer. + * @param Logger $logger A Monolog logger, used to dump debugging info for SMTP server transactions. + * @param mixed[] $config An array of configuration parameters for phpMailer. * @throws \phpmailerException Wrong mailer config value given. */ public function __construct($logger, $config = []) @@ -50,13 +51,13 @@ public function __construct($logger, $config = []) if ($config['mailer'] == 'smtp') { $this->phpMailer->isSMTP(true); - $this->phpMailer->Host = $config['host']; - $this->phpMailer->Port = $config['port']; - $this->phpMailer->SMTPAuth = $config['auth']; + $this->phpMailer->Host = $config['host']; + $this->phpMailer->Port = $config['port']; + $this->phpMailer->SMTPAuth = $config['auth']; $this->phpMailer->SMTPSecure = $config['secure']; - $this->phpMailer->Username = $config['username']; - $this->phpMailer->Password = $config['password']; - $this->phpMailer->SMTPDebug = $config['smtp_debug']; + $this->phpMailer->Username = $config['username']; + $this->phpMailer->Password = $config['password']; + $this->phpMailer->SMTPDebug = $config['smtp_debug']; if (isset($config['smtp_options'])) { $this->phpMailer->SMTPOptions = $config['smtp_options']; @@ -91,8 +92,8 @@ public function getPhpMailer() * * Sends a single email to all recipients, as well as their CCs and BCCs. * Since it is a single-header message, recipient-specific template data will not be included. - * @param MailMessage $message - * @param bool $clearRecipients Set to true to clear the list of recipients in the message after calling send(). This helps avoid accidentally sending a message multiple times. + * @param MailMessage $message + * @param bool $clearRecipients Set to true to clear the list of recipients in the message after calling send(). This helps avoid accidentally sending a message multiple times. * @throws \phpmailerException The message could not be sent. */ public function send(MailMessage $message, $clearRecipients = true) @@ -111,7 +112,7 @@ public function send(MailMessage $message, $clearRecipients = true) $this->phpMailer->addCC($cc['email'], $cc['name']); } } - + if ($recipient->getBCCs()) { foreach ($recipient->getBCCs() as $bcc) { $this->phpMailer->addBCC($bcc['email'], $bcc['name']); @@ -120,7 +121,7 @@ public function send(MailMessage $message, $clearRecipients = true) } $this->phpMailer->Subject = $message->renderSubject(); - $this->phpMailer->Body = $message->renderBody(); + $this->phpMailer->Body = $message->renderBody(); // Try to send the mail. Will throw an exception on failure. $this->phpMailer->send(); @@ -139,8 +140,8 @@ public function send(MailMessage $message, $clearRecipients = true) * Send a MailMessage message, sending a separate email to each recipient. * * If the message object supports message templates, this will render the template with the corresponding placeholder values for each recipient. - * @param MailMessage $message - * @param bool $clearRecipients Set to true to clear the list of recipients in the message after calling send(). This helps avoid accidentally sending a message multiple times. + * @param MailMessage $message + * @param bool $clearRecipients Set to true to clear the list of recipients in the message after calling send(). This helps avoid accidentally sending a message multiple times. * @throws \phpmailerException The message could not be sent. */ public function sendDistinct(MailMessage $message, $clearRecipients = true) @@ -159,19 +160,19 @@ public function sendDistinct(MailMessage $message, $clearRecipients = true) $this->phpMailer->addCC($cc['email'], $cc['name']); } } - + if ($recipient->getBCCs()) { foreach ($recipient->getBCCs() as $bcc) { $this->phpMailer->addBCC($bcc['email'], $bcc['name']); } } - + $this->phpMailer->Subject = $message->renderSubject($recipient->getParams()); - $this->phpMailer->Body = $message->renderBody($recipient->getParams()); - + $this->phpMailer->Body = $message->renderBody($recipient->getParams()); + // Try to send the mail. Will throw an exception on failure. $this->phpMailer->send(); - + // Clear recipients from the PHPMailer object for this iteration, // so that we can send a separate email to the next recipient. $this->phpMailer->clearAllRecipients(); @@ -186,7 +187,7 @@ public function sendDistinct(MailMessage $message, $clearRecipients = true) /** * Set option(s) on the underlying phpMailer object. * - * @param mixed[] $options + * @param mixed[] $options * @return Mailer */ public function setOptions($options) diff --git a/app/sprinkles/core/src/Mail/StaticMailMessage.php b/app/sprinkles/core/src/Mail/StaticMailMessage.php index ebbaa16dd..22ec70533 100644 --- a/app/sprinkles/core/src/Mail/StaticMailMessage.php +++ b/app/sprinkles/core/src/Mail/StaticMailMessage.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Mail; /** @@ -32,7 +33,7 @@ class StaticMailMessage extends MailMessage * @param string $subject * @param string $body */ - public function __construct($subject = "", $body = "") + public function __construct($subject = '', $body = '') { $this->subject = $subject; $this->body = $body; @@ -62,6 +63,7 @@ public function renderSubject($params = []) public function setSubject($subject) { $this->subject = $subject; + return $this; } @@ -73,6 +75,7 @@ public function setSubject($subject) public function setBody($body) { $this->body = $body; + return $this; } } diff --git a/app/sprinkles/core/src/Mail/TwigMailMessage.php b/app/sprinkles/core/src/Mail/TwigMailMessage.php index f28cb72ad..6c979d7b3 100644 --- a/app/sprinkles/core/src/Mail/TwigMailMessage.php +++ b/app/sprinkles/core/src/Mail/TwigMailMessage.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Mail; use Slim\Views\Twig; @@ -36,7 +37,7 @@ class TwigMailMessage extends MailMessage /** * Create a new TwigMailMessage instance. * - * @param Twig $view The Twig view object used to render mail templates. + * @param Twig $view The Twig view object used to render mail templates. * @param string $filename optional Set the Twig template to use for this message. */ public function __construct(Twig $view, $filename = null) @@ -61,6 +62,7 @@ public function __construct(Twig $view, $filename = null) public function addParams($params = []) { $this->params = array_replace_recursive($this->params, $params); + return $this; } @@ -70,6 +72,7 @@ public function addParams($params = []) public function renderSubject($params = []) { $params = array_replace_recursive($this->params, $params); + return $this->template->renderBlock('subject', $params); } @@ -79,6 +82,7 @@ public function renderSubject($params = []) public function renderBody($params = []) { $params = array_replace_recursive($this->params, $params); + return $this->template->renderBlock('body', $params); } @@ -90,6 +94,7 @@ public function renderBody($params = []) public function setTemplate(\Twig_Template $template) { $this->template = $template; + return $this; } } diff --git a/app/sprinkles/core/src/Model/UFModel.php b/app/sprinkles/core/src/Model/UFModel.php index 1e21f6339..60635e035 100644 --- a/app/sprinkles/core/src/Model/UFModel.php +++ b/app/sprinkles/core/src/Model/UFModel.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Model; use UserFrosting\Sprinkle\Core\Database\Models\Model; @@ -20,7 +21,7 @@ abstract class UFModel extends Model { public function __construct(array $attributes = []) { - Debug::warning("UFModel has been deprecated and will be removed in future versions. Please move your model " . static::class . " to Database/Models/ and have it extend the base Database/Models/Model class."); + Debug::warning('UFModel has been deprecated and will be removed in future versions. Please move your model ' . static::class . ' to Database/Models/ and have it extend the base Database/Models/Model class.'); parent::__construct($attributes); } diff --git a/app/sprinkles/core/src/Router.php b/app/sprinkles/core/src/Router.php index 6bb7b538e..60ff05a91 100644 --- a/app/sprinkles/core/src/Router.php +++ b/app/sprinkles/core/src/Router.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core; use Illuminate\Filesystem\Filesystem; @@ -21,7 +22,6 @@ */ class Router extends \Slim\Router implements RouterInterface { - /** * @var string[] a reverse lookup of route identifiers, indexed by route signature */ @@ -30,13 +30,12 @@ class Router extends \Slim\Router implements RouterInterface /** * Add route * - * @param string[] $methods Array of HTTP methods - * @param string $pattern The route pattern - * @param callable $handler The route callable - * - * @return RouteInterface + * @param string[] $methods Array of HTTP methods + * @param string $pattern The route pattern + * @param callable $handler The route callable * * @throws InvalidArgumentException if the route pattern isn't a string + * @return RouteInterface */ public function map($methods, $pattern, $handler) { @@ -50,7 +49,7 @@ public function map($methods, $pattern, $handler) } // According to RFC methods are defined in uppercase (See RFC 7231) - $methods = array_map("strtoupper", $methods); + $methods = array_map('strtoupper', $methods); // Determine route signature $signature = implode('-', $methods) . '-' . $pattern; @@ -80,7 +79,7 @@ public function map($methods, $pattern, $handler) public function clearCache() { // Get Filesystem instance - $fs = new Filesystem; + $fs = new Filesystem(); // Make sure file exist and delete it if ($fs->exists($this->cacheFile)) { @@ -94,7 +93,7 @@ public function clearCache() /** * Load all avaialbe routes * - * @param App $slimApp + * @param App $slimApp */ public function loadRoutes(App $slimApp) { diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 1b2564b9e..3eeeaf0e8 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\ServicesProvider; use Dotenv\Dotenv; @@ -78,7 +79,7 @@ public function register(ContainerInterface $container) * * Persists error/success messages between requests in the session. * - * @throws \Exception If alert storage handler is not supported + * @throws \Exception If alert storage handler is not supported * @return \UserFrosting\Sprinkle\Core\Alert\AlertStream */ $container['alerts'] = function ($c) { @@ -145,7 +146,7 @@ public function register(ContainerInterface $container) $assets = new Assets($locator, 'assets', $baseUrl); // Load compiled asset bundle. - $assets->addAssetBundles(new CompiledAssetBundles($locator("build://" . $config['assets.compiled.schema'], true, true))); + $assets->addAssetBundles(new CompiledAssetBundles($locator('build://' . $config['assets.compiled.schema'], true, true))); } return $assets; @@ -154,7 +155,7 @@ public function register(ContainerInterface $container) /** * Cache service. * - * @throws \Exception If cache handler is not supported + * @throws \Exception If cache handler is not supported * @return \Illuminate\Cache\Repository */ $container['cache'] = function ($c) { @@ -201,6 +202,7 @@ public function register(ContainerInterface $container) $classMapper->setClassMapping('query_builder', 'UserFrosting\Sprinkle\Core\Database\Builder'); $classMapper->setClassMapping('eloquent_builder', 'UserFrosting\Sprinkle\Core\Database\EloquentBuilder'); $classMapper->setClassMapping('throttle', 'UserFrosting\Sprinkle\Core\Database\Models\Throttle'); + return $classMapper; }; @@ -274,13 +276,13 @@ public function register(ContainerInterface $container) $container['db'] = function ($c) { $config = $c->config; - $capsule = new Capsule; + $capsule = new Capsule(); foreach ($config['db'] as $name => $dbConfig) { $capsule->addConnection($dbConfig, $name); } - $queryEventDispatcher = new Dispatcher(new Container); + $queryEventDispatcher = new Dispatcher(new Container()); $capsule->setEventDispatcher($queryEventDispatcher); @@ -446,7 +448,7 @@ public function register(ContainerInterface $container) if (array_key_exists(1, $parts)) { $parts[1] = str_replace('q=', '', $parts[1]); // Sanitize with int cast (bad values go to 0) - $parts[1] = (int)$parts[1]; + $parts[1] = (int) $parts[1]; } else { $parts[1] = 1; } @@ -535,8 +537,9 @@ public function register(ContainerInterface $container) */ $container['notFoundHandler'] = function ($c) { return function ($request, $response) use ($c) { - $exception = new NotFoundException; + $exception = new NotFoundException(); $handler = new NotFoundExceptionHandler($c, $request, $response, $exception, $c->settings['displayErrorDetails']); + return $handler->handle(); }; }; @@ -584,7 +587,7 @@ public function register(ContainerInterface $container) $routerCacheFile = $c->config['settings.routerCacheFile']; } - return (new Router)->setCacheFile($routerCacheFile); + return (new Router())->setCacheFile($routerCacheFile); }; /** @@ -598,14 +601,14 @@ public function register(ContainerInterface $container) // Create appropriate handler based on config if ($config['session.handler'] == 'file') { - $fs = new Filesystem; + $fs = new Filesystem(); $handler = new FileSessionHandler($fs, $c->locator->findResource('session://'), $config['session.minutes']); } elseif ($config['session.handler'] == 'database') { $connection = $c->db->connection(); // Table must exist, otherwise an exception will be thrown $handler = new DatabaseSessionHandler($connection, $config['session.database.table'], $config['session.minutes']); } elseif ($config['session.handler'] == 'array') { - $handler = new NullSessionHandler; + $handler = new NullSessionHandler(); } else { throw new \Exception("Bad session handler type '{$config['session.handler']}' specified in configuration file."); } diff --git a/app/sprinkles/core/src/Session/NullSessionHandler.php b/app/sprinkles/core/src/Session/NullSessionHandler.php index 7e4b8cf2e..fc2b5c428 100644 --- a/app/sprinkles/core/src/Session/NullSessionHandler.php +++ b/app/sprinkles/core/src/Session/NullSessionHandler.php @@ -1,11 +1,15 @@ [], + 'sorts' => [], 'filters' => [], - 'lists' => [], - 'size' => 'all', - 'page' => null, - 'format' => 'json' + 'lists' => [], + 'size' => 'all', + 'page' => null, + 'format' => 'json' ]; /** @@ -124,7 +125,7 @@ abstract class Sprunje * Constructor. * * @param ClassMapper $classMapper - * @param mixed[] $options + * @param mixed[] $options */ public function __construct(ClassMapper $classMapper, array $options) { @@ -162,19 +163,20 @@ public function __construct(ClassMapper $classMapper, array $options) /** * Extend the query by providing a callback. * - * @param callable $callback A callback which accepts and returns a Builder instance. + * @param callable $callback A callback which accepts and returns a Builder instance. * @return self */ public function extendQuery(callable $callback) { $this->query = $callback($this->query); + return $this; } /** * Execute the query and build the results, and append them in the appropriate format to the response. * - * @param Response $response + * @param Response $response * @return Response */ public function toResponse(Response $response) @@ -189,10 +191,12 @@ public function toResponse(Response $response) $date = Carbon::now()->format('Ymd'); $response = $response->withAddedHeader('Content-Disposition', "attachment;filename=$date-{$this->name}-$settings.csv"); $response = $response->withAddedHeader('Content-Type', 'text/csv; charset=utf-8'); + return $response->write($result); // Default to JSON } else { $result = $this->getArray(); + return $response->withJson($result, 200, JSON_PRETTY_PRINT); } } @@ -249,6 +253,7 @@ public function getCsv() $columnNames[] = $itemKey; } } + return $item; }); @@ -343,19 +348,20 @@ public function getQuery() /** * Set the underlying QueryBuilder object. * - * @param Builder $query + * @param Builder $query * @return self */ public function setQuery($query) { $this->query = $query; + return $this; } /** * Apply any filters from the options, calling a custom filter callback when appropriate. * - * @param Builder $query + * @param Builder $query * @return self */ public function applyFilters($query) @@ -379,7 +385,7 @@ public function applyFilters($query) /** * Apply any sorts from the options, calling a custom sorter callback when appropriate. * - * @param Builder $query + * @param Builder $query * @return self */ public function applySorts($query) @@ -408,7 +414,7 @@ public function applySorts($query) /** * Apply pagination based on the `page` and `size` options. * - * @param Builder $query + * @param Builder $query * @return self */ public function applyPagination($query) @@ -418,7 +424,7 @@ public function applyPagination($query) ($this->options['size'] !== null) && ($this->options['size'] != 'all') ) { - $offset = $this->options['size']*$this->options['page']; + $offset = $this->options['size'] * $this->options['page']; $query->skip($offset) ->take($this->options['size']); } @@ -429,8 +435,8 @@ public function applyPagination($query) /** * Match any filter in `filterable`. * - * @param Builder $query - * @param mixed $value + * @param Builder $query + * @param mixed $value * @return self */ protected function filterAll($query, $value) @@ -450,9 +456,9 @@ protected function filterAll($query, $value) /** * Build the filter query for a single field. * - * @param Builder $query - * @param string $name - * @param mixed $value + * @param Builder $query + * @param string $name + * @param mixed $value * @return self */ protected function buildFilterQuery($query, $name, $value) @@ -473,9 +479,9 @@ protected function buildFilterQuery($query, $name, $value) * Perform a 'like' query on a single field, separating the value string on the or separator and * matching any of the supplied values. * - * @param Builder $query - * @param string $name - * @param mixed $value + * @param Builder $query + * @param string $name + * @param mixed $value * @return self */ protected function buildFilterDefaultFieldQuery($query, $name, $value) @@ -493,7 +499,7 @@ protected function buildFilterDefaultFieldQuery($query, $name, $value) /** * Set any transformations you wish to apply to the collection, after the query is executed. * - * @param \Illuminate\Database\Eloquent\Collection $collection + * @param \Illuminate\Database\Eloquent\Collection $collection * @return \Illuminate\Database\Eloquent\Collection */ protected function applyTransformations($collection) @@ -512,7 +518,7 @@ abstract protected function baseQuery(); * Returns a list of distinct values for a specified column. * Formats results to have a "value" and "text" attribute. * - * @param string $column + * @param string $column * @return array */ protected function getColumnValues($column) @@ -522,16 +528,17 @@ protected function getColumnValues($column) foreach ($rawValues as $raw) { $values[] = [ 'value' => $raw[$column], - 'text' => $raw[$column] + 'text' => $raw[$column] ]; } + return $values; } /** * Get the unpaginated count of items (before filtering) in this query. * - * @param Builder $query + * @param Builder $query * @return int */ protected function count($query) @@ -542,7 +549,7 @@ protected function count($query) /** * Get the unpaginated count of items (after filtering) in this query. * - * @param Builder $query + * @param Builder $query * @return int */ protected function countFiltered($query) diff --git a/app/sprinkles/core/src/Throttle/ThrottleRule.php b/app/sprinkles/core/src/Throttle/ThrottleRule.php index 277eb3ee8..9829ebcee 100644 --- a/app/sprinkles/core/src/Throttle/ThrottleRule.php +++ b/app/sprinkles/core/src/Throttle/ThrottleRule.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Throttle; use Carbon\Carbon; @@ -25,17 +26,17 @@ class ThrottleRule /** * @var int[] A mapping of minimum observation counts (x) to delays (y), in seconds. - * Any throttleable event that has occurred more than x times in this rule's interval, - * must wait y seconds after the last occurrence before another attempt is permitted. + * Any throttleable event that has occurred more than x times in this rule's interval, + * must wait y seconds after the last occurrence before another attempt is permitted. */ protected $delays; /** * Create a new ThrottleRule object. * - * @param string $method Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling. - * @param int $interval The amount of time, in seconds, to look back in determining attempts to consider. - * @param int[] $delays A mapping of minimum observation counts (x) to delays (y), in seconds. + * @param string $method Set to 'ip' for ip-based throttling, 'data' for request-data-based throttling. + * @param int $interval The amount of time, in seconds, to look back in determining attempts to consider. + * @param int[] $delays A mapping of minimum observation counts (x) to delays (y), in seconds. */ public function __construct($method, $interval, $delays) { @@ -48,7 +49,7 @@ public function __construct($method, $interval, $delays) * Get the current delay on this rule for a particular number of event counts. * * @param Carbon $lastEventTime The timestamp for the last countable event. - * @param int $count The total number of events which have occurred in an interval. + * @param int $count The total number of events which have occurred in an interval. */ public function getDelay(Carbon $lastEventTime, $count) { diff --git a/app/sprinkles/core/src/Throttle/Throttler.php b/app/sprinkles/core/src/Throttle/Throttler.php index be45cf72e..19283ebf2 100644 --- a/app/sprinkles/core/src/Throttle/Throttler.php +++ b/app/sprinkles/core/src/Throttle/Throttler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Throttle; use Carbon\Carbon; @@ -42,7 +43,7 @@ public function __construct(ClassMapper $classMapper) /** * Add a throttling rule for a particular throttle event type. * - * @param string $type The type of throttle event to check against. + * @param string $type The type of throttle event to check against. * @param ThrottleRule|null $rule The rule to use when throttling this type of event. */ public function addThrottleRule($type, ThrottleRule $rule = null) @@ -59,8 +60,8 @@ public function addThrottleRule($type, ThrottleRule $rule = null) /** * Check the current request against a specified throttle rule. * - * @param string $type The type of throttle event to check against. - * @param mixed[] $requestData Any additional request parameters to use in checking the throttle. + * @param string $type The type of throttle event to check against. + * @param mixed[] $requestData Any additional request parameters to use in checking the throttle. * @return bool */ public function getDelay($type, $requestData = []) @@ -109,7 +110,7 @@ public function getDelay($type, $requestData = []) /** * Get a registered rule of a particular type. * - * @param string $type + * @param string $type * @throws ThrottlerException * @return ThrottleRule[] */ @@ -135,7 +136,7 @@ public function getThrottleRules() /** * Log a throttleable event to the database. * - * @param string $type the type of event + * @param string $type the type of event * @param string[] $requestData an array of field names => values that are relevant to throttling for this event (e.g. username, email, etc). */ public function logEvent($type, $requestData = []) @@ -148,8 +149,8 @@ public function logEvent($type, $requestData = []) } $event = $this->classMapper->createInstance('throttle', [ - 'type' => $type, - 'ip' => $_SERVER['REMOTE_ADDR'], + 'type' => $type, + 'ip' => $_SERVER['REMOTE_ADDR'], 'request_data' => json_encode($requestData) ]); @@ -161,9 +162,9 @@ public function logEvent($type, $requestData = []) /** * Returns the current delay for a specified throttle rule. * - * @param Collection $events a Collection of throttle events. + * @param Collection $events a Collection of throttle events. * @param ThrottleRule $throttleRule a rule representing the strategy to use for throttling a particular type of event. - * @return int seconds remaining until a particular event is permitted to be attempted again. + * @return int seconds remaining until a particular event is permitted to be attempted again. */ protected function computeDelay(Collection $events, ThrottleRule $throttleRule) { @@ -174,6 +175,7 @@ protected function computeDelay(Collection $events, ThrottleRule $throttleRule) // Great, now we compare our delay against the most recent attempt $lastEvent = $events->last(); + return $throttleRule->getDelay($lastEvent->created_at, $events->count()); } } diff --git a/app/sprinkles/core/src/Throttle/ThrottlerException.php b/app/sprinkles/core/src/Throttle/ThrottlerException.php index 9e1009640..0f231f372 100644 --- a/app/sprinkles/core/src/Throttle/ThrottlerException.php +++ b/app/sprinkles/core/src/Throttle/ThrottlerException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Throttle; /** diff --git a/app/sprinkles/core/src/Twig/CacheHelper.php b/app/sprinkles/core/src/Twig/CacheHelper.php index d44a4abab..dc654c517 100755 --- a/app/sprinkles/core/src/Twig/CacheHelper.php +++ b/app/sprinkles/core/src/Twig/CacheHelper.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Twig; use Interop\Container\ContainerInterface; @@ -17,7 +18,6 @@ */ class CacheHelper { - /** * @var ContainerInterface The global container object, which holds all your services. */ @@ -44,7 +44,7 @@ public function clearCache() $path = $this->ci->locator->findResource('cache://twig', true, true); // Get Filesystem instance - $fs = new Filesystem; + $fs = new Filesystem(); // Make sure directory exist and delete it if ($fs->exists($path)) { diff --git a/app/sprinkles/core/src/Twig/CoreExtension.php b/app/sprinkles/core/src/Twig/CoreExtension.php index 24f71dbb9..83ac3123f 100755 --- a/app/sprinkles/core/src/Twig/CoreExtension.php +++ b/app/sprinkles/core/src/Twig/CoreExtension.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Twig; use Interop\Container\ContainerInterface; @@ -18,7 +19,6 @@ */ class CoreExtension extends \Twig_Extension implements \Twig_Extension_GlobalsInterface { - /** * @var ContainerInterface The global container object, which holds all your services. */ @@ -51,7 +51,7 @@ public function getName() */ public function getFunctions() { - return array( + return [ // Add Twig function for fetching alerts new \Twig_SimpleFunction('getAlerts', function ($clear = true) { if ($clear) { @@ -60,12 +60,12 @@ public function getFunctions() return $this->services['alerts']->messages(); } }), - new \Twig_SimpleFunction('translate', function ($hook, $params = array()) { + new \Twig_SimpleFunction('translate', function ($hook, $params = []) { return $this->services['translator']->translate($hook, $params); }, [ 'is_safe' => ['html'] ]) - ); + ]; } /** @@ -75,8 +75,8 @@ public function getFunctions() */ public function getFilters() { - return array( - /** + return [ + /* * Converts phone numbers to a standard format. * * @param string $num A unformatted phone number @@ -88,7 +88,7 @@ public function getFilters() new \Twig_SimpleFilter('unescape', function ($string) { return html_entity_decode($string); }) - ); + ]; } /** diff --git a/app/sprinkles/core/src/Util/BadClassNameException.php b/app/sprinkles/core/src/Util/BadClassNameException.php index 09c4ea58e..1cd6f4e2a 100644 --- a/app/sprinkles/core/src/Util/BadClassNameException.php +++ b/app/sprinkles/core/src/Util/BadClassNameException.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Util; /** diff --git a/app/sprinkles/core/src/Util/Captcha.php b/app/sprinkles/core/src/Util/Captcha.php index 53544ffec..8472d7be3 100644 --- a/app/sprinkles/core/src/Util/Captcha.php +++ b/app/sprinkles/core/src/Util/Captcha.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Util; use UserFrosting\Session\Session; @@ -44,7 +45,7 @@ class Captcha * Create a new captcha. * * @param Session $session - * @param string $key + * @param string $key */ public function __construct(Session $session, $key) { @@ -52,7 +53,7 @@ public function __construct(Session $session, $key) $this->key = $key; if (!$this->session->has($key)) { - $this->session[$key] = array(); + $this->session[$key] = []; } } @@ -98,12 +99,12 @@ public function getImage() * Check that the specified code, when hashed, matches the code in the session. * Also, stores the specified code in the session with an md5 hash. * - * @param string $code + * @param string $code * @return bool */ public function verifyCode($code) { - return (md5($code) == $this->session[$this->key]); + return md5($code) == $this->session[$this->key]; } /** @@ -131,10 +132,10 @@ protected function generateImage() imagefilledrectangle($image, 0, 0, 150, 30, $white); //add some lines - for ($i=0;$i<2;$i++) { - imageline($image, 0, rand()%10, 10, rand()%30, $dark_grey); - imageline($image, 0, rand()%30, 150, rand()%30, $red); - imageline($image, 0, rand()%30, 150, rand()%30, $yellow); + for ($i = 0; $i < 2; $i++) { + imageline($image, 0, rand() % 10, 10, rand() % 30, $dark_grey); + imageline($image, 0, rand() % 30, 150, rand() % 30, $red); + imageline($image, 0, rand() % 30, 150, rand() % 30, $yellow); } // RandTab color pallette @@ -145,8 +146,8 @@ protected function generateImage() $randc[4] = imagecolorallocate($image, 0, 0, 255); //add some dots - for ($i=0;$i<1000;$i++) { - imagesetpixel($image, rand()%200, rand()%50, $randc[rand()%5]); + for ($i = 0; $i < 1000; $i++) { + imagesetpixel($image, rand() % 200, rand() % 50, $randc[rand() % 5]); } //calculate center of text diff --git a/app/sprinkles/core/src/Util/CheckEnvironment.php b/app/sprinkles/core/src/Util/CheckEnvironment.php index d4341568a..9087423b0 100644 --- a/app/sprinkles/core/src/Util/CheckEnvironment.php +++ b/app/sprinkles/core/src/Util/CheckEnvironment.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Util; use Psr\Http\Message\ResponseInterface as Response; @@ -48,9 +49,9 @@ class CheckEnvironment /** * Constructor. * - * @param Twig $view The view object, needed for rendering error page. + * @param Twig $view The view object, needed for rendering error page. * @param ResourceLocator $locator Locator service for stream resources. - * @param CacheManager $cache Cache manager + * @param CacheManager $cache Cache manager */ public function __construct(Twig $view, ResourceLocator $locator, $cache) { @@ -62,9 +63,9 @@ public function __construct(Twig $view, ResourceLocator $locator, $cache) /** * Invoke the CheckEnvironment middleware, performing all pre-flight checks and returning an error page if problems were found. * - * @param Request $request PSR7 request - * @param Response $response PSR7 response - * @param callable $next Next middleware + * @param Request $request PSR7 request + * @param Response $response PSR7 response + * @param callable $next Next middleware * @return \Psr\Http\Message\ResponseInterface */ public function __invoke(Request $request, Response $response, $next) @@ -87,7 +88,7 @@ public function __invoke(Request $request, Response $response, $next) $results = array_merge($this->resultsFailed, $this->resultsSuccess); $response = $this->view->render($response, 'pages/error/config-errors.html.twig', [ - "messages" => $results + 'messages' => $results ]); } else { $response = $next($request, $response); @@ -148,15 +149,15 @@ public function checkApache() if (!in_array($module, $apache_modules)) { $problemsFound = true; $this->resultsFailed['apache-' . $module] = [ - "title" => " Missing Apache module $module.", - "message" => "Please make sure that the $module Apache module is installed and enabled. If you use shared hosting, you will need to ask your web host to do this for you.", - "success" => false + 'title' => " Missing Apache module $module.", + 'message' => "Please make sure that the $module Apache module is installed and enabled. If you use shared hosting, you will need to ask your web host to do this for you.", + 'success' => false ]; } else { $this->resultsSuccess['apache-' . $module] = [ - "title" => " Apache module $module is installed and enabled.", - "message" => "Great, we found the $module Apache module!", - "success" => true + 'title' => " Apache module $module is installed and enabled.", + 'message' => "Great, we found the $module Apache module!", + 'success' => true ]; } } @@ -175,15 +176,15 @@ public function checkGd() if (!(extension_loaded('gd') && function_exists('gd_info'))) { $problemsFound = true; $this->resultsFailed['gd'] = [ - "title" => " GD library not installed", - "message" => "We could not confirm that the GD library is installed and enabled. GD is an image processing library that UserFrosting uses to generate captcha codes for user account registration.", - "success" => false + 'title' => " GD library not installed", + 'message' => 'We could not confirm that the GD library is installed and enabled. GD is an image processing library that UserFrosting uses to generate captcha codes for user account registration.', + 'success' => false ]; } else { $this->resultsSuccess['gd'] = [ - "title" => " GD library installed!", - "message" => "Great, you have GD installed and enabled.", - "success" => true + 'title' => " GD library installed!", + 'message' => 'Great, you have GD installed and enabled.', + 'success' => true ]; } @@ -214,15 +215,15 @@ public function checkImageFunctions() if (!function_exists($func)) { $problemsFound = true; $this->resultsFailed['function-' . $func] = [ - "title" => " Missing image manipulation function.", - "message" => "It appears that function $func is not available. UserFrosting needs this to render captchas.", - "success" => false + 'title' => " Missing image manipulation function.", + 'message' => "It appears that function $func is not available. UserFrosting needs this to render captchas.", + 'success' => false ]; } else { $this->resultsSuccess['function-' . $func] = [ - "title" => " Function $func is available!", - "message" => "Sweet!", - "success" => true + 'title' => " Function $func is available!", + 'message' => 'Sweet!', + 'success' => true ]; } } @@ -240,15 +241,15 @@ public function checkPdo() if (!class_exists('PDO')) { $problemsFound = true; $this->resultsFailed['pdo'] = [ - "title" => " PDO is not installed.", - "message" => "I'm sorry, you must have PDO installed and enabled in order for UserFrosting to access the database. If you don't know what PDO is, please see http://php.net/manual/en/book.pdo.php.", - "success" => false + 'title' => " PDO is not installed.", + 'message' => "I'm sorry, you must have PDO installed and enabled in order for UserFrosting to access the database. If you don't know what PDO is, please see http://php.net/manual/en/book.pdo.php.", + 'success' => false ]; } else { $this->resultsSuccess['pdo'] = [ - "title" => " PDO is installed!", - "message" => "You've got PDO installed. Good job!", - "success" => true + 'title' => " PDO is installed!", + 'message' => "You've got PDO installed. Good job!", + 'success' => true ]; } @@ -263,8 +264,8 @@ public function checkPermissions() $problemsFound = false; $shouldBeWriteable = [ - $this->locator->findResource('log://') => true, - $this->locator->findResource('cache://') => true, + $this->locator->findResource('log://') => true, + $this->locator->findResource('cache://') => true, $this->locator->findResource('session://') => true ]; @@ -272,7 +273,7 @@ public function checkPermissions() // Should be write-protected in production! $shouldBeWriteable = array_merge($shouldBeWriteable, [ \UserFrosting\SPRINKLES_DIR => false, - \UserFrosting\VENDOR_DIR => false + \UserFrosting\VENDOR_DIR => false ]); } @@ -282,36 +283,37 @@ public function checkPermissions() if (!file_exists($file)) { $problemsFound = true; $this->resultsFailed['file-' . $file] = [ - "title" => " File or directory does not exist.", - "message" => "We could not find the file or directory $file.", - "success" => false + 'title' => " File or directory does not exist.", + 'message' => "We could not find the file or directory $file.", + 'success' => false ]; } else { $writeable = is_writable($file); if ($assertWriteable !== $writeable) { $problemsFound = true; $this->resultsFailed['file-' . $file] = [ - "title" => " Incorrect permissions for file or directory.", - "message" => "$file is " - . ($writeable ? "writeable" : "not writeable") - . ", but it should " - . ($assertWriteable ? "be writeable" : "not be writeable") - . ". Please modify the OS user or group permissions so that user " - . exec('whoami') . " " - . ($assertWriteable ? "has" : "does not have") . " write permissions for this directory.", - "success" => false + 'title' => " Incorrect permissions for file or directory.", + 'message' => "$file is " + . ($writeable ? 'writeable' : 'not writeable') + . ', but it should ' + . ($assertWriteable ? 'be writeable' : 'not be writeable') + . '. Please modify the OS user or group permissions so that user ' + . exec('whoami') . ' ' + . ($assertWriteable ? 'has' : 'does not have') . ' write permissions for this directory.', + 'success' => false ]; } else { $this->resultsSuccess['file-' . $file] = [ - "title" => " File/directory check passed!", - "message" => "$file exists and is correctly set as " - . ($writeable ? "writeable" : "not writeable") - . ".", - "success" => true + 'title' => " File/directory check passed!", + 'message' => "$file exists and is correctly set as " + . ($writeable ? 'writeable' : 'not writeable') + . '.', + 'success' => true ]; } } } + return $problemsFound; } @@ -326,15 +328,15 @@ public function checkPhp() if (version_compare(phpversion(), \UserFrosting\PHP_MIN_VERSION, '<')) { $problemsFound = true; $this->resultsFailed['phpVersion'] = [ - "title" => " You need to upgrade your PHP installation.", - "message" => "I'm sorry, UserFrosting requires version " . \UserFrosting\PHP_MIN_VERSION . " or greater. Please upgrade your version of PHP, or contact your web hosting service and ask them to upgrade it for you.", - "success" => false + 'title' => " You need to upgrade your PHP installation.", + 'message' => "I'm sorry, UserFrosting requires version " . \UserFrosting\PHP_MIN_VERSION . ' or greater. Please upgrade your version of PHP, or contact your web hosting service and ask them to upgrade it for you.', + 'success' => false ]; } else { $this->resultsSuccess['phpVersion'] = [ - "title" => " PHP version checks out!", - "message" => "You're using PHP " . \UserFrosting\PHP_MIN_VERSION . "or higher. Great!", - "success" => true + 'title' => " PHP version checks out!", + 'message' => "You're using PHP " . \UserFrosting\PHP_MIN_VERSION . 'or higher. Great!', + 'success' => true ]; } @@ -348,6 +350,6 @@ public function checkPhp() */ public function isProduction() { - return (getenv('UF_MODE') == 'production'); + return getenv('UF_MODE') == 'production'; } } diff --git a/app/sprinkles/core/src/Util/ClassMapper.php b/app/sprinkles/core/src/Util/ClassMapper.php index bf29d8d93..448c1f496 100644 --- a/app/sprinkles/core/src/Util/ClassMapper.php +++ b/app/sprinkles/core/src/Util/ClassMapper.php @@ -28,7 +28,7 @@ class ClassMapper * Creates an instance for a requested class identifier. * * @param string $identifier The identifier for the class, e.g. 'user' - * @param mixed ...$arg Whatever needs to be passed to the constructor. + * @param mixed ...$arg Whatever needs to be passed to the constructor. */ public function createInstance($identifier) { @@ -45,7 +45,7 @@ public function createInstance($identifier) /** * Gets the fully qualified class name for a specified class identifier. * - * @param string $identifier + * @param string $identifier * @return string */ public function getClassMapping($identifier) @@ -60,8 +60,8 @@ public function getClassMapping($identifier) /** * Assigns a fully qualified class name to a specified class identifier. * - * @param string $identifier - * @param string $className + * @param string $identifier + * @param string $className * @return ClassMapper */ public function setClassMapping($identifier, $className) @@ -81,7 +81,7 @@ public function setClassMapping($identifier, $className) * * @param string $identifier The identifier for the class, e.g. 'user' * @param string $methodName The method to be invoked. - * @param mixed ...$arg Whatever needs to be passed to the method. + * @param mixed ...$arg Whatever needs to be passed to the method. */ public function staticMethod($identifier, $methodName) { diff --git a/app/sprinkles/core/src/Util/EnvironmentInfo.php b/app/sprinkles/core/src/Util/EnvironmentInfo.php index 8cf0f1cc6..459c34757 100644 --- a/app/sprinkles/core/src/Util/EnvironmentInfo.php +++ b/app/sprinkles/core/src/Util/EnvironmentInfo.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Util; use Illuminate\Database\Capsule\Manager as Capsule; @@ -38,13 +39,13 @@ public static function database() try { $results['type'] = $pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); } catch (\Exception $e) { - $results['type'] = "Unknown"; + $results['type'] = 'Unknown'; } try { $results['version'] = $pdo->getAttribute(\PDO::ATTR_SERVER_VERSION); } catch (\Exception $e) { - $results['version'] = ""; + $results['version'] = ''; } return $results; diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index 20ddf8f3d..f8f33915c 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -3,9 +3,9 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @copyright Copyright (c) 2013-2017 Alexander Weissman * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Util; use UserFrosting\Assets\AssetBundles\GulpBundleAssetsRawBundles; @@ -18,46 +18,45 @@ * * @author Alex Weissman (https://alexanderweissman.com) */ - class RawAssetBundles extends GulpBundleAssetsRawBundles - { - +class RawAssetBundles extends GulpBundleAssetsRawBundles +{ /** * Extends the currently loaded bundles with another bundle schema. * * @param string $filePath * * @throws \UserFrosting\Support\Exception\FileNotFoundException if file cannot be found. - * @throws \UserFrosting\Support\Exception\JsonException if file cannot be parsed as JSON. - * @throws InvalidBundlesFileException if unexpected value encountered. + * @throws \UserFrosting\Support\Exception\JsonException if file cannot be parsed as JSON. + * @throws InvalidBundlesFileException if unexpected value encountered. */ - public function extend($filePath) - { - if (!is_string($filePath)) { - throw new \InvalidArgumentException("\$filePath must of type string but was " . gettype($filePath)); - } + public function extend($filePath) + { + if (!is_string($filePath)) { + throw new \InvalidArgumentException('$filePath must of type string but was ' . gettype($filePath)); + } - // Read file - $bundlesFile = $this->readSchema($filePath); + // Read file + $bundlesFile = $this->readSchema($filePath); - // Process bundles - if (isset($bundlesFile->bundle)) { - foreach ($bundlesFile->bundle as $bundleName => $bundle) { - // Get collision setting. - $collisionRule = isset($bundle->options->sprinkle->onCollision) ? $bundle->options->sprinkle->onCollision : 'replace'; + // Process bundles + if (isset($bundlesFile->bundle)) { + foreach ($bundlesFile->bundle as $bundleName => $bundle) { + // Get collision setting. + $collisionRule = isset($bundle->options->sprinkle->onCollision) ? $bundle->options->sprinkle->onCollision : 'replace'; - // Handle CSS bundle if specified. - if (isset($bundle->styles)) { - // Attempt to add CSS bundle - try { - $standardisedBundle = $this->standardiseBundle($bundle->styles); - if (!array_key_exists($bundleName, $this->cssBundles)) { - $this->cssBundles[$bundleName] = $standardisedBundle; - } else { - switch ($collisionRule) { + // Handle CSS bundle if specified. + if (isset($bundle->styles)) { + // Attempt to add CSS bundle + try { + $standardisedBundle = $this->standardiseBundle($bundle->styles); + if (!array_key_exists($bundleName, $this->cssBundles)) { + $this->cssBundles[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { case 'replace': // Replaces the existing bundle. $this->cssBundles[$bundleName] = $standardisedBundle; - break; + break; case 'merge': // Merge with existing bundle. foreach ($standardisedBundle as $assetPath) { @@ -65,35 +64,35 @@ public function extend($filePath) $this->cssBundles[$bundleName][] = $assetPath; } } - break; + break; case 'ignore': - break; + break; case 'error': throw new \ErrorException("The bundle '$bundleName' is already defined."); - break; + break; default: throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); - break; + break; } - } - } catch (\Exception $e) { - throw new InvalidBundlesFileException("Encountered issue processing styles property for '$bundleName' for file '$filePath'", 0, $e); - } - } + } + } catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing styles property for '$bundleName' for file '$filePath'", 0, $e); + } + } - // Handle JS bundle if specified. - if (isset($bundle->scripts)) { - // Attempt to add JS bundle - try { - $standardisedBundle = $this->standardiseBundle($bundle->scripts); - if (!array_key_exists($bundleName, $this->jsBundles)) { - $this->jsBundles[$bundleName] = $standardisedBundle; - } else { - switch ($collisionRule) { + // Handle JS bundle if specified. + if (isset($bundle->scripts)) { + // Attempt to add JS bundle + try { + $standardisedBundle = $this->standardiseBundle($bundle->scripts); + if (!array_key_exists($bundleName, $this->jsBundles)) { + $this->jsBundles[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { case 'replace': // Replaces the existing bundle. $this->jsBundles[$bundleName] = $standardisedBundle; - break; + break; case 'merge': // Merge with existing bundle. foreach ($standardisedBundle as $assetPath) { @@ -101,22 +100,22 @@ public function extend($filePath) $this->jsBundles[$bundleName][] = $assetPath; } } - break; + break; case 'ignore': - break; + break; case 'error': throw new \ErrorException("The bundle '$bundleName' is already defined."); - break; + break; default: throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); - break; + break; } - } - } catch (\Exception $e) { - throw new InvalidBundlesFileException("Encountered issue processing scripts property for '$bundleName' for file '$filePath'", 0, $e); - } - } - } - } - } - } + } + } catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing scripts property for '$bundleName' for file '$filePath'", 0, $e); + } + } + } + } + } +} diff --git a/app/sprinkles/core/src/Util/ShutdownHandler.php b/app/sprinkles/core/src/Util/ShutdownHandler.php index bb5f50058..e17928b76 100755 --- a/app/sprinkles/core/src/Util/ShutdownHandler.php +++ b/app/sprinkles/core/src/Util/ShutdownHandler.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Util; use Interop\Container\ContainerInterface; @@ -33,8 +34,8 @@ class ShutdownHandler /** * Constructor. * - * @param ContainerInterface $ci The global container object, which holds all your services. - * @param bool $displayErrorInfo + * @param ContainerInterface $ci The global container object, which holds all your services. + * @param bool $displayErrorInfo */ public function __construct(ContainerInterface $ci, $displayErrorInfo) { @@ -97,30 +98,30 @@ public function fatalHandler() /** * Build the error message string. * - * @param array $error + * @param array $error * @return string */ protected function buildErrorInfoMessage(array $error) { $errfile = $error['file']; $errline = (string) $error['line']; - $errstr = $error['message']; + $errstr = $error['message']; $errorTypes = [ - E_ERROR => 'Fatal error', - E_PARSE => 'Parse error', - E_CORE_ERROR => 'PHP core error', - E_COMPILE_ERROR => 'Zend compile error', + E_ERROR => 'Fatal error', + E_PARSE => 'Parse error', + E_CORE_ERROR => 'PHP core error', + E_COMPILE_ERROR => 'Zend compile error', E_RECOVERABLE_ERROR => 'Catchable fatal error' ]; - return "" . $errorTypes[$error['type']] . ": $errstr in $errfile on line $errline"; + return '' . $errorTypes[$error['type']] . ": $errstr in $errfile on line $errline"; } /** * Build an error response of the appropriate type as determined by the request's Accept header. * - * @param string $message + * @param string $message * @return string */ protected function buildErrorPage($message) @@ -130,6 +131,7 @@ protected function buildErrorPage($message) switch ($contentType) { case 'application/json': $error = ['message' => $message]; + return json_encode($error, JSON_PRETTY_PRINT); case 'text/html': @@ -144,7 +146,7 @@ protected function buildErrorPage($message) /** * Build an HTML error page from an error string. * - * @param string $message + * @param string $message * @return string */ protected function buildHtmlErrorPage($message) @@ -154,9 +156,9 @@ protected function buildHtmlErrorPage($message) return sprintf( "" . - "%s

%s

%s", + '%s

%s

%s', $title, $title, $html diff --git a/app/sprinkles/core/src/Util/Util.php b/app/sprinkles/core/src/Util/Util.php index 6af17c0f1..d601c0dbb 100644 --- a/app/sprinkles/core/src/Util/Util.php +++ b/app/sprinkles/core/src/Util/Util.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Util; /** @@ -19,9 +20,9 @@ class Util /** * Extracts specific fields from one associative array, and places them into another. * - * @param mixed[] $inputArray - * @param string[] $fieldArray - * @param bool $remove + * @param mixed[] $inputArray + * @param string[] $fieldArray + * @param bool $remove * @return mixed[] */ public static function extractFields(&$inputArray, $fieldArray, $remove = true) @@ -45,7 +46,7 @@ public static function extractFields(&$inputArray, $fieldArray, $remove = true) /** * Extracts numeric portion of a string (for example, for normalizing phone numbers). * - * @param string $str + * @param string $str * @return string */ public static function extractDigits($str) @@ -56,7 +57,7 @@ public static function extractDigits($str) /** * Formats a phone number as a standard 7- or 10-digit string (xxx) xxx-xxxx * - * @param string $phone + * @param string $phone * @return string */ public static function formatPhoneNumber($phone) @@ -78,7 +79,7 @@ public static function formatPhoneNumber($phone) * Nicely format an array for printing. * See https://stackoverflow.com/a/9776726/2970321 * - * @param array $arr + * @param array $arr * @return string */ public static function prettyPrintArray(array $arr) @@ -146,16 +147,16 @@ public static function prettyPrintArray(array $arr) /** * Generate a random phrase, consisting of a specified number of adjectives, followed by a noun. * - * @param int $numAdjectives - * @param int $maxLength - * @param int $maxTries - * @param string $separator + * @param int $numAdjectives + * @param int $maxLength + * @param int $maxTries + * @param string $separator * @return string */ public static function randomPhrase($numAdjectives, $maxLength = 9999999, $maxTries = 10, $separator = '-') { - $adjectives = include('extra://adjectives.php'); - $nouns = include('extra://nouns.php'); + $adjectives = include 'extra://adjectives.php'; + $nouns = include 'extra://nouns.php'; for ($n = 0; $n < $maxTries; $n++) { $keys = array_rand($adjectives, $numAdjectives); diff --git a/app/sprinkles/core/tests/ControllerTestCase.php b/app/sprinkles/core/tests/ControllerTestCase.php index 5357c6450..aa8957598 100644 --- a/app/sprinkles/core/tests/ControllerTestCase.php +++ b/app/sprinkles/core/tests/ControllerTestCase.php @@ -5,13 +5,12 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Tests; use Slim\Http\Environment; use Slim\Http\Request; use Slim\Http\Response; -use UserFrosting\Sprinkle\Core\Tests\TestDatabase; -use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; use UserFrosting\Tests\TestCase; /** @@ -36,12 +35,13 @@ public function setUp() } /** - * @param array $args Request arguments + * @param array $args Request arguments * @return Request */ protected function getRequest($args = []) { $env = Environment::mock($args); + return Request::createFromEnvironment($env); } diff --git a/app/sprinkles/core/tests/DatabaseTransactions.php b/app/sprinkles/core/tests/DatabaseTransactions.php index 65f8ba8fc..5fcfb8b93 100644 --- a/app/sprinkles/core/tests/DatabaseTransactions.php +++ b/app/sprinkles/core/tests/DatabaseTransactions.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Tests; /** diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php index 395fcffbf..d6842415e 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use Mockery as m; @@ -13,7 +14,7 @@ use UserFrosting\Sprinkle\Core\Bakery\MigrateCommand; use UserFrosting\Tests\TestCase; -class DatabaseMigrationMigrateCommandTest extends TestCase +class BakeryMigrateCommandTest extends TestCase { public function tearDown() { diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php index f69597606..792b84c56 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use Mockery as m; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php index 53afca13e..78d71e98e 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use Mockery as m; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php index d5e02f6dc..2e034d736 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use Mockery as m; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php index 5affcbc7a..ddde7be0e 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use Mockery as m; @@ -96,8 +97,8 @@ protected function runCommand($migrator, $input = []) protected function getInstalledMigrationStub() { return collect([ - (object)['migration' => 'foo', 'batch' => 1, 'sprinkle' => 'foo'], - (object)['migration' => 'bar', 'batch' => 2, 'sprinkle' => 'bar'] + (object) ['migration' => 'foo', 'batch' => 1, 'sprinkle' => 'foo'], + (object) ['migration' => 'bar', 'batch' => 2, 'sprinkle' => 'bar'] ]); } } diff --git a/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php b/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php index 8cbd58458..8eee73458 100644 --- a/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php +++ b/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php @@ -1,4 +1,10 @@ ci); $this->assertInstanceOf(CoreController::class, $controller); + return $controller; } @@ -28,7 +34,7 @@ public function testPageIndex(CoreController $controller) { $result = $controller->pageIndex($this->getRequest(), $this->getResponse(), []); $this->assertSame($result->getStatusCode(), 200); - $this->assertTrue(!!preg_match('/<\/html>/', (string) $result->getBody())); + $this->assertTrue((bool) preg_match('/<\/html>/', (string) $result->getBody())); } /** @@ -59,7 +65,7 @@ public function testGetAsset_ExceptionNoUrl(CoreController $controller) */ public function testGetAsset_ExceptionBadUrl(CoreController $controller) { - $url = "/" . rand(0, 99999); + $url = '/' . rand(0, 99999); $controller->getAsset($this->getRequest(), $this->getResponse(), ['url' => $url]); } diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php index 2f5bba1ec..6a439a7c7 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php @@ -5,9 +5,9 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; -use Illuminate\Filesystem\Filesystem; use UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocator; use UserFrosting\Sprinkle\Core\Database\Migrator\Migrator; diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php index f457a37f4..3ee710b29 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use UserFrosting\Sprinkle\Core\Tests\TestDatabase; @@ -20,7 +21,7 @@ class DatabaseMigratorServiceTest extends TestCase use TestDatabase; /** - * @inheritDoc + * {@inheritdoc} */ public function setUp() { diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php index 4a50083ef..ce2f14533 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use Mockery as m; @@ -44,7 +45,7 @@ public function tearDown() protected $migrator; /** - * @var MigrationLocator The migration locator instance. + * @var MigrationLocator The migration locator instance. */ protected $locator; diff --git a/app/sprinkles/core/tests/Integration/DatabaseTests.php b/app/sprinkles/core/tests/Integration/DatabaseTests.php index 5c137aeab..6f4752cc8 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseTests.php +++ b/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -1,4 +1,10 @@ 'david@owlfancy.com' ]); $user->emails()->create([ - 'id' => 2, + 'id' => 2, 'label' => 'work', 'email' => 'david@attenboroughsreef.com' ]); @@ -167,7 +173,7 @@ public function testSyncOneToMany() // Delete `work`, update `primary`, and add `gmail` $user->emails()->sync([ [ - 'id' => 1, + 'id' => 1, 'email' => 'david@aol.com' ], [ @@ -180,16 +186,16 @@ public function testSyncOneToMany() $this->assertEquals([ [ - 'id' => 1, + 'id' => 1, 'user_id'=> 1, - 'label' => 'primary', - 'email' => 'david@aol.com' + 'label' => 'primary', + 'email' => 'david@aol.com' ], [ - 'id' => 3, + 'id' => 3, 'user_id' => 1, - 'label' => 'gmail', - 'email' => 'davidattenborough@gmail.com' + 'label' => 'gmail', + 'email' => 'davidattenborough@gmail.com' ] ], $emails); } @@ -202,24 +208,24 @@ public function testSyncMorphMany() $user = EloquentTestUser::create(['name' => 'David']); // Set up original phones $user->phones()->create([ - 'id' => 1, - 'label' => 'primary', + 'id' => 1, + 'label' => 'primary', 'number' => '5555551212' ]); $user->phones()->create([ - 'id' => 2, - 'label' => 'work', + 'id' => 2, + 'label' => 'work', 'number' => '2223334444' ]); // Delete `work`, update `primary`, and add `fax` $user->phones()->sync([ [ - 'id' => 1, + 'id' => 1, 'number' => '8883332222' ], [ - 'label' => 'fax', + 'label' => 'fax', 'number' => '5550005555' ] ]); @@ -228,18 +234,18 @@ public function testSyncMorphMany() $this->assertEquals([ [ - 'id' => 1, - 'phoneable_id'=> 1, + 'id' => 1, + 'phoneable_id' => 1, 'phoneable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser', - 'label' => 'primary', - 'number' => '8883332222' + 'label' => 'primary', + 'number' => '8883332222' ], [ - 'id' => 3, - 'phoneable_id'=> 1, + 'id' => 3, + 'phoneable_id' => 1, 'phoneable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser', - 'label' => 'fax', - 'number' => '5550005555' + 'label' => 'fax', + 'number' => '5550005555' ] ], $phones); } @@ -257,16 +263,16 @@ public function testBelongsToManyUnique() $expectedRoles = [ [ - 'id' => 2, - 'slug' => 'soldier', + 'id' => 2, + 'slug' => 'soldier', 'pivot' => [ 'user_id' => 1, 'role_id' => 2 ] ], [ - 'id' => 3, - 'slug' => 'egg-layer', + 'id' => 3, + 'slug' => 'egg-layer', 'pivot' => [ 'user_id' => 1, 'role_id' => 3 @@ -296,19 +302,19 @@ public function testMorphsToManyUnique() $expectedTasks = [ [ - 'id' => 2, - 'name' => 'Chopping', + 'id' => 2, + 'name' => 'Chopping', 'pivot' => [ 'assignable_id' => 1, - 'task_id' => 2 + 'task_id' => 2 ] ], [ - 'id' => 3, - 'name' => 'Baleing', + 'id' => 3, + 'name' => 'Baleing', 'pivot' => [ 'assignable_id' => 1, - 'task_id' => 3 + 'task_id' => 3 ] ] ]; @@ -335,45 +341,45 @@ public function testMorphsToManyUniqueWithTertiary() $expectedTasks = [ [ - 'id' => 2, - 'name' => 'Chopping', + 'id' => 2, + 'name' => 'Chopping', 'pivot' => [ 'assignable_id' => 1, - 'task_id' => 2 + 'task_id' => 2 ], 'locations' => [ [ - 'id' => 1, - 'name' => 'Hatchery', + 'id' => 1, + 'name' => 'Hatchery', 'pivot' => [ 'location_id' => 1, - 'task_id' => 2 + 'task_id' => 2 ], ], [ - 'id' => 2, - 'name' => 'Nexus', + 'id' => 2, + 'name' => 'Nexus', 'pivot' => [ 'location_id' => 2, - 'task_id' => 2 + 'task_id' => 2 ], ] ] ], [ - 'id' => 3, - 'name' => 'Baleing', + 'id' => 3, + 'name' => 'Baleing', 'pivot' => [ 'assignable_id' => 1, - 'task_id' => 3 + 'task_id' => 3 ], 'locations' => [ [ - 'id' => 2, - 'name' => 'Nexus', + 'id' => 2, + 'name' => 'Nexus', 'pivot' => [ 'location_id' => 2, - 'task_id' => 3 + 'task_id' => 3 ], ] ] @@ -401,48 +407,48 @@ public function testBelongsToManyUniqueWithTertiary() $expectedJobs = [ [ - 'id' => 2, - 'slug' => 'soldier', + 'id' => 2, + 'slug' => 'soldier', 'pivot' => [ 'user_id' => 1, 'role_id' => 2 ], 'locations' => [ [ - 'id' => 1, - 'name' => 'Hatchery', + 'id' => 1, + 'name' => 'Hatchery', 'pivot' => [ - 'title' => 'Grunt', + 'title' => 'Grunt', 'location_id' => 1, - 'role_id' => 2 + 'role_id' => 2 ] ], [ - 'id' => 2, - 'name' => 'Nexus', + 'id' => 2, + 'name' => 'Nexus', 'pivot' => [ - 'title' => 'Sergeant', + 'title' => 'Sergeant', 'location_id' => 2, - 'role_id' => 2 + 'role_id' => 2 ] ] ] ], [ - 'id' => 3, - 'slug' => 'egg-layer', + 'id' => 3, + 'slug' => 'egg-layer', 'pivot' => [ 'user_id' => 1, 'role_id' => 3 ], 'locations' => [ [ - 'id' => 2, - 'name' => 'Nexus', + 'id' => 2, + 'name' => 'Nexus', 'pivot' => [ - 'title' => 'Queen', + 'title' => 'Queen', 'location_id' => 2, - 'role_id' => 3 + 'role_id' => 3 ] ] ] @@ -476,49 +482,49 @@ public function testBelongsToManyUniqueWithTertiaryEagerLoad() $this->assertEquals([ [ - 'id' => 1, + 'id' => 1, 'name' => 'David', 'jobs' => [ [ - 'id' => 2, - 'slug' => 'soldier', + 'id' => 2, + 'slug' => 'soldier', 'pivot' => [ 'user_id' => 1, 'role_id' => 2 ], 'locations' => [ [ - 'id' => 1, - 'name' => 'Hatchery', + 'id' => 1, + 'name' => 'Hatchery', 'pivot' => [ 'location_id' => 1, - 'role_id' => 2 + 'role_id' => 2 ] ], [ - 'id' => 2, - 'name' => 'Nexus', + 'id' => 2, + 'name' => 'Nexus', 'pivot' => [ 'location_id' => 2, - 'role_id' => 2 + 'role_id' => 2 ] ] ] ], [ - 'id' => 3, - 'slug' => 'egg-layer', + 'id' => 3, + 'slug' => 'egg-layer', 'pivot' => [ 'user_id' => 1, 'role_id' => 3 ], 'locations' => [ [ - 'id' => 2, - 'name' => 'Nexus', + 'id' => 2, + 'name' => 'Nexus', 'pivot' => [ 'location_id' => 2, - 'role_id' => 3 + 'role_id' => 3 ] ] ] @@ -526,23 +532,23 @@ public function testBelongsToManyUniqueWithTertiaryEagerLoad() ] ], [ - 'id' => 2, + 'id' => 2, 'name' => 'Alex', 'jobs' => [ [ - 'id' => 3, - 'slug' => 'egg-layer', + 'id' => 3, + 'slug' => 'egg-layer', 'pivot' => [ 'user_id' => 2, 'role_id' => 3 ], 'locations' => [ [ - 'id' => 1, - 'name' => 'Hatchery', + 'id' => 1, + 'name' => 'Hatchery', 'pivot' => [ 'location_id' => 1, - 'role_id' => 3 + 'role_id' => 3 ] ], ] @@ -561,31 +567,31 @@ public function testBelongsToManyThrough() $user = EloquentTestUser::create(['name' => 'David']); - $user->roles()->attach([1,2]); + $user->roles()->attach([1, 2]); // Test retrieval of via models as well $this->assertEquals([ [ - 'id' => 1, - 'slug' => 'uri_harvest', + 'id' => 1, + 'slug' => 'uri_harvest', 'pivot' => [ - 'user_id' => 1, + 'user_id' => 1, 'permission_id' => 1 ] ], [ - 'id' => 2, - 'slug' => 'uri_spit_acid', + 'id' => 2, + 'slug' => 'uri_spit_acid', 'pivot' => [ - 'user_id' => 1, + 'user_id' => 1, 'permission_id' => 2 ] ], [ - 'id' => 3, - 'slug' => 'uri_slash', + 'id' => 3, + 'slug' => 'uri_slash', 'pivot' => [ - 'user_id' => 1, + 'user_id' => 1, 'permission_id' => 3 ] ] @@ -595,7 +601,7 @@ public function testBelongsToManyThrough() $this->assertEquals(3, $user->permissions()->count()); $user2 = EloquentTestUser::create(['name' => 'Alex']); - $user2->roles()->attach([2,3]); + $user2->roles()->attach([2, 3]); // Test eager load $users = EloquentTestUser::with('permissions')->get(); @@ -603,26 +609,26 @@ public function testBelongsToManyThrough() $this->assertEquals([ [ - 'id' => 2, - 'slug' => 'uri_spit_acid', + 'id' => 2, + 'slug' => 'uri_spit_acid', 'pivot' => [ - 'user_id' => 2, + 'user_id' => 2, 'permission_id' => 2 ] ], [ - 'id' => 3, - 'slug' => 'uri_slash', + 'id' => 3, + 'slug' => 'uri_slash', 'pivot' => [ - 'user_id' => 2, + 'user_id' => 2, 'permission_id' => 3 ] ], [ - 'id' => 4, - 'slug' => 'uri_royal_jelly', + 'id' => 4, + 'slug' => 'uri_royal_jelly', 'pivot' => [ - 'user_id' => 2, + 'user_id' => 2, 'permission_id' => 4 ] ] @@ -647,24 +653,24 @@ public function testBelongsToManyThroughPaginated() $user = EloquentTestUser::create(['name' => 'David']); - $user->roles()->attach([1,2]); + $user->roles()->attach([1, 2]); $paginatedPermissions = $user->permissions()->take(2)->offset(1); $this->assertEquals([ [ - 'id' => 2, - 'slug' => 'uri_spit_acid', + 'id' => 2, + 'slug' => 'uri_spit_acid', 'pivot' => [ - 'user_id' => 1, + 'user_id' => 1, 'permission_id' => 2 ] ], [ - 'id' => 3, - 'slug' => 'uri_slash', + 'id' => 3, + 'slug' => 'uri_slash', 'pivot' => [ - 'user_id' => 1, + 'user_id' => 1, 'permission_id' => 3 ] ] @@ -682,7 +688,7 @@ public function testBelongsToManyThroughPaginatedWithOrderByAggregateColumn() $this->generateRolesWithPermissions(); $user = EloquentTestUser::create(['name' => 'David']); - $user->roles()->attach([1,2]); + $user->roles()->attach([1, 2]); // If the paginated query is being ordered correctly by including the `roles_count` computed column, // Then `uri_spit_acid` should appear first. If not, then the results will not be ordered and the `uri_harvest` @@ -691,11 +697,11 @@ public function testBelongsToManyThroughPaginatedWithOrderByAggregateColumn() $this->assertEquals([ [ - 'id' => 2, - 'slug' => 'uri_spit_acid', + 'id' => 2, + 'slug' => 'uri_spit_acid', 'roles_count' => 3, - 'pivot' => [ - 'user_id' => 1, + 'pivot' => [ + 'user_id' => 1, 'permission_id' => 2 ] ] @@ -712,13 +718,13 @@ public function testBelongsToManyThroughWithVia() $user = EloquentTestUser::create(['name' => 'David']); - $user->roles()->attach([1,2]); + $user->roles()->attach([1, 2]); // Test retrieval of via models as well $this->assertBelongsToManyThroughForDavid($user->permissions()->withVia('roles_via')->get()->toArray()); $user2 = EloquentTestUser::create(['name' => 'Alex']); - $user2->roles()->attach([2,3]); + $user2->roles()->attach([2, 3]); // Test eager loading $users = EloquentTestUser::with(['permissions' => function ($query) { @@ -758,7 +764,7 @@ public function testQueryExcludeOnJoinedTable() $user = EloquentTestUser::create(['name' => 'David']); - $user->roles()->attach([1,2]); + $user->roles()->attach([1, 2]); $users = EloquentTestUser::with(['permissions' => function ($query) { $query->exclude('slug'); @@ -766,27 +772,27 @@ public function testQueryExcludeOnJoinedTable() $this->assertEquals([ [ - 'id' => 1, - 'name' => 'David', + 'id' => 1, + 'name' => 'David', 'permissions' => [ [ - 'id' => 1, + 'id' => 1, 'pivot' => [ - 'user_id' => 1, + 'user_id' => 1, 'permission_id' => 1 ] ], [ - 'id' => 2, + 'id' => 2, 'pivot' => [ - 'user_id' => 1, + 'user_id' => 1, 'permission_id' => 2 ] ], [ - 'id' => 3, + 'id' => 3, 'pivot' => [ - 'user_id' => 1, + 'user_id' => 1, 'permission_id' => 3 ] ] @@ -804,7 +810,7 @@ public function testQueryExcludeUseQualifiedNamesOnJoinedTable() $user = EloquentTestUser::create(['name' => 'David']); - $user->roles()->attach([1,2]); + $user->roles()->attach([1, 2]); $users = EloquentTestUser::with(['roles' => function ($query) { $query->addSelect('roles.*', 'jobs.*')->leftJoin('jobs', 'jobs.role_id', '=', 'roles.id') @@ -813,11 +819,11 @@ public function testQueryExcludeUseQualifiedNamesOnJoinedTable() $this->assertEquals([ [ - 'id' => 1, - 'name' => 'David', + 'id' => 1, + 'name' => 'David', 'roles' => [ [ - 'id' => 1, + 'id' => 1, 'title' => null, 'pivot' => [ 'user_id' => 1, @@ -825,7 +831,7 @@ public function testQueryExcludeUseQualifiedNamesOnJoinedTable() ] ], [ - 'id' => 2, + 'id' => 2, 'title' => null, 'pivot' => [ 'user_id' => 1, @@ -870,7 +876,7 @@ public function testQueryExcludeWildcard() /** * Get a database connection instance. * - * @param string $connection [description] + * @param string $connection [description] * @return \Illuminate\Database\Connection */ protected function connection($connection = 'test_integration') @@ -881,7 +887,7 @@ protected function connection($connection = 'test_integration') /** * Get a schema builder instance. * - * @param string $connection + * @param string $connection * @return \Illuminate\Database\Schema\Builder */ protected function schema($connection = 'test_integration') @@ -896,17 +902,17 @@ protected function generateRoles() { return [ EloquentTestRole::create([ - 'id' => 1, + 'id' => 1, 'slug' => 'forager' ]), EloquentTestRole::create([ - 'id' => 2, + 'id' => 2, 'slug' => 'soldier' ]), EloquentTestRole::create([ - 'id' => 3, + 'id' => 3, 'slug' => 'egg-layer' ]) ]; @@ -919,22 +925,22 @@ protected function generatePermissions() { return [ EloquentTestPermission::create([ - 'id' => 1, + 'id' => 1, 'slug' => 'uri_harvest' ]), EloquentTestPermission::create([ - 'id' => 2, + 'id' => 2, 'slug' => 'uri_spit_acid' ]), EloquentTestPermission::create([ - 'id' => 3, + 'id' => 3, 'slug' => 'uri_slash' ]), EloquentTestPermission::create([ - 'id' => 4, + 'id' => 4, 'slug' => 'uri_royal_jelly' ]) ]; @@ -949,10 +955,10 @@ protected function generateRolesWithPermissions() $this->generatePermissions(); - $roles[0]->permissions()->attach([1,2]); + $roles[0]->permissions()->attach([1, 2]); // We purposefully want a permission that belongs to more than one role - $roles[1]->permissions()->attach([2,3]); - $roles[2]->permissions()->attach([2,4]); + $roles[1]->permissions()->attach([2, 3]); + $roles[2]->permissions()->attach([2, 4]); return $roles; } @@ -963,7 +969,7 @@ protected function generateRolesWithPermissions() protected function generateJobs() { - /** + /* * Sample data | user_id | role_id | location_id | @@ -976,28 +982,28 @@ protected function generateJobs() return [ EloquentTestJob::create([ - 'role_id' => 2, + 'role_id' => 2, 'location_id' => 1, - 'user_id' => 1, - 'title' => 'Grunt' + 'user_id' => 1, + 'title' => 'Grunt' ]), EloquentTestJob::create([ - 'role_id' => 2, + 'role_id' => 2, 'location_id' => 2, - 'user_id' => 1, - 'title' => 'Sergeant' + 'user_id' => 1, + 'title' => 'Sergeant' ]), EloquentTestJob::create([ - 'role_id' => 3, + 'role_id' => 3, 'location_id' => 2, - 'user_id' => 1, - 'title' => 'Queen' + 'user_id' => 1, + 'title' => 'Queen' ]), EloquentTestJob::create([ - 'role_id' => 3, + 'role_id' => 3, 'location_id' => 1, - 'user_id' => 2, - 'title' => 'Demi-queen' + 'user_id' => 2, + 'title' => 'Demi-queen' ]) ]; } @@ -1009,12 +1015,12 @@ protected function generateLocations() { return [ EloquentTestLocation::create([ - 'id' => 1, + 'id' => 1, 'name' => 'Hatchery' ]), EloquentTestLocation::create([ - 'id' => 2, + 'id' => 2, 'name' => 'Nexus' ]) ]; @@ -1027,17 +1033,17 @@ protected function generateTasks() { return [ EloquentTestTask::create([ - 'id' => 1, + 'id' => 1, 'name' => 'Digging' ]), EloquentTestTask::create([ - 'id' => 2, + 'id' => 2, 'name' => 'Chopping' ]), EloquentTestTask::create([ - 'id' => 3, + 'id' => 3, 'name' => 'Baleing' ]) ]; @@ -1050,33 +1056,33 @@ protected function generateAssignments() { return [ EloquentTestAssignment::create([ - 'task_id' => 2, - 'location_id' => 1, - 'assignable_id' => 1, + 'task_id' => 2, + 'location_id' => 1, + 'assignable_id' => 1, 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' ]), EloquentTestAssignment::create([ - 'task_id' => 2, - 'location_id' => 2, - 'assignable_id' => 1, + 'task_id' => 2, + 'location_id' => 2, + 'assignable_id' => 1, 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' ]), EloquentTestAssignment::create([ - 'task_id' => 3, - 'location_id' => 2, - 'assignable_id' => 1, + 'task_id' => 3, + 'location_id' => 2, + 'assignable_id' => 1, 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' ]), EloquentTestAssignment::create([ - 'task_id' => 3, - 'location_id' => 3, - 'assignable_id' => 1, + 'task_id' => 3, + 'location_id' => 3, + 'assignable_id' => 1, 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestNonExistant' ]), EloquentTestAssignment::create([ - 'task_id' => 3, - 'location_id' => 1, - 'assignable_id' => 2, + 'task_id' => 3, + 'location_id' => 1, + 'assignable_id' => 2, 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' ]) ]; @@ -1084,7 +1090,7 @@ protected function generateAssignments() /** * assertBelongsToManyThroughForDavid - * @param array $permissions + * @param array $permissions */ protected function assertBelongsToManyThroughForDavid($permissions) { @@ -1093,41 +1099,41 @@ protected function assertBelongsToManyThroughForDavid($permissions) $this->assertEquals('uri_harvest', $permissions[0]['slug']); $this->assertEquals([ [ - 'id' => 1, - 'slug' => 'forager', + 'id' => 1, + 'slug' => 'forager', 'pivot' => [ 'permission_id' => 1, - 'role_id' => 1 + 'role_id' => 1 ] ] ], $permissions[0]['roles_via']); $this->assertEquals('uri_spit_acid', $permissions[1]['slug']); $this->assertEquals([ [ - 'id' => 1, - 'slug' => 'forager', + 'id' => 1, + 'slug' => 'forager', 'pivot' => [ 'permission_id' => 2, - 'role_id' => 1 + 'role_id' => 1 ] ], [ - 'id' => 2, - 'slug' => 'soldier', + 'id' => 2, + 'slug' => 'soldier', 'pivot' => [ 'permission_id' => 2, - 'role_id' => 2 + 'role_id' => 2 ] ] ], $permissions[1]['roles_via']); $this->assertEquals('uri_slash', $permissions[2]['slug']); $this->assertEquals([ [ - 'id' => 2, - 'slug' => 'soldier', + 'id' => 2, + 'slug' => 'soldier', 'pivot' => [ 'permission_id' => 3, - 'role_id' => 2 + 'role_id' => 2 ] ] ], $permissions[2]['roles_via']); @@ -1135,7 +1141,7 @@ protected function assertBelongsToManyThroughForDavid($permissions) /** * assertBelongsToManyThroughForAlex - * @param array $permissions + * @param array $permissions */ protected function assertBelongsToManyThroughForAlex($permissions) { @@ -1144,41 +1150,41 @@ protected function assertBelongsToManyThroughForAlex($permissions) $this->assertEquals('uri_spit_acid', $permissions[0]['slug']); $this->assertEquals([ [ - 'id' => 2, - 'slug' => 'soldier', + 'id' => 2, + 'slug' => 'soldier', 'pivot' => [ 'permission_id' => 2, - 'role_id' => 2 + 'role_id' => 2 ] ], [ - 'id' => 3, - 'slug' => 'egg-layer', + 'id' => 3, + 'slug' => 'egg-layer', 'pivot' => [ 'permission_id' => 2, - 'role_id' => 3 + 'role_id' => 3 ] ] ], $permissions[0]['roles_via']); $this->assertEquals('uri_slash', $permissions[1]['slug']); $this->assertEquals([ [ - 'id' => 2, - 'slug' => 'soldier', + 'id' => 2, + 'slug' => 'soldier', 'pivot' => [ 'permission_id' => 3, - 'role_id' => 2 + 'role_id' => 2 ] ] ], $permissions[1]['roles_via']); $this->assertEquals('uri_royal_jelly', $permissions[2]['slug']); $this->assertEquals([ [ - 'id' => 3, - 'slug' => 'egg-layer', + 'id' => 3, + 'slug' => 'egg-layer', 'pivot' => [ 'permission_id' => 4, - 'role_id' => 3 + 'role_id' => 3 ] ] ], $permissions[2]['roles_via']); @@ -1198,17 +1204,11 @@ class EloquentTestUser extends EloquentTestModel protected $table = 'users'; protected $guarded = []; - /** - * - */ public function emails() { return $this->hasMany('UserFrosting\Tests\Integration\EloquentTestEmail', 'user_id'); } - /** - * - */ public function phones() { return $this->morphMany('UserFrosting\Tests\Integration\EloquentTestPhone', 'phoneable'); @@ -1311,9 +1311,6 @@ class EloquentTestEmail extends EloquentTestModel protected $table = 'emails'; protected $guarded = []; - /** - * - */ public function user() { return $this->belongsTo('UserFrosting\Tests\Integration\EloquentTestUser', 'user_id'); @@ -1325,9 +1322,6 @@ class EloquentTestPhone extends EloquentTestModel protected $table = 'phones'; protected $guarded = []; - /** - * - */ public function phoneable() { return $this->morphTo(); @@ -1367,9 +1361,6 @@ class EloquentTestTask extends EloquentTestModel protected $table = 'tasks'; protected $guarded = []; - /** - * - */ public function locations() { return $this->belongsToMany( diff --git a/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php b/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php index 6bf4d201a..e10ea5793 100644 --- a/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php +++ b/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php @@ -1,4 +1,10 @@ ci, $this->getRequest(), $this->getResponse(), $this->getException(), false); $this->assertInstanceOf(ExceptionHandler::class, $handler); + return $handler; } diff --git a/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php b/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php index 09ad932ca..1b9c886d6 100644 --- a/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php +++ b/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php @@ -1,4 +1,10 @@ getException('My first exception'); - $exception2 = $this->getException('My second exception', 0, $exception1); - $exception3 = $this->getException('And the third one', 0, $exception2); + $exception1 = $this->getException('My first exception'); + $exception2 = $this->getException('My second exception', 0, $exception1); + $exception3 = $this->getException('And the third one', 0, $exception2); - $inspector = new Inspector($exception3); + $inspector = new Inspector($exception3); $previousExceptions = $inspector->getPreviousExceptionMessages(); @@ -48,8 +54,8 @@ public function testRenderWhoopsPage() $whoopsRenderer->handleUnconditionally(true); $renderBody = $whoopsRenderer->render(); - $this->assertTrue(!!preg_match('/RuntimeException: This is my exception in file /', $renderBody)); - $this->assertTrue(!!preg_match('/This is my exception<\/span>/', $renderBody)); + $this->assertTrue((bool) preg_match('/RuntimeException: This is my exception in file /', $renderBody)); + $this->assertTrue((bool) preg_match('/This is my exception<\/span>/', $renderBody)); } /** diff --git a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php index 173071a08..51c3e7e82 100644 --- a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationDependencyAnalyser; diff --git a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php index fc01f9cc4..d3da7fdfd 100644 --- a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use Mockery as m; diff --git a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php index 6eb7683ad..5c5c1183f 100644 --- a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Integration; use Mockery as m; diff --git a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php index 9131218f4..6ee07ef24 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php @@ -1,4 +1,10 @@ fakeCi = new Container; + $this->fakeCi = new Container(); // Register services stub $serviceProvider = new ServicesProviderStub(); @@ -46,11 +52,12 @@ public function testSeeder() { $seeder = new Seeder($this->fakeCi); $this->assertInstanceOf(Seeder::class, $seeder); + return $seeder; } /** - * @param Seeder $seeder + * @param Seeder $seeder * @depends testSeeder */ public function testgetSeeds(Seeder $seeder) @@ -60,25 +67,25 @@ public function testgetSeeds(Seeder $seeder) $this->assertCount(3, $seeds); $this->assertEquals([ [ - 'name' => 'Seed1', - 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed1', + 'name' => 'Seed1', + 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed1', 'sprinkle' => 'Core' ], [ - 'name' => 'Seed2', - 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed2', + 'name' => 'Seed2', + 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed2', 'sprinkle' => 'Core' ], [ - 'name' => 'Test/Seed', - 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Test\\Seed', + 'name' => 'Test/Seed', + 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Test\\Seed', 'sprinkle' => 'Core' ] ], $seeds); } /** - * @param Seeder $seeder + * @param Seeder $seeder * @depends testSeeder */ public function testGetSeed(Seeder $seeder) @@ -86,14 +93,14 @@ public function testGetSeed(Seeder $seeder) $seed = $seeder->getSeed('Seed1'); $this->assertInternalType('array', $seed); $this->assertEquals([ - 'name' => 'Seed1', - 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed1', + 'name' => 'Seed1', + 'class' => '\\UserFrosting\\Sprinkle\\Core\\Database\\Seeds\\Seed1', 'sprinkle' => 'Core' ], $seed); } /** - * @param Seeder $seeder + * @param Seeder $seeder * @depends testSeeder * @expectedException \Exception */ @@ -103,7 +110,7 @@ public function testUnfoundGetSeed(Seeder $seeder) } /** - * @param Seeder $seeder + * @param Seeder $seeder * @depends testSeeder */ public function testGetSeedClass(Seeder $seeder) @@ -113,7 +120,7 @@ public function testGetSeedClass(Seeder $seeder) } /** - * @param Seeder $seeder + * @param Seeder $seeder * @depends testSeeder * @expectedException \Exception */ @@ -124,7 +131,7 @@ public function testGetSeedClassNotSeedInterface(Seeder $seeder) } /** - * @param Seeder $seeder + * @param Seeder $seeder * @depends testSeeder * @expectedException \Exception */ @@ -135,7 +142,7 @@ public function testGetSeedClassException(Seeder $seeder) } /** - * @param Seeder $seeder + * @param Seeder $seeder * @depends testSeeder */ public function testExecuteSeed(Seeder $seeder) @@ -165,6 +172,7 @@ public function register(ContainerInterface $container) $locator = new ResourceLocator(\UserFrosting\SPRINKLES_DIR); $locator->registerStream('seeds', '', 'Seeder/Seeds/'); $locator->registerLocation('Core', 'core/tests/Integration/'); + return $locator; }; } diff --git a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php index f589c9447..419ae5d00 100644 --- a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php +++ b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php @@ -1,4 +1,10 @@ ci->db->getConnection(); + return $connection->getDatabaseName() == ':memory:'; } @@ -54,7 +56,7 @@ protected function refreshInMemoryDatabase() */ protected function refreshTestDatabase() { - if (! self::$migrated) { + if (!self::$migrated) { // Refresh the Database. Rollback all migrations and start over $this->ci->migrator->reset(); diff --git a/app/sprinkles/core/tests/TestDatabase.php b/app/sprinkles/core/tests/TestDatabase.php index ae8b8dd14..772d9f737 100644 --- a/app/sprinkles/core/tests/TestDatabase.php +++ b/app/sprinkles/core/tests/TestDatabase.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Tests; /** diff --git a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php index fa4a2b4de..97bc6a80d 100644 --- a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php +++ b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests\Unit; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; @@ -47,11 +48,11 @@ public function testPaginatedQuery() // Mock the collection generated by the constrained query $collection = m::mock('Illuminate\Database\Eloquent\Collection'); $collection->shouldReceive('pluck')->once()->with('id')->andReturn($collection); - $collection->shouldReceive('toArray')->once()->andReturn([1,2]); + $collection->shouldReceive('toArray')->once()->andReturn([1, 2]); $builder->shouldReceive('get')->once()->andReturn($collection); // Test the final modification to the original unpaginated query - $builder->shouldReceive('whereIn')->once()->with('users.id', [1,2])->andReturnSelf(); + $builder->shouldReceive('whereIn')->once()->with('users.id', [1, 2])->andReturnSelf(); $paginatedQuery = $relation->getPaginatedQuery($builder, 2, 1); } diff --git a/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php b/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php index fd8d0deb8..404f3a7de 100644 --- a/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php +++ b/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Tests\Unit; use stdClass; @@ -57,7 +58,7 @@ public function testSyncMethod($list) ]); $model->shouldReceive('getAttribute')->with('id')->andReturn('x'); - $this->assertEquals(['created' => ['x'], 'deleted' => [1], 'updated' => [2,3]], $relation->sync($list)); + $this->assertEquals(['created' => ['x'], 'deleted' => [1], 'updated' => [2, 3]], $relation->sync($list)); } /** @@ -74,6 +75,7 @@ protected function getRelation() $parent->shouldReceive('getAttribute')->with('id')->andReturn(1); $parent->shouldReceive('getCreatedAtColumn')->andReturn('created_at'); $parent->shouldReceive('getUpdatedAtColumn')->andReturn('updated_at'); + return new HasManySyncable($builder, $parent, 'table.foreign_key', 'id'); } @@ -85,11 +87,11 @@ public function syncMethodHasManyListProvider() // First argument [ [ - 'id' => 2, + 'id' => 2, 'species' => 'Tyto' ], [ - 'id' => 3, + 'id' => 3, 'species' => 'Megascops' ], [ @@ -105,6 +107,7 @@ protected function expectNewModel($relation, $attributes = null) { $relation->getRelated()->shouldReceive('newInstance')->once()->with($attributes)->andReturn($model = m::mock(Model::class)); $model->shouldReceive('setAttribute')->with('foreign_key', 1)->andReturn($model); + return $model; } @@ -112,6 +115,7 @@ protected function expectCreatedModel($relation, $attributes) { $model = $this->expectNewModel($relation, $attributes); $model->shouldReceive('save')->andReturn($model); + return $model; } } diff --git a/app/sprinkles/core/tests/Unit/FilesystemTest.php b/app/sprinkles/core/tests/Unit/FilesystemTest.php index 0a85d9140..f0a0fa3b8 100644 --- a/app/sprinkles/core/tests/Unit/FilesystemTest.php +++ b/app/sprinkles/core/tests/Unit/FilesystemTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Sprinkle\Core\Tests\Unit; use Illuminate\Filesystem\FilesystemAdapter; @@ -21,10 +22,10 @@ */ class FilesystemTest extends TestCase { - /** @var string Testing storage path **/ + /** @var string Testing storage path */ private $testDir; - /** @var string Test disk name **/ + /** @var string Test disk name */ private $testDisk = 'testing'; /** @@ -70,7 +71,7 @@ public function testFacade() } /** - * @param FilesystemAdapter $files + * @param FilesystemAdapter $files * @depends testService */ public function testAdapter(FilesystemAdapter $files) @@ -90,7 +91,7 @@ public function testAdapter(FilesystemAdapter $files) } /** - * @param FilesystemAdapter $files + * @param FilesystemAdapter $files * @depends testService * NOTE : The `download` method was introduced in Laravel 5.5. * We'll need to enable this once we can upgrade to newer version of Laravel @@ -104,7 +105,7 @@ public function testAdapter(FilesystemAdapter $files) }*/ /** - * @param FilesystemAdapter $files + * @param FilesystemAdapter $files * @depends testService */ public function testUrl(FilesystemAdapter $files) @@ -125,7 +126,7 @@ public function testNonExistingAdapter() $filesystemManager = $this->ci->filesystem; // InvalidArgumentException - $this->expectException("InvalidArgumentException"); + $this->expectException('InvalidArgumentException'); $filesystemManager->disk('testingDriver'); } diff --git a/app/sprinkles/core/tests/Unit/RouterTest.php b/app/sprinkles/core/tests/Unit/RouterTest.php index ebdca7980..cd90c9fa9 100644 --- a/app/sprinkles/core/tests/Unit/RouterTest.php +++ b/app/sprinkles/core/tests/Unit/RouterTest.php @@ -1,4 +1,10 @@ app = new Application("UserFrosting Bakery", \UserFrosting\VERSION); + $this->app = new Application('UserFrosting Bakery', \UserFrosting\VERSION); // Setup the sprinkles $uf = new UserFrosting(true); @@ -74,8 +75,8 @@ public function run() protected function loadCommands() { /** - * @var ResourceLocator $locator - */ + * @var ResourceLocator $locator + */ $locator = $this->ci->locator; // Get Bakery command resources @@ -92,20 +93,20 @@ protected function loadCommands() // Class must be an instance of symfony command if (!$instance instanceof Command) { - throw new \Exception("Bakery command class must be an instance of `" . Command::class . "`"); + throw new \Exception('Bakery command class must be an instance of `' . Command::class . '`'); } // Add command to the Console app $instance->setContainer($this->ci); $this->app->add($instance); - }; + } } /** * Transform a Bakery Command Resource into a classpath * - * @param Resource $file The command resource - * @return string The command class path + * @param \UserFrosting\UniformResourceLocator\Resource $file The command resource + * @return string The command class path */ protected function getResourceClass(Resource $file) { diff --git a/app/system/Bakery/BaseCommand.php b/app/system/Bakery/BaseCommand.php index b9e041e25..146f47919 100644 --- a/app/system/Bakery/BaseCommand.php +++ b/app/system/Bakery/BaseCommand.php @@ -5,14 +5,12 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System\Bakery; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Formatter\OutputFormatterStyle; use Symfony\Component\Console\Style\SymfonyStyle; use Interop\Container\ContainerInterface; @@ -61,8 +59,8 @@ protected function isProduction() { // N.B.: Need to touch the config service first to load dotenv values $config = $this->ci->config; - $mode = getenv("UF_MODE") ?: ''; + $mode = getenv('UF_MODE') ?: ''; - return ($mode == "production"); + return $mode == 'production'; } } diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/system/Bakery/Command/BuildAssets.php index 8a3fb63d6..7e44f831e 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/system/Bakery/Command/BuildAssets.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System\Bakery\Command; use Symfony\Component\Console\Input\InputInterface; @@ -30,11 +31,11 @@ class BuildAssets extends BaseCommand */ protected function configure() { - $this->setName("build-assets") - ->setDescription("Build the assets using node and npm") - ->setHelp("The build directory contains the scripts and configuration files required to download Javascript, CSS, and other assets used by UserFrosting. This command will install Gulp, Bower, and several other required npm packages locally. With npm set up with all of its required packages, it can be use it to automatically download and install the assets in the correct directories. For more info, see https://learn.userfrosting.com/basics/installation") - ->addOption("compile", "c", InputOption::VALUE_NONE, "Compile the assets and asset bundles for production environment") - ->addOption("force", "f", InputOption::VALUE_NONE, "Force assets compilation by deleting cached data and installed assets before proceeding"); + $this->setName('build-assets') + ->setDescription('Build the assets using node and npm') + ->setHelp('The build directory contains the scripts and configuration files required to download Javascript, CSS, and other assets used by UserFrosting. This command will install Gulp, Bower, and several other required npm packages locally. With npm set up with all of its required packages, it can be use it to automatically download and install the assets in the correct directories. For more info, see https://learn.userfrosting.com/basics/installation') + ->addOption('compile', 'c', InputOption::VALUE_NONE, 'Compile the assets and asset bundles for production environment') + ->addOption('force', 'f', InputOption::VALUE_NONE, 'Force assets compilation by deleting cached data and installed assets before proceeding'); } /** @@ -63,7 +64,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } // If all went well and there's no fatal errors, we are successful - $this->io->success("Assets install looks successful, check output for specifics"); + $this->io->success('Assets install looks successful, check output for specifics'); } /** @@ -71,18 +72,18 @@ protected function execute(InputInterface $input, OutputInterface $output) */ protected function npmInstall() { - $this->io->section("Installing npm dependencies"); - $this->io->writeln("> npm install"); + $this->io->section('Installing npm dependencies'); + $this->io->writeln('> npm install'); // Temporarily change the working directory so we can install npm dependencies $wd = getcwd(); chdir($this->buildPath); $exitCode = 0; - passthru("npm install", $exitCode); + passthru('npm install', $exitCode); chdir($wd); if ($exitCode !== 0) { - $this->io->error("npm dependency installation has failed"); + $this->io->error('npm dependency installation has failed'); exit(1); } } @@ -92,18 +93,18 @@ protected function npmInstall() */ protected function assetsInstall() { - $this->io->section("Installing frontend vendor assets"); - $this->io->writeln("> npm run uf-assets-install"); + $this->io->section('Installing frontend vendor assets'); + $this->io->writeln('> npm run uf-assets-install'); // Temporarily change the working directory (more reliable than --prefix npm switch) $wd = getcwd(); chdir($this->buildPath); $exitCode = 0; - passthru("npm run uf-assets-install", $exitCode); + passthru('npm run uf-assets-install', $exitCode); chdir($wd); if ($exitCode !== 0) { - $this->io->error("assets installation has failed"); + $this->io->error('assets installation has failed'); exit(1); } @@ -115,7 +116,7 @@ protected function assetsInstall() */ protected function buildAssets() { - $this->io->section("Building assets for production"); + $this->io->section('Building assets for production'); // Temporarily change the working directory (more reliable than --prefix npm switch) $wd = getcwd(); @@ -123,28 +124,28 @@ protected function buildAssets() $exitCode = 0; - $this->io->writeln("> npm run uf-bundle-build"); - passthru("npm run uf-bundle-build", $exitCode); + $this->io->writeln('> npm run uf-bundle-build'); + passthru('npm run uf-bundle-build', $exitCode); if ($exitCode !== 0) { - $this->io->error("bundling preparation has failed"); + $this->io->error('bundling preparation has failed'); exit(1); } - $this->io->writeln("> npm run uf-bundle"); - passthru("npm run uf-bundle"); + $this->io->writeln('> npm run uf-bundle'); + passthru('npm run uf-bundle'); if ($exitCode !== 0) { - $this->io->error("bundling has failed"); + $this->io->error('bundling has failed'); exit(1); } if ($exitCode !== 0) { - $this->io->warning("bundling may have failed, check output"); + $this->io->warning('bundling may have failed, check output'); } - $this->io->writeln("> npm run uf-bundle-clean"); - passthru("npm run uf-bundle-clean"); + $this->io->writeln('> npm run uf-bundle-clean'); + passthru('npm run uf-bundle-clean'); if ($exitCode !== 0) { $this->io->warning("bundling cleanup has failed, which while unusual shouldn't cause any problems"); @@ -159,18 +160,18 @@ protected function buildAssets() */ protected function clean() { - $this->io->section("Cleaning cached data"); - $this->io->writeln("> npm run uf-clean"); + $this->io->section('Cleaning cached data'); + $this->io->writeln('> npm run uf-clean'); // Temporarily change the working directory (more reliable than --prefix npm switch) $wd = getcwd(); chdir($this->buildPath); $exitCode = 0; - passthru("npm run uf-clean", $exitCode); + passthru('npm run uf-clean', $exitCode); chdir($wd); if ($exitCode !== 0) { - $this->io->error("Failed to clean cached data"); + $this->io->error('Failed to clean cached data'); exit(1); } } diff --git a/app/system/Bakery/Command/Test.php b/app/system/Bakery/Command/Test.php index a7d6c84de..96eaa2075 100644 --- a/app/system/Bakery/Command/Test.php +++ b/app/system/Bakery/Command/Test.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System\Bakery\Command; use Symfony\Component\Console\Input\InputInterface; @@ -30,10 +31,10 @@ class Test extends BaseCommand */ protected function configure() { - $this->setName("test") - ->addOption("coverage", "c", InputOption::VALUE_NONE, "Generate code coverage report in HTML format. Will be saved in _meta/coverage") - ->setDescription("Run tests") - ->setHelp("Run php unit tests"); + $this->setName('test') + ->addOption('coverage', 'c', InputOption::VALUE_NONE, 'Generate code coverage report in HTML format. Will be saved in _meta/coverage') + ->setDescription('Run tests') + ->setHelp('Run php unit tests'); } /** @@ -44,14 +45,14 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->title("UserFrosting's Tester"); // Get command - $command = \UserFrosting\VENDOR_DIR . "/bin/phpunit --colors=always"; + $command = \UserFrosting\VENDOR_DIR . '/bin/phpunit --colors=always'; if ($output->isVerbose() || $output->isVeryVerbose()) { - $command .= " -v"; + $command .= ' -v'; } // Add coverage report if ($input->getOption('coverage')) { - $command .= " --coverage-html _meta/coverage"; + $command .= ' --coverage-html _meta/coverage'; } // Execute diff --git a/app/system/Bakery/ConfirmableTrait.php b/app/system/Bakery/ConfirmableTrait.php index a4baec98f..638a3b3c1 100644 --- a/app/system/Bakery/ConfirmableTrait.php +++ b/app/system/Bakery/ConfirmableTrait.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System\Bakery; /** @@ -18,9 +19,9 @@ trait ConfirmableTrait * Confirm before proceeding with the action. * This method only asks for confirmation in production. * - * @param bool $force - * @param string $warning - * @param \Closure|bool|null $callback + * @param bool $force + * @param string $warning + * @param \Closure|bool|null $callback * @return bool */ public function confirmToProceed($force = false, $warning = 'Application In Production Mode!', $callback = null) @@ -39,8 +40,9 @@ public function confirmToProceed($force = false, $warning = 'Application In Prod // Ask confirmation $confirmed = $this->io->confirm('Do you really wish to run this command?', false); - if (! $confirmed) { + if (!$confirmed) { $this->io->comment('Command Cancelled!'); + return false; } } diff --git a/app/system/Bakery/DatabaseTest.php b/app/system/Bakery/DatabaseTest.php index 97ecfd3a2..6f7e7c7a4 100644 --- a/app/system/Bakery/DatabaseTest.php +++ b/app/system/Bakery/DatabaseTest.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System\Bakery; use Illuminate\Database\Capsule\Manager as Capsule; @@ -39,9 +40,9 @@ protected function testDB() try { Capsule::connection()->getPdo(); } catch (\PDOException $e) { - $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; - $message .= "Exception: " . $e->getMessage() . PHP_EOL.PHP_EOL; - $message .= "Please check your database configuration and/or google the exception shown above and run command again."; + $message = "Could not connect to the database '{$dbParams['username']}@{$dbParams['host']}/{$dbParams['database']}':".PHP_EOL; + $message .= 'Exception: ' . $e->getMessage() . PHP_EOL.PHP_EOL; + $message .= 'Please check your database configuration and/or google the exception shown above and run command again.'; throw new \Exception($message); } diff --git a/app/system/Bakery/Migration.php b/app/system/Bakery/Migration.php index 6023d3672..cd7d2dfe2 100644 --- a/app/system/Bakery/Migration.php +++ b/app/system/Bakery/Migration.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System\Bakery; use Illuminate\Database\Schema\Builder; @@ -24,8 +25,8 @@ abstract class Migration extends NewMigration /** * Constructor * - * @param Builder|null $schema The schema builder - * @param SymfonyStyle|null $io The SymfonyStyle instance + * @param Builder|null $schema The schema builder + * @param SymfonyStyle|null $io The SymfonyStyle instance */ public function __construct(Builder $schema = null, SymfonyStyle $io = null) { diff --git a/app/system/Facade.php b/app/system/Facade.php index 8ec704816..98294fef4 100644 --- a/app/system/Facade.php +++ b/app/system/Facade.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System; use Mockery; @@ -74,7 +75,7 @@ public static function shouldReceive() /** * Create a fresh mock instance for the given class. * - * @param string $name + * @param string $name * @return \Mockery\Expectation */ protected static function createFreshMockInstance($name) @@ -93,7 +94,7 @@ protected static function createFreshMockInstance($name) /** * Create a fresh mock instance for the given class. * - * @param string $name + * @param string $name * @return \Mockery\Expectation */ protected static function createMockByName($name) @@ -150,7 +151,7 @@ protected static function getFacadeAccessor() /** * Resolve the facade root instance from the container. * - * @param string|object $name + * @param string|object $name * @return mixed */ protected static function resolveFacadeInstance($name) @@ -169,7 +170,7 @@ protected static function resolveFacadeInstance($name) /** * Clear a resolved facade instance. * - * @param string $name + * @param string $name */ public static function clearResolvedInstance($name) { @@ -197,7 +198,7 @@ public static function getFacadeContainer() /** * Set the container instance. * - * @param ContainerInterface $container + * @param ContainerInterface $container */ public static function setFacadeContainer(ContainerInterface $container) { @@ -207,16 +208,16 @@ public static function setFacadeContainer(ContainerInterface $container) /** * Handle dynamic, static calls to the object. * + * @param string $method + * @param array $args * @throws \RuntimeException - * @param string $method - * @param array $args * @return mixed */ public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); - if (! $instance) { + if (!$instance) { throw new RuntimeException('A facade root has not been set.'); } diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index c815885a3..d0d043011 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System; use Interop\Container\ContainerInterface; diff --git a/app/system/SlimAppEvent.php b/app/system/SlimAppEvent.php index 7e146ca10..77f0aa901 100644 --- a/app/system/SlimAppEvent.php +++ b/app/system/SlimAppEvent.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System; use RocketTheme\Toolbox\Event\Event; diff --git a/app/system/Sprinkle/Sprinkle.php b/app/system/Sprinkle/Sprinkle.php index f9d4ce82b..b66e48862 100644 --- a/app/system/Sprinkle/Sprinkle.php +++ b/app/system/Sprinkle/Sprinkle.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System\Sprinkle; use Interop\Container\ContainerInterface; diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index 4ec3b34fa..387ddde86 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System\Sprinkle; use Illuminate\Support\Str; @@ -78,8 +79,8 @@ public function addSprinkleResources($sprinkleName) * * Creates an object of a subclass of UserFrosting\System\Sprinkle\Sprinkle if defined for the sprinkle (converting to StudlyCase). * Otherwise, returns null. - * @param string $name The name of the Sprinkle to initialize. - * @return mixed Sprinkle class instance or null if no such class exist + * @param string $name The name of the Sprinkle to initialize. + * @return mixed Sprinkle class instance or null if no such class exist */ public function bootSprinkle($name) { @@ -89,9 +90,10 @@ public function bootSprinkle($name) // Check that class exists. If not, set to null if (class_exists($fullClassName)) { $sprinkle = new $fullClassName($this->ci); + return $sprinkle; } else { - return null; + return; } } @@ -150,7 +152,7 @@ public function initFromSchema($schemaPath) * Return if a Sprinkle is available * Can be used by other Sprinkles to test if their dependencies are met * - * @param string $name The name of the Sprinkle + * @param string $name The name of the Sprinkle * @return bool */ public function isAvailable($name) @@ -158,7 +160,6 @@ public function isAvailable($name) return in_array($name, $this->getSprinkleNames()); } - /** * Interate through the list of loaded Sprinkles, and invoke their ServiceProvider classes. */ @@ -190,7 +191,7 @@ public function registerServices($name) /** * Load list of Sprinkles from a JSON schema file (e.g. 'sprinkles.json'). * - * @param string $schemaPath + * @param string $schemaPath * @return string[] */ protected function loadSchema($schemaPath) diff --git a/app/system/UserFrosting.php b/app/system/UserFrosting.php index 511412201..3aca2d4c2 100644 --- a/app/system/UserFrosting.php +++ b/app/system/UserFrosting.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\System; use RocketTheme\Toolbox\Event\EventDispatcher; @@ -12,7 +13,6 @@ use Slim\App; use Slim\Container; use UserFrosting\Support\Exception\FileNotFoundException; -use UserFrosting\System\Facade; /** * UserFrosting Main Class @@ -42,7 +42,7 @@ class UserFrosting public function __construct($cli = false) { // First, we create our DI container - $this->ci = new Container; + $this->ci = new Container(); // Assign vars $this->isCli = $cli; @@ -57,8 +57,8 @@ public function __construct($cli = false) /** * Fires an event with optional parameters. * - * @param string $eventName - * @param Event|null $event + * @param string $eventName + * @param Event|null $event * @return Event */ public function fireEvent($eventName, Event $event = null) @@ -160,18 +160,18 @@ protected function setupApp() * * @param string $errorMessage Message to display [Default ""] */ - protected function renderSprinkleErrorPage($errorMessage = "") + protected function renderSprinkleErrorPage($errorMessage = '') { ob_clean(); - $title = "UserFrosting Application Error"; - $errorMessage = "Unable to start site. Contact owner.

" . - "Version: UserFrosting ".\UserFrosting\VERSION."
" . + $title = 'UserFrosting Application Error'; + $errorMessage = 'Unable to start site. Contact owner.

' . + 'Version: UserFrosting '.\UserFrosting\VERSION.'
' . $errorMessage; $output = sprintf( "" . - "%s

%s

%s", + '%s

%s

%s', $title, $title, $errorMessage @@ -184,7 +184,7 @@ protected function renderSprinkleErrorPage($errorMessage = "") * * @param string $errorMessage Message to display [Default ""] */ - protected function renderSprinkleErrorCli($errorMessage = "") + protected function renderSprinkleErrorCli($errorMessage = '') { exit($errorMessage . PHP_EOL); } diff --git a/app/tests/DatabaseTransactions.php b/app/tests/DatabaseTransactions.php index fd1a5463d..7ac961dc0 100644 --- a/app/tests/DatabaseTransactions.php +++ b/app/tests/DatabaseTransactions.php @@ -5,6 +5,7 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests; /** diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php index 13e1d0c69..87d210a32 100644 --- a/app/tests/TestCase.php +++ b/app/tests/TestCase.php @@ -5,12 +5,12 @@ * @link https://github.com/userfrosting/UserFrosting * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ + namespace UserFrosting\Tests; use PHPUnit\Framework\TestCase as BaseTestCase; use UserFrosting\System\UserFrosting; use UserFrosting\Sprinkle\Core\Facades\Debug; -use UserFrosting\Tests\DatabaseTransactions; /** * Class to handle Test @@ -120,7 +120,7 @@ protected function tearDown() /** * Register a callback to be run after the application is created. * - * @param callable $callback + * @param callable $callback */ public function afterApplicationCreated(callable $callback) { @@ -134,10 +134,10 @@ public function afterApplicationCreated(callable $callback) /** * Asserts that collections are equivalent. * - * @param array $expected - * @param array $actual - * @param string $key [description] - * @param string $message [description] + * @param array $expected + * @param array $actual + * @param string $key [description] + * @param string $message [description] * @throws \PHPUnit_Framework_AssertionFailedError */ public static function assertCollectionsSame($expected, $actual, $key = 'id', $message = '') @@ -168,12 +168,12 @@ public static function assertCollectionsSame($expected, $actual, $key = 'id', $m /** * Call protected/private method of a class. * - * @param object &$object Instantiated object that we will run method on. - * @param string $methodName Method name to call - * @param array $parameters Array of parameters to pass into method. - * @return mixed Method return. + * @param object &$object Instantiated object that we will run method on. + * @param string $methodName Method name to call + * @param array $parameters Array of parameters to pass into method. + * @return mixed Method return. */ - public function invokeMethod(&$object, $methodName, array $parameters = array()) + public function invokeMethod(&$object, $methodName, array $parameters = []) { $reflection = new \ReflectionClass(get_class($object)); $method = $reflection->getMethod($methodName); @@ -185,7 +185,7 @@ public function invokeMethod(&$object, $methodName, array $parameters = array()) /** * Register a callback to be run before the application is destroyed. * - * @param callable $callback + * @param callable $callback */ protected function beforeApplicationDestroyed(callable $callback) { @@ -210,7 +210,7 @@ protected static function castToComparable($item) /** * Remove all relations on a collection of models. * - * @param array $models + * @param array $models */ protected static function ignoreRelations($models) { diff --git a/app/tests/Unit/ExampleTest.php b/app/tests/Unit/ExampleTest.php index 304fcf196..d0bae826a 100644 --- a/app/tests/Unit/ExampleTest.php +++ b/app/tests/Unit/ExampleTest.php @@ -1,4 +1,10 @@ Date: Sun, 11 Nov 2018 20:20:23 -0500 Subject: [PATCH 139/237] Add PHP-CS-Fixer cache file location config --- .php_cs | 1 + 1 file changed, 1 insertion(+) diff --git a/.php_cs b/.php_cs index 57610a595..e8df3e4ea 100755 --- a/.php_cs +++ b/.php_cs @@ -110,4 +110,5 @@ return PhpCsFixer\Config::create() ->setRules($rules) ->setFinder($finder) ->setUsingCache(true) + ->setCacheFile(__DIR__.'/.php_cs.cache') ->setRiskyAllowed(true); From 116453da33b7396edabb0cb026a12377e5aa6883 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 12 Nov 2018 20:15:55 -0500 Subject: [PATCH 140/237] Use custom `PDOStorage` for Rememberme (Resolve #915) --- app/sprinkles/account/config/default.php | 7 - .../src/Authenticate/Authenticator.php | 20 +-- .../src/Database/Models/Persistence.php | 68 +++++++++ .../account/src/Rememberme/PDOStorage.php | 121 +++++++++++++++ .../src/ServicesProvider/ServicesProvider.php | 7 +- .../tests/Integration/AuthenticatorTest.php | 29 +--- .../account/tests/Unit/PDOStorageTest.php | 143 ++++++++++++++++++ 7 files changed, 351 insertions(+), 44 deletions(-) create mode 100644 app/sprinkles/account/src/Database/Models/Persistence.php create mode 100644 app/sprinkles/account/src/Rememberme/PDOStorage.php create mode 100644 app/sprinkles/account/tests/Unit/PDOStorageTest.php diff --git a/app/sprinkles/account/config/default.php b/app/sprinkles/account/config/default.php index 71c689696..fb811fcf1 100644 --- a/app/sprinkles/account/config/default.php +++ b/app/sprinkles/account/config/default.php @@ -47,13 +47,6 @@ 'expire_time' => 604800, 'session' => [ 'path' => '/' - ], - 'table' => [ - 'tableName' => 'persistences', - 'credentialColumn' => 'user_id', - 'tokenColumn' => 'token', - 'persistentTokenColumn' => 'persistent_token', - 'expiresColumn' => 'expires_at' ] ], diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index a7aff94ee..2383a4e04 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -9,7 +9,6 @@ namespace UserFrosting\Sprinkle\Account\Authenticate; use Birke\Rememberme\Authenticator as RememberMe; -use Birke\Rememberme\Storage\PDOStorage as RememberMePDO; use Birke\Rememberme\Triplet as RememberMeTriplet; use Illuminate\Cache\Repository as Cache; use Illuminate\Database\Capsule\Manager as Capsule; @@ -22,6 +21,7 @@ use UserFrosting\Sprinkle\Account\Authenticate\Exception\InvalidCredentialsException; use UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface; use UserFrosting\Sprinkle\Account\Facades\Password; +use UserFrosting\Sprinkle\Account\Rememberme\PDOStorage as RememberMePDO; use UserFrosting\Sprinkle\Core\Util\ClassMapper; use UserFrosting\Support\Repository\Repository as Config; @@ -53,6 +53,11 @@ class Authenticator */ protected $cache; + /** + * @var Capsule + */ + protected $db; + /** * @var bool */ @@ -87,24 +92,22 @@ class Authenticator * @param Session $session The session wrapper object that will store the user's id. * @param Config $config Config object that contains authentication settings. * @param Cache $cache Cache service instance + * @param Capsule $capsule Database service instance */ - public function __construct(ClassMapper $classMapper, Session $session, Config $config, Cache $cache) + public function __construct(ClassMapper $classMapper, Session $session, Config $config, Cache $cache, Capsule $db) { $this->classMapper = $classMapper; $this->session = $session; $this->config = $config; $this->cache = $cache; + $this->db = $db; // Initialize RememberMe storage - $this->rememberMeStorage = new RememberMePDO($this->config['remember_me.table']); - - // Get the actual PDO instance from Eloquent - $pdo = Capsule::connection()->getPdo(); - - $this->rememberMeStorage->setConnection($pdo); + $this->rememberMeStorage = new RememberMePDO($this->db); // Set up RememberMe $this->rememberMe = new RememberMe($this->rememberMeStorage); + // Set cookie name $cookieName = $this->config['session.name'] . '-' . $this->config['remember_me.cookie.name']; $this->rememberMe->getCookie()->setName($cookieName); @@ -118,7 +121,6 @@ public function __construct(ClassMapper $classMapper, Session $session, Config $ } $this->user = null; - $this->viaRemember = false; } diff --git a/app/sprinkles/account/src/Database/Models/Persistence.php b/app/sprinkles/account/src/Database/Models/Persistence.php new file mode 100644 index 000000000..c8a6ad4be --- /dev/null +++ b/app/sprinkles/account/src/Database/Models/Persistence.php @@ -0,0 +1,68 @@ +classMapper; + + return $this->hasOne( + $classMapper->getClassMapping('user') + ); + } + + /** + * Scope a query to only include not expired entries + * + * @param \Illuminate\Database\Eloquent\Builder $query + * @return \Illuminate\Database\Eloquent\Builder + */ + public function scopeNotExpired($query) + { + return $query->where('expires_at', '>', Carbon::now()); + } +} diff --git a/app/sprinkles/account/src/Rememberme/PDOStorage.php b/app/sprinkles/account/src/Rememberme/PDOStorage.php new file mode 100644 index 000000000..1eebc7cf4 --- /dev/null +++ b/app/sprinkles/account/src/Rememberme/PDOStorage.php @@ -0,0 +1,121 @@ +db = $db; + } + + /** + * @param mixed $credential + * @param string $token + * @param string $persistentToken + * @return int + */ + public function findTriplet($credential, $token, $persistentToken) + { + $result = Persistence::notExpired()->where([ + 'user_id' => $credential, + 'persistent_token' => sha1($persistentToken) + ])->first(); + + if (!$result) { + return self::TRIPLET_NOT_FOUND; + } elseif ($result->token === sha1($token)) { + return self::TRIPLET_FOUND; + } + + return self::TRIPLET_INVALID; + } + + /** + * @param mixed $credential + * @param string $token + * @param string $persistentToken + * @param int $expire + */ + public function storeTriplet($credential, $token, $persistentToken, $expire = 0) + { + $persistence = new Persistence([ + 'user_id' => $credential, + 'token' => sha1($token), + 'persistent_token' => sha1($persistentToken), + 'expires_at' => date('Y-m-d H:i:s', $expire) + ]); + $persistence->save(); + } + + /** + * @param mixed $credential + * @param string $persistentToken + */ + public function cleanTriplet($credential, $persistentToken) + { + Persistence::where([ + 'user_id' => $credential, + 'persistent_token' => sha1($persistentToken) + ])->delete(); + } + + /** + * Replace current token after successful authentication + * + * @param mixed $credential + * @param string $token + * @param string $persistentToken + * @param int $expire + */ + public function replaceTriplet($credential, $token, $persistentToken, $expire = 0) + { + try { + Capsule::transaction(function () use ($credential, $token, $persistentToken, $expire) { + $this->cleanTriplet($credential, $persistentToken); + $this->storeTriplet($credential, $token, $persistentToken, $expire); + }); + } catch (\PDOException $e) { + throw $e; + } + } + + /** + * @param mixed $credential + */ + public function cleanAllTriplets($credential) + { + Persistence::where('user_id', $credential)->delete(); + } + + /** + * Remove all expired triplets of all users. + * + * @param int $expiryTime Timestamp, all tokens before this time will be deleted + */ + public function cleanExpiredTokens($expiryTime) + { + Persistence::where('expires_at', '<', date('Y-m-d H:i:s', $expiryTime))->delete(); + } +} diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index 45c1c08be..408a4b816 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -164,12 +164,9 @@ public function register(ContainerInterface $container) $cache = $c->cache; // Force database connection to boot up - $c->db; + $db = $c->db; - // Fix RememberMe table name - $config['remember_me.table.tableName'] = Capsule::connection()->getTablePrefix() . $config['remember_me.table.tableName']; - - $authenticator = new Authenticator($classMapper, $session, $config, $cache); + $authenticator = new Authenticator($classMapper, $session, $config, $cache, $db); return $authenticator; }; diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index 31686ab56..c0d3b23db 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -71,9 +71,7 @@ public function testLogin(Authenticator $authenticator) $this->assertSame($testUser->id, $this->ci->session[$key]); // Must logout to avoid test issue - $authenticator->logout(); - // $authenticator->logout(true); //<-- Doesn't work with SQLite. Doctrine\DBAL\Driver\PDOException: SQLSTATE[HY000]: General error: 5 database is locked - // Is required to test the `cleanAllTriplets` thing + $authenticator->logout(true); // We'll test the logout system works too while we're at it (and depend on it) $key = $this->ci->config['session.keys.current_user_id']; @@ -135,24 +133,11 @@ public function testValidateUserAccountWithAccountDisabledException(Authenticato $this->invokeMethod($authenticator, 'validateUserAccount', [$testUser->id]); } - /** - * The next test doesn't work with SQLite, as birke/rememberme doesn't look - * compatible with SQLite - * - * Exception : - * Doctrine\DBAL\Driver\PDOException: SQLSTATE[HY000]: General error: 1 no such function: NOW - * app/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:82 - * app/vendor/birke/rememberme/src/Storage/PDOStorage.php:28 - * app/vendor/birke/rememberme/src/Authenticator.php:107 - * app/sprinkles/account/src/Authenticate/Authenticator.php:332 - * app/tests/TestCase.php:182 - * app/sprinkles/account/tests/Integration/AuthenticatorTest.php:161 - */ /** * @depends testConstructor * @param Authenticator $authenticator */ - /*public function testLoginWithRememberMe(Authenticator $authenticator) + public function testLoginWithRememberMe(Authenticator $authenticator) { // Create a test user $testUser = $this->createTestUser(); @@ -176,19 +161,17 @@ public function testValidateUserAccountWithAccountDisabledException(Authenticato // Go througt the loginRememberedUser process // First, we'll simulate a page refresh by creating a new authenticator $authenticator = $this->getAuthenticator(); - $user = $authenticator->user(); - //$user = $this->invokeMethod($authenticator, 'loginRememberedUser'); //<-- Use this to see the PDOException // If loginRememberedUser returns a PDOException, `user` will return a null user $this->assertNotNull($user); - $this->assertSame($testUser->id, $user->id); - $this->assertSame($testUser->id, $this->ci->session[$key]); + $this->assertEquals($testUser->id, $user->id); + $this->assertEquals($testUser->id, $this->ci->session[$key]); $this->assertTrue($authenticator->viaRemember()); // Must logout to avoid test issue $authenticator->logout(); - }*/ + } /** * @depends testConstructor @@ -365,6 +348,6 @@ public function testCheckWithLoggedInUser() */ protected function getAuthenticator() { - return new Authenticator($this->ci->classMapper, $this->ci->session, $this->ci->config, $this->ci->cache); + return new Authenticator($this->ci->classMapper, $this->ci->session, $this->ci->config, $this->ci->cache, $this->ci->db); } } diff --git a/app/sprinkles/account/tests/Unit/PDOStorageTest.php b/app/sprinkles/account/tests/Unit/PDOStorageTest.php new file mode 100644 index 000000000..ae33aefff --- /dev/null +++ b/app/sprinkles/account/tests/Unit/PDOStorageTest.php @@ -0,0 +1,143 @@ +setupTestDatabase(); + $this->refreshDatabase(); + + $this->storage = new PDOStorage($this->ci->db); + } + + public function testFindTripletReturnsFoundIfDataMatches() + { + $this->insertTestData(); + $result = $this->storage->findTriplet($this->userid, $this->validToken, $this->validPersistentToken); + $this->assertEquals(StorageInterface::TRIPLET_FOUND, $result); + } + + public function testFindTripletReturnsNotFoundIfNoDataMatches() + { + $result = $this->storage->findTriplet($this->userid, $this->validToken, $this->validPersistentToken); + $this->assertEquals(StorageInterface::TRIPLET_NOT_FOUND, $result); + } + + public function testFindTripletReturnsInvalidTokenIfTokenIsInvalid() + { + $this->insertTestData(); + $result = $this->storage->findTriplet($this->userid, $this->invalidToken, $this->validPersistentToken); + $this->assertEquals(StorageInterface::TRIPLET_INVALID, $result); + } + + public function testStoreTripletSavesValuesIntoDatabase() + { + $this->storage->storeTriplet($this->userid, $this->validToken, $this->validPersistentToken, strtotime($this->expire)); + $row = Persistence::select(['user_id', 'token', 'persistent_token', 'expires_at'])->first()->toArray(); + $this->assertEquals([$this->userid, $this->validDBToken, $this->validDBPersistentToken, $this->expire], array_values($row)); + } + + public function testCleanTripletRemovesEntryFromDatabase() + { + $this->insertTestData(); + $this->storage->cleanTriplet($this->userid, $this->validPersistentToken); + $this->assertEquals(0, Persistence::count()); + } + + public function testCleanAllTripletsRemovesAllEntriesWithMatchingCredentialsFromDatabase() + { + $this->insertTestData(); + $persistence = new Persistence([ + 'user_id' => $this->userid, + 'token' => 'dummy', + 'persistent_token' => 'dummy', + 'expires_at' => null + ]); + $persistence->save(); + $this->storage->cleanAllTriplets($this->userid); + $this->assertEquals(0, Persistence::count()); + } + + public function testReplaceTripletRemovesAndSavesEntryFromDatabase() + { + $this->insertTestData(); + $this->storage->replaceTriplet($this->userid, $this->invalidToken, $this->validPersistentToken, strtotime($this->expire)); + $this->assertEquals(1, Persistence::count()); + $row = Persistence::select(['user_id', 'token', 'persistent_token', 'expires_at'])->first()->toArray(); + $this->assertEquals([$this->userid, $this->invalidDBToken, $this->validDBPersistentToken, $this->expire], array_values($row)); + } + + public function testCleanExpiredTokens() + { + $this->insertTestData(); + $persistence = new Persistence([ + 'user_id' => $this->userid, + 'token' => 'dummy', + 'persistent_token' => 'dummy', + 'expires_at' => Carbon::now()->subHour(1) + ]); + $persistence->save(); + $this->assertEquals(2, Persistence::count()); + $this->storage->cleanExpiredTokens(Carbon::now()->timestamp); + $this->assertEquals(1, Persistence::count()); + } + + /** + * Insert test dataset + * @return Persistence + */ + protected function insertTestData() + { + $persistence = new Persistence([ + 'user_id' => $this->userid, + 'token' => $this->validDBToken, + 'persistent_token' => $this->validDBPersistentToken, + 'expires_at' => $this->expire + ]); + $persistence->save(); + + return $persistence; + } +} From fb0292f88f095f4526103cde4ff56b94aa347a9a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 12 Nov 2018 21:44:00 -0500 Subject: [PATCH 141/237] Add cache facade (Ref #838) --- CHANGELOG.md | 1 + app/sprinkles/core/src/Facades/Cache.php | 29 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 app/sprinkles/core/src/Facades/Cache.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 5edcffbd6..ff4d8a852 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `ControllerTestCase` special test case to help testing controllers - Improved overall test coverage and added coverage config to `phpunit.xml` - Added code style config (`.php_cs`) and instructions for PHP-CS-Fixer in Readme +- Add cache facade (Ref [#838](https://github.com/userfrosting/UserFrosting/issues/838)) ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle diff --git a/app/sprinkles/core/src/Facades/Cache.php b/app/sprinkles/core/src/Facades/Cache.php new file mode 100644 index 000000000..5f24d983b --- /dev/null +++ b/app/sprinkles/core/src/Facades/Cache.php @@ -0,0 +1,29 @@ + Date: Mon, 12 Nov 2018 22:02:27 -0500 Subject: [PATCH 142/237] Cache the `currentUser` (Implement #846) --- app/sprinkles/account/config/default.php | 14 +++++++++ .../src/Authenticate/Authenticator.php | 12 ++++++-- .../Models/Events/DeleteUserCacheEvent.php | 29 +++++++++++++++++++ .../account/src/Database/Models/User.php | 9 ++++++ 4 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 app/sprinkles/account/src/Database/Models/Events/DeleteUserCacheEvent.php diff --git a/app/sprinkles/account/config/default.php b/app/sprinkles/account/config/default.php index fb811fcf1..24cc64644 100644 --- a/app/sprinkles/account/config/default.php +++ b/app/sprinkles/account/config/default.php @@ -10,6 +10,20 @@ * Account configuration file for UserFrosting. */ return [ + /* + * ---------------------------------------------------------------------- + * User Cache Config + * ---------------------------------------------------------------------- + * Cache current user info for a given time to speed up process. + * Set to zero to disable. + */ + 'cache' => [ + 'user' => [ + 'delay' => 120, // In minutes + 'key' => '_user', + ], + ], + /* * ---------------------------------------------------------------------- * AuthorizationManager Debug diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index 2383a4e04..c00c91f2f 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -92,7 +92,7 @@ class Authenticator * @param Session $session The session wrapper object that will store the user's id. * @param Config $config Config object that contains authentication settings. * @param Cache $cache Cache service instance - * @param Capsule $capsule Database service instance + * @param Capsule $db Database service instance */ public function __construct(ClassMapper $classMapper, Session $session, Config $config, Cache $cache, Capsule $db) { @@ -255,6 +255,9 @@ public function logout($complete = false) if ($currentUser) { $currentUser->onLogout(); } + + // Delete user object cache + $this->cache->forget($this->config['cache.user.key'] . $currentUserId); } $this->user = null; @@ -403,7 +406,12 @@ protected function validateRememberMeCookie() protected function validateUserAccount($userId) { if ($userId) { - $user = $this->classMapper->staticMethod('user', 'find', (int) $userId); + + // Load user from db, cache the result + $key = $this->config['cache.user.key'] . $userId; + $user = $this->cache->remember($key, $this->config['cache.user.delay'], function () use ($userId) { + return $this->classMapper->staticMethod('user', 'find', (int) $userId); + }); // If the user doesn't exist any more, throw an exception. if (!$user) { diff --git a/app/sprinkles/account/src/Database/Models/Events/DeleteUserCacheEvent.php b/app/sprinkles/account/src/Database/Models/Events/DeleteUserCacheEvent.php new file mode 100644 index 000000000..4e397f019 --- /dev/null +++ b/app/sprinkles/account/src/Database/Models/Events/DeleteUserCacheEvent.php @@ -0,0 +1,29 @@ +id); + } +} diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index bb98db7fe..5afd7d7e8 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -92,6 +92,15 @@ class User extends Model implements UserInterface 'full_name' ]; + /** + * Events used to handle the user object cache on update and deletion + * @var array + */ + protected $events = [ + 'saved' => Events\DeleteUserCacheEvent::class, + 'deleted' => Events\DeleteUserCacheEvent::class + ]; + /** * Cached dictionary of permissions for the user. * From 794ec38820489f49821cf32a01341f85445ed601 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 13 Nov 2018 22:19:18 -0500 Subject: [PATCH 143/237] Updated phpunit.xml --- phpunit.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/phpunit.xml b/phpunit.xml index 942583c38..192eb2cd3 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -13,6 +13,8 @@ app/tests/Unit app/sprinkles/*/tests/Unit + + app/sprinkles/*/tests/Integration
From 079142f8027f8dda7e1fa80e05961560e3db6f1d Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 17 Nov 2018 20:38:35 -0500 Subject: [PATCH 144/237] Uncomment foreign keys in core migrations (#833) --- CHANGELOG.md | 3 + .../Migrations/v420/AddingForeignKeys.php | 82 +++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 app/sprinkles/account/src/Database/Migrations/v420/AddingForeignKeys.php diff --git a/CHANGELOG.md b/CHANGELOG.md index ff4d8a852..ef1a951a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Rewritten the `locator` service so it's better suited for sprinkle system ([#853](https://github.com/userfrosting/UserFrosting/issues/853)) - `dev` environment changed to `debug` ([#653](https://github.com/userfrosting/UserFrosting/issues/653)) - Changed deprecations to `warning`, and suppressed them in tests +- Uncomment foreign keys in core migrations ([#833]) ### Fix - Sprinkle without a `template/` folder won't cause error anymore @@ -640,3 +641,5 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x - Added 404 error page - Standardized JSON interface for backend scripts - Front-end should now be able to catch virtually any backend error and take an appropriate action (instead of white screen of death) + +[#833]: https://github.com/userfrosting/UserFrosting/issues/833 diff --git a/app/sprinkles/account/src/Database/Migrations/v420/AddingForeignKeys.php b/app/sprinkles/account/src/Database/Migrations/v420/AddingForeignKeys.php new file mode 100644 index 000000000..72c6df473 --- /dev/null +++ b/app/sprinkles/account/src/Database/Migrations/v420/AddingForeignKeys.php @@ -0,0 +1,82 @@ + [ + 'user_id' => ['id', 'users'] + ], + 'password_resets' => [ + 'user_id' => ['id', 'users'] + ], + 'permission_roles' => [ + 'permission_id' => ['id', 'permissions'], + 'role_id' => ['id', 'roles'] + ], + 'persistences' => [ + 'user_id' => ['id', 'users'] + ], + 'role_users' => [ + 'user_id' => ['id', 'users'], + 'role_id' => ['id', 'roles'] + ], + 'users' => [ + 'group_id' => ['id', 'groups'], + 'last_activity_id' => ['id', 'activities'] + ], + 'verifications' => [ + 'user_id' => ['id', 'users'], + ], + ]; + + /** + * {@inheritdoc} + */ + public function up() + { + foreach ($this->tables as $tableName => $keys) { + if ($this->schema->hasTable($tableName)) { + $this->schema->table($tableName, function (Blueprint $table) use ($keys) { + foreach ($keys as $key => $data) { + $table->foreign($key)->references($data[0])->on($data[1]); + } + }); + } + } + } + + /** + * {@inheritdoc} + */ + public function down() + { + foreach ($this->tables as $tableName => $keys) { + if ($this->schema->hasTable($tableName)) { + $this->schema->table($tableName, function (Blueprint $table) use ($keys) { + foreach ($keys as $key => $data) { + $table->dropForeign([$key]); + } + }); + } + } + } +} From 084381f9363636bacde851afade4cec801fe62d3 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 17 Nov 2018 22:50:07 -0500 Subject: [PATCH 145/237] Move default groups, roles & permissions to seeds. --- .../Database/Migrations/v400/GroupsTable.php | 27 +- .../Migrations/v400/PermissionsTable.php | 190 +------------ .../Database/Migrations/v400/RolesTable.php | 25 +- .../src/Database/Seeds/DefaultGroups.php | 60 +++++ .../src/Database/Seeds/DefaultPermissions.php | 252 ++++++++++++++++++ .../src/Database/Seeds/DefaultRoles.php | 57 ++++ app/sprinkles/core/src/Bakery/SeedCommand.php | 4 +- .../core/src/Bakery/SeedListCommand.php | 4 +- .../core/src/Database/Seeder/Seeder.php | 17 +- app/sprinkles/core/src/Facades/Seeder.php | 29 ++ .../src/ServicesProvider/ServicesProvider.php | 10 + 11 files changed, 430 insertions(+), 245 deletions(-) create mode 100644 app/sprinkles/account/src/Database/Seeds/DefaultGroups.php create mode 100644 app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php create mode 100644 app/sprinkles/account/src/Database/Seeds/DefaultRoles.php create mode 100644 app/sprinkles/core/src/Facades/Seeder.php diff --git a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php index 4b6f37daa..95f8c330c 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php @@ -9,8 +9,8 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use UserFrosting\Sprinkle\Account\Database\Models\Group; use UserFrosting\Sprinkle\Core\Database\Migration; +use UserFrosting\Sprinkle\Core\Facades\Seeder; /** * Groups table migration @@ -44,30 +44,7 @@ public function up() }); // Add default groups - $groups = [ - 'terran' => new Group([ - 'slug' => 'terran', - 'name' => 'Terran', - 'description' => 'The terrans are a young species with psionic potential. The terrans of the Koprulu sector descend from the survivors of a disastrous 23rd century colonization mission from Earth.', - 'icon' => 'sc sc-terran' - ]), - 'zerg' => new Group([ - 'slug' => 'zerg', - 'name' => 'Zerg', - 'description' => 'Dedicated to the pursuit of genetic perfection, the zerg relentlessly hunt down and assimilate advanced species across the galaxy, incorporating useful genetic code into their own.', - 'icon' => 'sc sc-zerg' - ]), - 'protoss' => new Group([ - 'slug' => 'protoss', - 'name' => 'Protoss', - 'description' => 'The protoss, a.k.a. the Firstborn, are a sapient humanoid race native to Aiur. Their advanced technology complements and enhances their psionic mastery.', - 'icon' => 'sc sc-protoss' - ]) - ]; - - foreach ($groups as $slug => $group) { - $group->save(); - } + Seeder::execute('DefaultGroups'); } } diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php index 470a7ad20..0c65ccd15 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php @@ -10,8 +10,8 @@ use Illuminate\Database\Schema\Blueprint; use UserFrosting\Sprinkle\Account\Database\Models\Permission; -use UserFrosting\Sprinkle\Account\Database\Models\Role; use UserFrosting\Sprinkle\Core\Database\Migration; +use UserFrosting\Sprinkle\Core\Facades\Seeder; /** * Permissions table migration @@ -54,193 +54,7 @@ public function up() // Skip this if table is not empty if (Permission::count() == 0) { - $defaultRoleIds = [ - 'user' => Role::where('slug', 'user')->first()->id, - 'group-admin' => Role::where('slug', 'group-admin')->first()->id, - 'site-admin' => Role::where('slug', 'site-admin')->first()->id - ]; - - // Add default permissions - $permissions = [ - 'create_group' => new Permission([ - 'slug' => 'create_group', - 'name' => 'Create group', - 'conditions' => 'always()', - 'description' => 'Create a new group.' - ]), - 'create_user' => new Permission([ - 'slug' => 'create_user', - 'name' => 'Create user', - 'conditions' => 'always()', - 'description' => 'Create a new user in your own group and assign default roles.' - ]), - 'create_user_field' => new Permission([ - 'slug' => 'create_user_field', - 'name' => 'Set new user group', - 'conditions' => "subset(fields,['group'])", - 'description' => 'Set the group when creating a new user.' - ]), - 'delete_group' => new Permission([ - 'slug' => 'delete_group', - 'name' => 'Delete group', - 'conditions' => 'always()', - 'description' => 'Delete a group.' - ]), - 'delete_user' => new Permission([ - 'slug' => 'delete_user', - 'name' => 'Delete user', - 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && !is_master(user.id)", - 'description' => 'Delete users who are not Site Administrators.' - ]), - 'update_account_settings' => new Permission([ - 'slug' => 'update_account_settings', - 'name' => 'Edit user', - 'conditions' => 'always()', - 'description' => 'Edit your own account settings.' - ]), - 'update_group_field' => new Permission([ - 'slug' => 'update_group_field', - 'name' => 'Edit group', - 'conditions' => 'always()', - 'description' => 'Edit basic properties of any group.' - ]), - 'update_user_field' => new Permission([ - 'slug' => 'update_user_field', - 'name' => 'Edit user', - 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && subset(fields,['name','email','locale','group','flag_enabled','flag_verified','password'])", - 'description' => 'Edit users who are not Site Administrators.' - ]), - 'update_user_field_group' => new Permission([ - 'slug' => 'update_user_field', - 'name' => 'Edit group user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && subset(fields,['name','email','locale','flag_enabled','flag_verified','password'])", - 'description' => 'Edit users in your own group who are not Site or Group Administrators, except yourself.' - ]), - 'uri_account_settings' => new Permission([ - 'slug' => 'uri_account_settings', - 'name' => 'Account settings page', - 'conditions' => 'always()', - 'description' => 'View the account settings page.' - ]), - 'uri_activities' => new Permission([ - 'slug' => 'uri_activities', - 'name' => 'Activity monitor', - 'conditions' => 'always()', - 'description' => 'View a list of all activities for all users.' - ]), - 'uri_dashboard' => new Permission([ - 'slug' => 'uri_dashboard', - 'name' => 'Admin dashboard', - 'conditions' => 'always()', - 'description' => 'View the administrative dashboard.' - ]), - 'uri_group' => new Permission([ - 'slug' => 'uri_group', - 'name' => 'View group', - 'conditions' => 'always()', - 'description' => 'View the group page of any group.' - ]), - 'uri_group_own' => new Permission([ - 'slug' => 'uri_group', - 'name' => 'View own group', - 'conditions' => 'equals_num(self.group_id,group.id)', - 'description' => 'View the group page of your own group.' - ]), - 'uri_groups' => new Permission([ - 'slug' => 'uri_groups', - 'name' => 'Group management page', - 'conditions' => 'always()', - 'description' => 'View a page containing a list of groups.' - ]), - 'uri_user' => new Permission([ - 'slug' => 'uri_user', - 'name' => 'View user', - 'conditions' => 'always()', - 'description' => 'View the user page of any user.' - ]), - 'uri_user_in_group' => new Permission([ - 'slug' => 'uri_user', - 'name' => 'View user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id))", - 'description' => 'View the user page of any user in your group, except the master user and Site and Group Administrators (except yourself).' - ]), - 'uri_users' => new Permission([ - 'slug' => 'uri_users', - 'name' => 'User management page', - 'conditions' => 'always()', - 'description' => 'View a page containing a table of users.' - ]), - 'view_group_field' => new Permission([ - 'slug' => 'view_group_field', - 'name' => 'View group', - 'conditions' => "in(property,['name','icon','slug','description','users'])", - 'description' => 'View certain properties of any group.' - ]), - 'view_group_field_own' => new Permission([ - 'slug' => 'view_group_field', - 'name' => 'View group', - 'conditions' => "equals_num(self.group_id,group.id) && in(property,['name','icon','slug','description','users'])", - 'description' => 'View certain properties of your own group.' - ]), - 'view_user_field' => new Permission([ - 'slug' => 'view_user_field', - 'name' => 'View user', - 'conditions' => "in(property,['user_name','name','email','locale','theme','roles','group','activities'])", - 'description' => 'View certain properties of any user.' - ]), - 'view_user_field_group' => new Permission([ - 'slug' => 'view_user_field', - 'name' => 'View user', - 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && in(property,['user_name','name','email','locale','roles','group','activities'])", - 'description' => 'View certain properties of any user in your own group, except the master user and Site and Group Administrators (except yourself).' - ]) - ]; - - foreach ($permissions as $slug => $permission) { - $permission->save(); - } - - // Add default mappings to permissions - $roleUser = Role::where('slug', 'user')->first(); - if ($roleUser) { - $roleUser->permissions()->sync([ - $permissions['update_account_settings']->id, - $permissions['uri_account_settings']->id, - $permissions['uri_dashboard']->id - ]); - } - - $roleSiteAdmin = Role::where('slug', 'site-admin')->first(); - if ($roleSiteAdmin) { - $roleSiteAdmin->permissions()->sync([ - $permissions['create_group']->id, - $permissions['create_user']->id, - $permissions['create_user_field']->id, - $permissions['delete_group']->id, - $permissions['delete_user']->id, - $permissions['update_user_field']->id, - $permissions['update_group_field']->id, - $permissions['uri_activities']->id, - $permissions['uri_group']->id, - $permissions['uri_groups']->id, - $permissions['uri_user']->id, - $permissions['uri_users']->id, - $permissions['view_group_field']->id, - $permissions['view_user_field']->id - ]); - } - - $roleGroupAdmin = Role::where('slug', 'group-admin')->first(); - if ($roleGroupAdmin) { - $roleGroupAdmin->permissions()->sync([ - $permissions['create_user']->id, - $permissions['update_user_field_group']->id, - $permissions['uri_group_own']->id, - $permissions['uri_user_in_group']->id, - $permissions['view_group_field_own']->id, - $permissions['view_user_field_group']->id - ]); - } + Seeder::execute('DefaultPermissions'); } } diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php index 73bb04f62..cbc3132f7 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php @@ -9,12 +9,12 @@ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; use Illuminate\Database\Schema\Blueprint; -use UserFrosting\Sprinkle\Account\Database\Models\Role; use UserFrosting\Sprinkle\Core\Database\Migration; /** * Roles table migration * Roles replace "groups" in UF 0.3.x. Users acquire permissions through roles. + * N.B.: Default roles will be added in `DefaultPermissions` seed * Version 4.0.0 * * See https://laravel.com/docs/5.4/migrations#tables @@ -41,29 +41,6 @@ public function up() $table->unique('slug'); $table->index('slug'); }); - - // Add default roles - $roles = [ - 'user' => new Role([ - 'slug' => 'user', - 'name' => 'User', - 'description' => 'This role provides basic user functionality.' - ]), - 'site-admin' => new Role([ - 'slug' => 'site-admin', - 'name' => 'Site Administrator', - 'description' => 'This role is meant for "site administrators", who can basically do anything except create, edit, or delete other administrators.' - ]), - 'group-admin' => new Role([ - 'slug' => 'group-admin', - 'name' => 'Group Administrator', - 'description' => 'This role is meant for "group administrators", who can basically do anything with users in their own group, except other administrators of that group.' - ]) - ]; - - foreach ($roles as $slug => $role) { - $role->save(); - } } } diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php b/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php new file mode 100644 index 000000000..d538e7faa --- /dev/null +++ b/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php @@ -0,0 +1,60 @@ +getGroups(); + + foreach ($groups as $group) { + // Don't save if already exist + if (Group::where('slug', $group->slug)->first() == null) { + $group->save(); + } + } + } + + /** + * @return array Groups to seed + */ + protected function getGroups() + { + return [ + new Group([ + 'slug' => 'terran', + 'name' => 'Terran', + 'description' => 'The terrans are a young species with psionic potential. The terrans of the Koprulu sector descend from the survivors of a disastrous 23rd century colonization mission from Earth.', + 'icon' => 'sc sc-terran' + ]), + new Group([ + 'slug' => 'zerg', + 'name' => 'Zerg', + 'description' => 'Dedicated to the pursuit of genetic perfection, the zerg relentlessly hunt down and assimilate advanced species across the galaxy, incorporating useful genetic code into their own.', + 'icon' => 'sc sc-zerg' + ]), + new Group([ + 'slug' => 'protoss', + 'name' => 'Protoss', + 'description' => 'The protoss, a.k.a. the Firstborn, are a sapient humanoid race native to Aiur. Their advanced technology complements and enhances their psionic mastery.', + 'icon' => 'sc sc-protoss' + ]) + ]; + } +} diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php b/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php new file mode 100644 index 000000000..ac6c81308 --- /dev/null +++ b/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php @@ -0,0 +1,252 @@ +getPermissions(); + $this->savePermissions($permissions); + + // Add default mappings to permissions + $this->syncPermissionsRole($permissions); + } + + /** + * @return array Permissions to seed + */ + protected function getPermissions() + { + $defaultRoleIds = [ + 'user' => Role::where('slug', 'user')->first()->id, + 'group-admin' => Role::where('slug', 'group-admin')->first()->id, + 'site-admin' => Role::where('slug', 'site-admin')->first()->id + ]; + + return [ + 'create_group' => new Permission([ + 'slug' => 'create_group', + 'name' => 'Create group', + 'conditions' => 'always()', + 'description' => 'Create a new group.' + ]), + 'create_user' => new Permission([ + 'slug' => 'create_user', + 'name' => 'Create user', + 'conditions' => 'always()', + 'description' => 'Create a new user in your own group and assign default roles.' + ]), + 'create_user_field' => new Permission([ + 'slug' => 'create_user_field', + 'name' => 'Set new user group', + 'conditions' => "subset(fields,['group'])", + 'description' => 'Set the group when creating a new user.' + ]), + 'delete_group' => new Permission([ + 'slug' => 'delete_group', + 'name' => 'Delete group', + 'conditions' => 'always()', + 'description' => 'Delete a group.' + ]), + 'delete_user' => new Permission([ + 'slug' => 'delete_user', + 'name' => 'Delete user', + 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && !is_master(user.id)", + 'description' => 'Delete users who are not Site Administrators.' + ]), + 'update_account_settings' => new Permission([ + 'slug' => 'update_account_settings', + 'name' => 'Edit user', + 'conditions' => 'always()', + 'description' => 'Edit your own account settings.' + ]), + 'update_group_field' => new Permission([ + 'slug' => 'update_group_field', + 'name' => 'Edit group', + 'conditions' => 'always()', + 'description' => 'Edit basic properties of any group.' + ]), + 'update_user_field' => new Permission([ + 'slug' => 'update_user_field', + 'name' => 'Edit user', + 'conditions' => "!has_role(user.id,{$defaultRoleIds['site-admin']}) && subset(fields,['name','email','locale','group','flag_enabled','flag_verified','password'])", + 'description' => 'Edit users who are not Site Administrators.' + ]), + 'update_user_field_group' => new Permission([ + 'slug' => 'update_user_field', + 'name' => 'Edit group user', + 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && subset(fields,['name','email','locale','flag_enabled','flag_verified','password'])", + 'description' => 'Edit users in your own group who are not Site or Group Administrators, except yourself.' + ]), + 'uri_account_settings' => new Permission([ + 'slug' => 'uri_account_settings', + 'name' => 'Account settings page', + 'conditions' => 'always()', + 'description' => 'View the account settings page.' + ]), + 'uri_activities' => new Permission([ + 'slug' => 'uri_activities', + 'name' => 'Activity monitor', + 'conditions' => 'always()', + 'description' => 'View a list of all activities for all users.' + ]), + 'uri_dashboard' => new Permission([ + 'slug' => 'uri_dashboard', + 'name' => 'Admin dashboard', + 'conditions' => 'always()', + 'description' => 'View the administrative dashboard.' + ]), + 'uri_group' => new Permission([ + 'slug' => 'uri_group', + 'name' => 'View group', + 'conditions' => 'always()', + 'description' => 'View the group page of any group.' + ]), + 'uri_group_own' => new Permission([ + 'slug' => 'uri_group', + 'name' => 'View own group', + 'conditions' => 'equals_num(self.group_id,group.id)', + 'description' => 'View the group page of your own group.' + ]), + 'uri_groups' => new Permission([ + 'slug' => 'uri_groups', + 'name' => 'Group management page', + 'conditions' => 'always()', + 'description' => 'View a page containing a list of groups.' + ]), + 'uri_user' => new Permission([ + 'slug' => 'uri_user', + 'name' => 'View user', + 'conditions' => 'always()', + 'description' => 'View the user page of any user.' + ]), + 'uri_user_in_group' => new Permission([ + 'slug' => 'uri_user', + 'name' => 'View user', + 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id))", + 'description' => 'View the user page of any user in your group, except the master user and Site and Group Administrators (except yourself).' + ]), + 'uri_users' => new Permission([ + 'slug' => 'uri_users', + 'name' => 'User management page', + 'conditions' => 'always()', + 'description' => 'View a page containing a table of users.' + ]), + 'view_group_field' => new Permission([ + 'slug' => 'view_group_field', + 'name' => 'View group', + 'conditions' => "in(property,['name','icon','slug','description','users'])", + 'description' => 'View certain properties of any group.' + ]), + 'view_group_field_own' => new Permission([ + 'slug' => 'view_group_field', + 'name' => 'View group', + 'conditions' => "equals_num(self.group_id,group.id) && in(property,['name','icon','slug','description','users'])", + 'description' => 'View certain properties of your own group.' + ]), + 'view_user_field' => new Permission([ + 'slug' => 'view_user_field', + 'name' => 'View user', + 'conditions' => "in(property,['user_name','name','email','locale','theme','roles','group','activities'])", + 'description' => 'View certain properties of any user.' + ]), + 'view_user_field_group' => new Permission([ + 'slug' => 'view_user_field', + 'name' => 'View user', + 'conditions' => "equals_num(self.group_id,user.group_id) && !is_master(user.id) && !has_role(user.id,{$defaultRoleIds['site-admin']}) && (!has_role(user.id,{$defaultRoleIds['group-admin']}) || equals_num(self.id,user.id)) && in(property,['user_name','name','email','locale','roles','group','activities'])", + 'description' => 'View certain properties of any user in your own group, except the master user and Site and Group Administrators (except yourself).' + ]) + ]; + } + + /** + * Save permissions + * @param array $permissions + */ + protected function savePermissions(array $permissions) + { + foreach ($permissions as $slug => $permission) { + + // Trying to find if the permission already exist + $existingPermission = Permission::where(['slug' => $permission->slug, 'conditions' => $permission->conditions])->first(); + + // Don't save if already exist, use existing permission reference + // otherwise to re-sync permissions and roles + if ($existingPermission == null) { + $permission->save(); + } else { + $permissions[$slug] = $existingPermission; + } + } + } + + /** + * Sync permissions with default roles + * @param array $permissions + */ + protected function syncPermissionsRole(array $permissions) + { + $roleUser = Role::where('slug', 'user')->first(); + if ($roleUser) { + $roleUser->permissions()->sync([ + $permissions['update_account_settings']->id, + $permissions['uri_account_settings']->id, + $permissions['uri_dashboard']->id + ]); + } + + $roleSiteAdmin = Role::where('slug', 'site-admin')->first(); + if ($roleSiteAdmin) { + $roleSiteAdmin->permissions()->sync([ + $permissions['create_group']->id, + $permissions['create_user']->id, + $permissions['create_user_field']->id, + $permissions['delete_group']->id, + $permissions['delete_user']->id, + $permissions['update_user_field']->id, + $permissions['update_group_field']->id, + $permissions['uri_activities']->id, + $permissions['uri_group']->id, + $permissions['uri_groups']->id, + $permissions['uri_user']->id, + $permissions['uri_users']->id, + $permissions['view_group_field']->id, + $permissions['view_user_field']->id + ]); + } + + $roleGroupAdmin = Role::where('slug', 'group-admin')->first(); + if ($roleGroupAdmin) { + $roleGroupAdmin->permissions()->sync([ + $permissions['create_user']->id, + $permissions['update_user_field_group']->id, + $permissions['uri_group_own']->id, + $permissions['uri_user_in_group']->id, + $permissions['view_group_field_own']->id, + $permissions['view_user_field_group']->id + ]); + } + } +} diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php b/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php new file mode 100644 index 000000000..9762be974 --- /dev/null +++ b/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php @@ -0,0 +1,57 @@ +getRoles(); + + foreach ($roles as $role) { + // Don't save if already exist + if (Role::where('slug', $role->slug)->first() == null) { + $role->save(); + } + } + } + + /** + * @return array Roles to seed + */ + protected function getRoles() + { + return [ + new Role([ + 'slug' => 'user', + 'name' => 'User', + 'description' => 'This role provides basic user functionality.' + ]), + new Role([ + 'slug' => 'site-admin', + 'name' => 'Site Administrator', + 'description' => 'This role is meant for "site administrators", who can basically do anything except create, edit, or delete other administrators.' + ]), + new Role([ + 'slug' => 'group-admin', + 'name' => 'Group Administrator', + 'description' => 'This role is meant for "group administrators", who can basically do anything with users in their own group, except other administrators of that group.' + ]) + ]; + } +} diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index 101a1a6a5..6a38339e7 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -51,7 +51,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->title("UserFrosting's Seeder"); // Prepare seed locator - $this->seeder = new Seeder($this->ci); + $this->seeder = $this->ci->seeder; // Get options $classes = $input->getArgument('class'); @@ -71,7 +71,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } // Display the class we are going to use as info - $this->io->writeln('Seeding class `'.get_class($seedClass).'`'); + $this->io->writeln('Seeding database using class `'.get_class($seedClass).'`'); // Add seed class to list $seeds[] = $seedClass; diff --git a/app/sprinkles/core/src/Bakery/SeedListCommand.php b/app/sprinkles/core/src/Bakery/SeedListCommand.php index a86d76bbf..28aa9119c 100644 --- a/app/sprinkles/core/src/Bakery/SeedListCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedListCommand.php @@ -10,7 +10,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; -use UserFrosting\Sprinkle\Core\Database\Seeder\Seeder; use UserFrosting\System\Bakery\BaseCommand; /** @@ -37,8 +36,7 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $this->io->title('Database Seeds List'); - $seeder = new Seeder($this->ci); - $seeds = $seeder->getSeeds(); + $seeds = $this->ci->seeder->getSeeds(); $this->io->table(['Name', 'Namespace', 'Sprinkle'], $seeds); } } diff --git a/app/sprinkles/core/src/Database/Seeder/Seeder.php b/app/sprinkles/core/src/Database/Seeder/Seeder.php index 8a14fb9a8..e494e9e6c 100644 --- a/app/sprinkles/core/src/Database/Seeder/Seeder.php +++ b/app/sprinkles/core/src/Database/Seeder/Seeder.php @@ -10,7 +10,7 @@ use Interop\Container\ContainerInterface; use Illuminate\Support\Str; -use UserFrosting\UniformResourceLocator\Resource; +use UserFrosting\UniformResourceLocator\Resource as ResourceInstance; /** * Seeder Class @@ -111,6 +111,17 @@ public function executeSeed(SeedInterface $seed) $seed->run(); } + /** + * Execute a seed based on it's name + * + * @param string $seedName + */ + public function execute($seedName) + { + $seed = $this->getSeedClass($seedName); + $this->executeSeed($seed); + } + /** * Process seeder Resource into info * @@ -130,10 +141,10 @@ protected function loadSeeders(array $seedFiles) /** * Return an array of seed details inclusing the classname and the sprinkle name * - * @param resource $file The seed file + * @param ResourceInstance $file The seed file * @return array The details about a seed file [name, class, sprinkle] */ - protected function getSeedDetails(Resource $file) + protected function getSeedDetails(ResourceInstance $file) { // Format the sprinkle name for the namespace $sprinkleName = $file->getLocation()->getName(); diff --git a/app/sprinkles/core/src/Facades/Seeder.php b/app/sprinkles/core/src/Facades/Seeder.php new file mode 100644 index 000000000..2c3031266 --- /dev/null +++ b/app/sprinkles/core/src/Facades/Seeder.php @@ -0,0 +1,29 @@ +setCacheFile($routerCacheFile); }; + /** + * Return an instance of the database seeder + * + * @return \UserFrosting\Sprinkle\Core\Database\Seeder\Seeder + */ + $container['seeder'] = function ($c) { + return new Seeder($c); + }; + /** * Start the PHP session, with the name and parameters specified in the configuration file. * From 990d05c6ce2ce06a72f9eec88e6e48a75cc9a84f Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 18 Nov 2018 20:37:14 -0500 Subject: [PATCH 146/237] Fix PDOStorageTest --- .../account/tests/Unit/PDOStorageTest.php | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/app/sprinkles/account/tests/Unit/PDOStorageTest.php b/app/sprinkles/account/tests/Unit/PDOStorageTest.php index ae33aefff..be65bfc3f 100644 --- a/app/sprinkles/account/tests/Unit/PDOStorageTest.php +++ b/app/sprinkles/account/tests/Unit/PDOStorageTest.php @@ -12,6 +12,7 @@ use Carbon\Carbon; use UserFrosting\Sprinkle\Account\Database\Models\Persistence; use UserFrosting\Sprinkle\Account\Rememberme\PDOStorage; +use UserFrosting\Sprinkle\Account\Tests\withTestUser; use UserFrosting\Sprinkle\Core\Tests\TestDatabase; use UserFrosting\Sprinkle\Core\Tests\RefreshDatabase; use UserFrosting\Tests\TestCase; @@ -23,13 +24,18 @@ class PDOStorageTest extends TestCase { use TestDatabase; use RefreshDatabase; + use withTestUser; /** * @var PDOStorage */ protected $storage; - protected $userid = 1; + /** + * @var \UserFrosting\Sprinkle\Account\Database\Models\Interfaces\UserInterface + */ + protected $testUser; + protected $validToken = '78b1e6d775cec5260001af137a79dbd5'; protected $validPersistentToken = '0e0530c1430da76495955eb06eb99d95'; protected $invalidToken = '7ae7c7caa0c7b880cb247bb281d527de'; @@ -49,40 +55,43 @@ protected function setUp() $this->setupTestDatabase(); $this->refreshDatabase(); + // Create a test user + $this->testUser = $this->createTestUser(); + $this->storage = new PDOStorage($this->ci->db); } public function testFindTripletReturnsFoundIfDataMatches() { $this->insertTestData(); - $result = $this->storage->findTriplet($this->userid, $this->validToken, $this->validPersistentToken); + $result = $this->storage->findTriplet($this->testUser->id, $this->validToken, $this->validPersistentToken); $this->assertEquals(StorageInterface::TRIPLET_FOUND, $result); } public function testFindTripletReturnsNotFoundIfNoDataMatches() { - $result = $this->storage->findTriplet($this->userid, $this->validToken, $this->validPersistentToken); + $result = $this->storage->findTriplet($this->testUser->id, $this->validToken, $this->validPersistentToken); $this->assertEquals(StorageInterface::TRIPLET_NOT_FOUND, $result); } public function testFindTripletReturnsInvalidTokenIfTokenIsInvalid() { $this->insertTestData(); - $result = $this->storage->findTriplet($this->userid, $this->invalidToken, $this->validPersistentToken); + $result = $this->storage->findTriplet($this->testUser->id, $this->invalidToken, $this->validPersistentToken); $this->assertEquals(StorageInterface::TRIPLET_INVALID, $result); } public function testStoreTripletSavesValuesIntoDatabase() { - $this->storage->storeTriplet($this->userid, $this->validToken, $this->validPersistentToken, strtotime($this->expire)); + $this->storage->storeTriplet($this->testUser->id, $this->validToken, $this->validPersistentToken, strtotime($this->expire)); $row = Persistence::select(['user_id', 'token', 'persistent_token', 'expires_at'])->first()->toArray(); - $this->assertEquals([$this->userid, $this->validDBToken, $this->validDBPersistentToken, $this->expire], array_values($row)); + $this->assertEquals([$this->testUser->id, $this->validDBToken, $this->validDBPersistentToken, $this->expire], array_values($row)); } public function testCleanTripletRemovesEntryFromDatabase() { $this->insertTestData(); - $this->storage->cleanTriplet($this->userid, $this->validPersistentToken); + $this->storage->cleanTriplet($this->testUser->id, $this->validPersistentToken); $this->assertEquals(0, Persistence::count()); } @@ -90,30 +99,30 @@ public function testCleanAllTripletsRemovesAllEntriesWithMatchingCredentialsFrom { $this->insertTestData(); $persistence = new Persistence([ - 'user_id' => $this->userid, + 'user_id' => $this->testUser->id, 'token' => 'dummy', 'persistent_token' => 'dummy', 'expires_at' => null ]); $persistence->save(); - $this->storage->cleanAllTriplets($this->userid); + $this->storage->cleanAllTriplets($this->testUser->id); $this->assertEquals(0, Persistence::count()); } public function testReplaceTripletRemovesAndSavesEntryFromDatabase() { $this->insertTestData(); - $this->storage->replaceTriplet($this->userid, $this->invalidToken, $this->validPersistentToken, strtotime($this->expire)); + $this->storage->replaceTriplet($this->testUser->id, $this->invalidToken, $this->validPersistentToken, strtotime($this->expire)); $this->assertEquals(1, Persistence::count()); $row = Persistence::select(['user_id', 'token', 'persistent_token', 'expires_at'])->first()->toArray(); - $this->assertEquals([$this->userid, $this->invalidDBToken, $this->validDBPersistentToken, $this->expire], array_values($row)); + $this->assertEquals([$this->testUser->id, $this->invalidDBToken, $this->validDBPersistentToken, $this->expire], array_values($row)); } public function testCleanExpiredTokens() { $this->insertTestData(); $persistence = new Persistence([ - 'user_id' => $this->userid, + 'user_id' => $this->testUser->id, 'token' => 'dummy', 'persistent_token' => 'dummy', 'expires_at' => Carbon::now()->subHour(1) @@ -131,7 +140,7 @@ public function testCleanExpiredTokens() protected function insertTestData() { $persistence = new Persistence([ - 'user_id' => $this->userid, + 'user_id' => $this->testUser->id, 'token' => $this->validDBToken, 'persistent_token' => $this->validDBPersistentToken, 'expires_at' => $this->expire From bcad48ba96d4144ae07170ade638ff5df546f8f2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 18 Nov 2018 21:27:55 -0500 Subject: [PATCH 147/237] Update Changelog --- CHANGELOG.md | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef1a951a0..540deb5f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added -- Use locale requested by browser when possible for guests ([#718](https://github.com/userfrosting/UserFrosting/issues/718)) -- Add locale drop down to registration page, with the currently applied locale selected ([#718](https://github.com/userfrosting/UserFrosting/issues/718)) +- Use locale requested by browser when possible for guests ([#718]) +- Add locale drop down to registration page, with the currently applied locale selected ([#718]) - Integrated improvements from [v4.0.25-Alpha](#v4025-alpha) - Added `database` option for `migrate` and `migrate:*` Bakery commands - New `isProduction` method for Bakery command to test if app is in production mode @@ -18,35 +18,36 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `RefreshDatabase` test Trait to use a fresh database for a test - Added `TestDatabase` test Trait to use the in memory database for a test - Implement `withRaw`, `withSum`, `withAvg`, `withMin`, `withMax` (see https://github.com/laravel/framework/pull/16815) -- Include Vagrant integration directly inside UF ([#829](https://github.com/userfrosting/UserFrosting/issues/829)) -- Added arguments to the `create-admin` and `setup` Bakery commands so it can be used in a non-interactive way ([#808](https://github.com/userfrosting/UserFrosting/issues/808)) +- Include Vagrant integration directly inside UF ([#829]) +- Added arguments to the `create-admin` and `setup` Bakery commands so it can be used in a non-interactive way ([#808]) - Added tests for migrator and it's components - Added tests for `migrate` Bakery command and sub-commands -- Added new `filesystem` service ([#869](https://github.com/userfrosting/UserFrosting/issues/869)) +- Added new `filesystem` service ([#869]) - Added new `Seeder` and `seed` Bakery command - Added `withTestUser` trait for helper methods when running tests requiring a user - Added `ControllerTestCase` special test case to help testing controllers - Improved overall test coverage and added coverage config to `phpunit.xml` - Added code style config (`.php_cs`) and instructions for PHP-CS-Fixer in Readme -- Add cache facade (Ref [#838](https://github.com/userfrosting/UserFrosting/issues/838)) +- Add cache facade (Ref [#838]) ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle -- Re-written the migrator. It is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider ([#795](https://github.com/userfrosting/UserFrosting/issues/795)) +- Re-written the migrator. It is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider ([#795]) - Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace -- Move User registration out of the `AccountController` ([#793](https://github.com/userfrosting/UserFrosting/issues/793)) +- Move User registration out of the `AccountController` ([#793]) - Temporarily undeprecate `AssetLoader` until the new asset system can be refactored (https://github.com/userfrosting/assets/issues/4) - Rewrite `AssetLoader` to act as a wrapper for `Assets` - Improved `route:list` Bakery command from [v4.1.20](#v4.1.20) -- Rewritten the `locator` service so it's better suited for sprinkle system ([#853](https://github.com/userfrosting/UserFrosting/issues/853)) -- `dev` environment changed to `debug` ([#653](https://github.com/userfrosting/UserFrosting/issues/653)) +- Rewritten the `locator` service so it's better suited for sprinkle system ([#853]) +- `dev` environment changed to `debug` ([#653]) - Changed deprecations to `warning`, and suppressed them in tests - Uncomment foreign keys in core migrations ([#833]) +- Move default groups, roles & permissions creation to seeds ### Fix - Sprinkle without a `template/` folder won't cause error anymore -- Fixed routes not available in Tests [and Bakery] ([#854](https://github.com/userfrosting/UserFrosting/issues/854)) -- redirect failing in UserController::pageInfo when user not found ([#888](https://github.com/userfrosting/UserFrosting/issues/888)) +- Fixed routes not available in Tests [and Bakery] ([#854]) +- redirect failing in UserController::pageInfo when user not found ([#888]) - Fix WhoopsRenderer integration, resolving a temp fix in [v4.1.21](#v4.1.21). - Fix Travis not running tests with the env database @@ -54,7 +55,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Migrations should now extends `UserFrosting\Sprinkle\Core\Database\Migration` instead of `UserFrosting\System\Bakery\Migration` - Migrations dependencies property should now be a static property - Deprecated migration `seed` method. Database seeding should now be done using the new Seeder -- Trait `\UserFrosting\Tests\DatabaseTransactions` has been deprecated. Tests should now use the `\UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` trait instead. ([#826](https://github.com/userfrosting/UserFrosting/issues/826)) +- Trait `\UserFrosting\Tests\DatabaseTransactions` has been deprecated. Tests should now use the `\UserFrosting\Sprinkle\Core\Tests\DatabaseTransactions` trait instead. ([#826]) ### Removed - The console IO instance is not available anymore in migrations @@ -642,4 +643,16 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x - Standardized JSON interface for backend scripts - Front-end should now be able to catch virtually any backend error and take an appropriate action (instead of white screen of death) +[#653]: https://github.com/userfrosting/UserFrosting/issues/653 +[#718]: https://github.com/userfrosting/UserFrosting/issues/718 +[#793]: https://github.com/userfrosting/UserFrosting/issues/793 +[#795]: https://github.com/userfrosting/UserFrosting/issues/795 +[#808]: https://github.com/userfrosting/UserFrosting/issues/808 +[#826]: https://github.com/userfrosting/UserFrosting/issues/826 +[#829]: https://github.com/userfrosting/UserFrosting/issues/829 [#833]: https://github.com/userfrosting/UserFrosting/issues/833 +[#838]: https://github.com/userfrosting/UserFrosting/issues/838 +[#853]: https://github.com/userfrosting/UserFrosting/issues/853 +[#854]: https://github.com/userfrosting/UserFrosting/issues/854 +[#869]: https://github.com/userfrosting/UserFrosting/issues/869 +[#888]: https://github.com/userfrosting/UserFrosting/issues/888 From 35a03466e3c485408284a296a79f65b8de09ecec Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 19 Nov 2018 21:29:45 -0500 Subject: [PATCH 148/237] Added `test:mail` Bakery command --- CHANGELOG.md | 1 + .../core/src/Bakery/TestMailCommand.php | 67 +++++++++++++++++++ .../core/templates/mail/test.html.twig | 13 ++++ 3 files changed, 81 insertions(+) create mode 100644 app/sprinkles/core/src/Bakery/TestMailCommand.php create mode 100644 app/sprinkles/core/templates/mail/test.html.twig diff --git a/CHANGELOG.md b/CHANGELOG.md index 540deb5f2..52250c25b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Improved overall test coverage and added coverage config to `phpunit.xml` - Added code style config (`.php_cs`) and instructions for PHP-CS-Fixer in Readme - Add cache facade (Ref [#838]) +- Added `test:mail` Bakery Command ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle diff --git a/app/sprinkles/core/src/Bakery/TestMailCommand.php b/app/sprinkles/core/src/Bakery/TestMailCommand.php new file mode 100644 index 000000000..f261ebb2f --- /dev/null +++ b/app/sprinkles/core/src/Bakery/TestMailCommand.php @@ -0,0 +1,67 @@ +setName('test:mail') + ->setDescription('Test mail settings') + ->setHelp('This command let you test the email sending capability of your UserFrosting setup') + ->addOption('to', null, InputOption::VALUE_REQUIRED, 'Adress to send test email to. Use admin contact if ommited.'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title('Testing Email Configuration'); + + /** @var \UserFrosting\Support\Repository\Repository */ + $config = $this->ci->config; + + $to = $input->getOption('to') ?: $config['address_book.admin.email']; + $this->io->writeln("Sending test email to : $to"); + + // Create and send email + $message = new TwigMailMessage($this->ci->view, 'mail/test.html.twig'); + $message->from($config['address_book.admin']) + ->addEmailRecipient(new EmailRecipient($to, $to)) + ->addParams([ + 'request_date' => Carbon::now()->format('Y-m-d H:i:s') + ]); + + try { + $this->ci->mailer->send($message); + } catch (\Exception $e) { + $this->io->error($e->getMessage()); + exit(1); + } + + $this->io->success("Test email sent to $to !"); + } +} diff --git a/app/sprinkles/core/templates/mail/test.html.twig b/app/sprinkles/core/templates/mail/test.html.twig new file mode 100644 index 000000000..00f4c6ec8 --- /dev/null +++ b/app/sprinkles/core/templates/mail/test.html.twig @@ -0,0 +1,13 @@ +{% block subject %} + {{site.title}} - Test email +{% endblock %} + +{% block body %} +

+A test email has been submitted from {{site.title}} ({{site.uri.public}}) on {{request_date | date('m/d/Y g:i A')}}. +

+

+With regards,
+The {{site.title}} Team +

+{% endblock %} \ No newline at end of file From abbdf947a4bc14b79be88838d6426660c7990af2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 19 Nov 2018 21:47:45 -0500 Subject: [PATCH 149/237] Removed unnecessary if --- app/sprinkles/core/src/Mail/Mailer.php | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/app/sprinkles/core/src/Mail/Mailer.php b/app/sprinkles/core/src/Mail/Mailer.php index ba083ab68..7c43fbd85 100644 --- a/app/sprinkles/core/src/Mail/Mailer.php +++ b/app/sprinkles/core/src/Mail/Mailer.php @@ -44,8 +44,7 @@ public function __construct($logger, $config = []) $this->phpMailer = new \PHPMailer(true); // Configuration options - if (isset($config['mailer'])) { - switch ($config['mailer']) { + switch ($config['mailer']) { case 'mail': $this->phpMailer->isMail(); break; @@ -71,13 +70,12 @@ public function __construct($logger, $config = []) break; default: throw new \phpmailerException("'mailer' must be one of 'smtp', 'mail', 'qmail', or 'sendmail'."); - } + } - // Set any additional message-specific options - // TODO: enforce which options can be set through this subarray - if (isset($config['message_options'])) { - $this->setOptions($config['message_options']); - } + // Set any additional message-specific options + // TODO: enforce which options can be set through this subarray + if (isset($config['message_options'])) { + $this->setOptions($config['message_options']); } // Pass logger into phpMailer object From 311293bf222be8f05ce9e8767f5949d56ad8a5fa Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 19 Nov 2018 21:50:25 -0500 Subject: [PATCH 150/237] Updated Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 52250c25b..be6f343b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added code style config (`.php_cs`) and instructions for PHP-CS-Fixer in Readme - Add cache facade (Ref [#838]) - Added `test:mail` Bakery Command +- Add support for other config['mailer'] options ([#872]; Thanks @apple314159 !) ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle @@ -656,4 +657,5 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#853]: https://github.com/userfrosting/UserFrosting/issues/853 [#854]: https://github.com/userfrosting/UserFrosting/issues/854 [#869]: https://github.com/userfrosting/UserFrosting/issues/869 +[#872]: https://github.com/userfrosting/UserFrosting/issues/872 [#888]: https://github.com/userfrosting/UserFrosting/issues/888 From 0c350d05d702230d26756575f8a01e1a03c81a66 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 20 Nov 2018 21:23:48 -0500 Subject: [PATCH 151/237] Fix comment about that weird code --- app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 03f6261be..188d41299 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -248,7 +248,8 @@ public function register(ContainerInterface $container) $config->set('csrf.blacklist', $csrfBlacklist); - // Reset 'assets' scheme in locator if specified in config. (must be done here thanks to prevent circular dependency) + // Reset 'assets' scheme in locator to use raw assets if specified in config. + // Must be done here to prevent circular dependency as config is not loaded in system and locator can't be extended here. if (!$config['assets.use_raw']) { $c->locator->removeStream('assets'); $c->locator->registerStream('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); From ff6b3e51ec56203cc88d98c3cb5ac809bd0c90da Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 20 Nov 2018 22:24:31 -0500 Subject: [PATCH 152/237] When running Bakery bake in production... ...the migration warning should only be displayed if migrations are pending. --- .../core/src/Bakery/MigrateCommand.php | 27 ++++++++++--- .../core/src/Bakery/MigrateRefreshCommand.php | 26 ++++++++++-- .../core/src/Bakery/MigrateResetCommand.php | 22 +++++++++- .../src/Bakery/MigrateRollbackCommand.php | 22 +++++++++- .../core/src/Bakery/MigrateStatusCommand.php | 7 ++-- .../Database/Migrator/MigrationLocator.php | 6 +-- .../core/src/Database/Migrator/Migrator.php | 40 ++++++++++++++----- .../Integration/BakeryMigrateCommandTest.php | 4 ++ .../BakeryMigrateRefreshCommandTest.php | 3 ++ .../BakeryMigrateResetCommandTest.php | 3 ++ .../BakeryMigrateRollbackCommandTest.php | 4 ++ .../BakeryMigrateStatusCommandTest.php | 4 +- 12 files changed, 136 insertions(+), 32 deletions(-) diff --git a/app/sprinkles/core/src/Bakery/MigrateCommand.php b/app/sprinkles/core/src/Bakery/MigrateCommand.php index 3340b2593..cbef3aa4b 100644 --- a/app/sprinkles/core/src/Bakery/MigrateCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateCommand.php @@ -52,6 +52,26 @@ protected function execute(InputInterface $input, OutputInterface $output) // Get migrator $migrator = $this->setupMigrator($input); + // Get pending migrations + $pending = $migrator->getPendingMigrations(); + + // Don't go further if no migration is pending + if (empty($pending)) { + $this->io->success('Nothing to migrate'); + exit(1); + } + + // Show migrations about to be ran when in production mode + if ($this->isProduction()) { + $this->io->section('Pending migrations'); + $this->io->listing($pending); + + // Confirm action when in production mode + if (!$this->confirmToProceed($input->getOption('force'))) { + exit(1); + } + } + // Run migration try { $migrated = $migrator->run(['pretend' => $pretend, 'step' => $step]); @@ -67,7 +87,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // If all went well, there's no fatal errors and we have migrated // something, show some success if (empty($migrated)) { - $this->io->success('Nothing to migrate'); + $this->io->warning('Nothing migrated !'); } else { $this->io->success('Migration successful !'); } @@ -81,11 +101,6 @@ protected function execute(InputInterface $input, OutputInterface $output) */ protected function setupMigrator(InputInterface $input) { - // Confirm action when in production mode - if (!$this->confirmToProceed($input->getOption('force'))) { - exit(1); - } - /** @var \UserFrosting\Sprinkle\Core\Database\Migrator\Migrator */ $migrator = $this->ci->migrator; diff --git a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php index 2f421d86d..b14c70672 100644 --- a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php @@ -45,6 +45,26 @@ protected function execute(InputInterface $input, OutputInterface $output) // Get migrator $migrator = $this->setupMigrator($input); + // Get pending migrations + $ran = $migrator->getRanMigrations($steps); + + // Don't go further if no migration is ran + if (empty($ran)) { + $this->io->success('Nothing to refresh'); + exit(1); + } + + // Show migrations about to be reset when in production mode + if ($this->isProduction()) { + $this->io->section('Migrations to refresh'); + $this->io->listing($ran); + + // Confirm action when in production mode + if (!$this->confirmToProceed($input->getOption('force'))) { + exit(1); + } + } + // Rollback migration try { $rolledback = $migrator->rollback(['pretend' => false, 'steps' => $steps]); @@ -59,7 +79,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // Stop if nothing was rolledback if (empty($rolledback)) { - $this->io->success('Nothing to refresh'); + $this->io->warning('Nothing was refreshed !'); return; } @@ -70,9 +90,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // If all went well, there's no fatal errors and we have migrated // something, show some success - if (empty($migrated)) { - $this->io->success('Nothing to refresh'); - } else { + if (!empty($migrated)) { $this->io->success('Refresh successful !'); } } diff --git a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php index f7160cc68..b2d9af1e0 100644 --- a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php @@ -61,6 +61,26 @@ protected function performReset(InputInterface $input) // Get migrator $migrator = $this->setupMigrator($input); + // Get pending migrations + $ran = $migrator->getRanMigrations(); + + // Don't go further if no migration is ran + if (empty($ran)) { + $this->io->success('Nothing to reset'); + exit(1); + } + + // Show migrations about to be reset when in production mode + if ($this->isProduction()) { + $this->io->section('Migrations to rollback'); + $this->io->listing($ran); + + // Confirm action when in production mode + if (!$this->confirmToProceed($input->getOption('force'))) { + exit(1); + } + } + // Reset migrator try { $resetted = $migrator->reset($pretend); @@ -82,7 +102,7 @@ protected function performReset(InputInterface $input) // If all went well, there's no fatal errors and we have migrated // something, show some success if (empty($resetted)) { - $this->io->success('Nothing to reset'); + $this->io->warning('Nothing was reseted !'); } else { $this->io->success('Reset successful !'); } diff --git a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php index 76ad14842..8d201ace4 100644 --- a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php @@ -49,6 +49,26 @@ protected function execute(InputInterface $input, OutputInterface $output) // Get migrator $migrator = $this->setupMigrator($input); + // Get pending migrations + $ran = $migration ? [$migration]: $migrator->getRanMigrations($steps); + + // Don't go further if no migration is ran + if (empty($ran)) { + $this->io->success('Nothing to rollback'); + exit(1); + } + + // Show migrations about to be reset when in production mode + if ($this->isProduction()) { + $this->io->section('Migrations to rollback'); + $this->io->listing($ran); + + // Confirm action when in production mode + if (!$this->confirmToProceed($input->getOption('force'))) { + exit(1); + } + } + // Rollback migrations try { // If we have a specific to rollback, do this. Otherwise, do a normal rollback @@ -69,7 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // If all went well, there's no fatal errors and we have migrated // something, show some success if (empty($migrated)) { - $this->io->success('Nothing to rollback'); + $this->io->warning('Nothing was rollbacked !'); } else { $this->io->success('Rollback successful !'); } diff --git a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php index adfc6d257..bfda24f1b 100644 --- a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php @@ -48,19 +48,18 @@ protected function execute(InputInterface $input, OutputInterface $output) // Get ran migrations. If repository doesn't exist, there's no ran if (!$migrator->repositoryExists()) { - $ranArray = []; + $ran = collect(); } else { $ran = $migrator->getRepository()->getMigrations(); - $ranArray = $ran->pluck('migration')->all(); } // Get available migrations and calculate pending one $available = $migrator->getAvailableMigrations(); - $pending = $migrator->pendingMigrations($available, $ranArray); + $pending = $migrator->getPendingMigrations(); // Display ran migrations $this->io->section('Installed migrations'); - if (count($ranArray) > 0) { + if ($ran->count() > 0) { $this->io->table( ['Migration', 'Available?', 'Batch'], $this->getStatusFor($ran, $available) diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php index af5ae7167..b64937916 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php @@ -9,7 +9,7 @@ namespace UserFrosting\Sprinkle\Core\Database\Migrator; use Illuminate\Support\Str; -use UserFrosting\UniformResourceLocator\Resource; +use UserFrosting\UniformResourceLocator\Resource as ResourceInstance; use UserFrosting\UniformResourceLocator\ResourceLocator; /** @@ -61,10 +61,10 @@ public function getMigrations() /** * Return an array of migration details inclusing the classname and the sprinkle name * - * @param resource $file The migration file + * @param ResourceInstance $file The migration file * @return string The migration full class path */ - protected function getMigrationDetails(Resource $file) + protected function getMigrationDetails(ResourceInstance $file) { // Format the sprinkle name for the namespace $sprinkleName = $file->getLocation()->getName(); diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index b6233dde1..f5582ebb8 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -75,14 +75,8 @@ public function run(array $options = []) { $this->notes = []; - // Get the list of available migration classes in the the Filesystem - $availableMigrations = $this->getAvailableMigrations(); - - // Get ran migrations - $ranMigrations = $this->repository->getMigrationsList(); - // Get outstanding migrations classes that requires to be run up - $pendingMigrations = $this->pendingMigrations($availableMigrations, $ranMigrations); + $pendingMigrations = $this->getPendingMigrations(); // First we will just make sure that there are any migrations to run. If there // aren't, we will just make a note of it to the developer so they're aware @@ -95,7 +89,7 @@ public function run(array $options = []) // This operation is important as it's the one that place the outstanding migrations // in the correct order, making sure a migration script won't fail because the table // it depends on has not been created yet (for example). - $analyser = new Analyser($pendingMigrations, $ranMigrations); + $analyser = new Analyser($pendingMigrations, $this->getRanMigrations()); // Any migration without a fulfilled dependency will cause this script to throw an exception if ($unfulfillable = $analyser->getUnfulfillable()) { @@ -117,7 +111,7 @@ public function run(array $options = []) * @param array $ran The list of already ran migrations returned by the migration repository * @return array The list of pending migrations, ie the available migrations not ran yet */ - public function pendingMigrations(array $available, array $ran) + protected function pendingMigrations(array $available, array $ran) { return collect($available)->reject(function ($migration) use ($ran) { return collect($ran)->contains($migration); @@ -314,7 +308,7 @@ protected function rollbackMigrations(array $migrations, array $options) protected function checkRollbackDependencies(array $migrations) { // Get ran migrations - $ranMigrations = $this->repository->getMigrationsList(); + $ranMigrations = $this->getRanMigrations(); // Setup rollback analyser $analyser = new RollbackAnalyser($ranMigrations, $migrations); @@ -345,7 +339,7 @@ public function reset($pretend = false) // "empty" state and ready to be migrated "up" again. // // !TODO :: Should compare to the install list to make sure no outstanding migration (ran, but with no migraiton class anymore) still exist in the db - $migrations = array_reverse($this->repository->getMigrationsList()); + $migrations = array_reverse($this->getRanMigrations()); if (count($migrations) === 0) { return []; @@ -467,6 +461,30 @@ public function getAvailableMigrations() return $this->locator->getMigrations(); } + /** + * Get a list of all ran migrations + * + * @param int $steps Number of batch to return + * @param string $order asc|desc + * @return array + */ + public function getRanMigrations($steps = -1, $order = 'asc') + { + return $this->repository->getMigrationsList($steps, $order); + } + + /** + * Get a list of pending migrations + * + * @return array + */ + public function getPendingMigrations() + { + $available = $this->getAvailableMigrations(); + $ran = $this->getRanMigrations(); + return $this->pendingMigrations($available, $ran); + } + /** * Get the migration repository instance. * diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php index d6842415e..f86aa1d42 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php @@ -27,6 +27,7 @@ public function testBasicMigrationsCallMigratorWithProperArguments() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getPendingMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => false])->andReturn([]); $migrator->shouldReceive('getNotes'); @@ -41,6 +42,7 @@ public function testMigrationRepositoryCreatedWhenNecessary() $migrator->shouldReceive('repositoryExists')->once()->andReturn(false); $migrator->shouldReceive('getRepository')->once()->andReturn($repository); + $migrator->shouldReceive('getPendingMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => false])->andReturn([]); $migrator->shouldReceive('getNotes'); @@ -55,6 +57,7 @@ public function testTheCommandMayBePretended() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getPendingMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('run')->once()->with(['pretend' => true, 'step' => false])->andReturn([]); $migrator->shouldReceive('getNotes'); @@ -67,6 +70,7 @@ public function testStepMayBeSet() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getPendingMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => true])->andReturn([]); $migrator->shouldReceive('getNotes'); diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php index 792b84c56..da8145b0b 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php @@ -27,6 +27,7 @@ public function testBasicMigrationsCallMigratorWithProperArguments() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 1])->andReturn(['foo']); $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => false])->andReturn([]); $migrator->shouldReceive('getNotes'); @@ -40,6 +41,7 @@ public function testBasicCallWithNotthingToRollback() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 1])->andReturn([]); $migrator->shouldNotReceive('run'); $migrator->shouldReceive('getNotes'); @@ -53,6 +55,7 @@ public function testStepsMayBeSet() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 3])->andReturn(['foo']); $migrator->shouldReceive('run')->once()->with(['pretend' => false, 'step' => false])->andReturn([]); $migrator->shouldReceive('getNotes'); diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php index 78d71e98e..c0e482ce5 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php @@ -31,6 +31,7 @@ public function testBasicMigrationsCallMigratorWithProperArguments() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->twice()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('reset')->once()->with(false)->andReturn(['foo']); $migrator->shouldReceive('getNotes'); $migrator->shouldReceive('getRepository')->once()->andReturn($repository); @@ -48,6 +49,7 @@ public function testBasicCallWithNotthingToRollback() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->twice()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('reset')->once()->with(false)->andReturn([]); $migrator->shouldReceive('getNotes'); $migrator->shouldReceive('getRepository')->once()->andReturn($repository); @@ -61,6 +63,7 @@ public function testTheCommandMayBePretended() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('reset')->once()->with(true)->andReturn(['foo']); $migrator->shouldReceive('getNotes'); $migrator->shouldNotReceive('getRepository'); diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php index 2e034d736..23b509c4b 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php @@ -27,6 +27,7 @@ public function testBasicMigrationsCallMigratorWithProperArguments() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 1])->andReturn([]); $migrator->shouldReceive('getNotes'); @@ -40,6 +41,7 @@ public function testMigrationRepositoryCreatedWhenNecessary() $repository = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(false); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('getRepository')->once()->andReturn($repository); $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 1])->andReturn([]); $migrator->shouldReceive('getNotes'); @@ -55,6 +57,7 @@ public function testTheCommandMayBePretended() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('rollback')->once()->with(['pretend' => true, 'steps' => 1])->andReturn([]); $migrator->shouldReceive('getNotes'); @@ -67,6 +70,7 @@ public function testStepsMayBeSet() // Setup migrator mock $migrator = m::mock('UserFrosting\Sprinkle\Core\Database\Migrator\Migrator'); $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); + $migrator->shouldReceive('getRanMigrations')->once()->andReturn(['foo']); $migrator->shouldReceive('rollback')->once()->with(['pretend' => false, 'steps' => 3])->andReturn([]); $migrator->shouldReceive('getNotes'); diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php index ddde7be0e..65b385d81 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php @@ -38,7 +38,7 @@ public function testBasicMigrationsCallMigratorWithProperArguments() $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); $migrator->shouldReceive('getRepository')->once()->andReturn($repository); $migrator->shouldReceive('getAvailableMigrations')->once()->andReturn($available); - $migrator->shouldReceive('pendingMigrations')->once()->with($available, $installed)->andReturn($pending); + $migrator->shouldReceive('getPendingMigrations')->once()->andReturn($pending); $repository->shouldReceive('getMigrations')->once()->andReturn($this->getInstalledMigrationStub()); @@ -62,7 +62,7 @@ public function testDatabaseMayBeSet() $migrator->shouldReceive('repositoryExists')->once()->andReturn(true); $migrator->shouldReceive('getRepository')->once()->andReturn($repository); $migrator->shouldReceive('getAvailableMigrations')->once()->andReturn($available); - $migrator->shouldReceive('pendingMigrations')->once()->with($available, $installed)->andReturn($pending); + $migrator->shouldReceive('getPendingMigrations')->once()->andReturn($pending); $repository->shouldReceive('getMigrations')->once()->andReturn($this->getInstalledMigrationStub()); From 40c39aeab8b6a88ad29f4d4068d34727244e9e74 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 24 Nov 2018 12:23:50 +1100 Subject: [PATCH 153/237] Streamify assets (duct-tape edition) #615 --- app/system/Bakery/Command/BuildAssets.php | 19 - build/gulpfile.js | 535 +- build/package-lock.json | 7134 ++++++++++++--------- build/package.json | 35 +- 4 files changed, 4576 insertions(+), 3147 deletions(-) diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/system/Bakery/Command/BuildAssets.php index 7e44f831e..0faa60960 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/system/Bakery/Command/BuildAssets.php @@ -124,14 +124,6 @@ protected function buildAssets() $exitCode = 0; - $this->io->writeln('> npm run uf-bundle-build'); - passthru('npm run uf-bundle-build', $exitCode); - - if ($exitCode !== 0) { - $this->io->error('bundling preparation has failed'); - exit(1); - } - $this->io->writeln('> npm run uf-bundle'); passthru('npm run uf-bundle'); @@ -140,17 +132,6 @@ protected function buildAssets() exit(1); } - if ($exitCode !== 0) { - $this->io->warning('bundling may have failed, check output'); - } - - $this->io->writeln('> npm run uf-bundle-clean'); - passthru('npm run uf-bundle-clean'); - - if ($exitCode !== 0) { - $this->io->warning("bundling cleanup has failed, which while unusual shouldn't cause any problems"); - } - chdir($wd); } diff --git a/build/gulpfile.js b/build/gulpfile.js index 91adf8185..bbef76c2b 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -1,280 +1,329 @@ -'use strict'; +"use strict"; +const { config: envConfig } = require("dotenv"); +const { task, src, dest, parallel, series } = require("gulp"); +const { readFileSync, existsSync, writeFileSync } = require("fs"); +const { bower: mergeBowerDeps, yarn: mergeYarnDeps, yarnIsFlat } = require("@userfrosting/merge-package-dependencies"); +const { sync: deleteSync } = require("del"); +const { execSync } = require("child_process"); +const concatJs = require("gulp-concat"); +const { default: minifyJs } = require("gulp-uglify-es"); +const concatCss = require("gulp-concat-css"); +const minifyCss = require("gulp-clean-css"); +const { ValidateRawConfig, MergeRawConfigs, default: Bundler } = require("gulp-uf-bundle-assets"); +const rev = require("gulp-rev"); +const prune = require("gulp-prune"); +const { resolve: resolvePath } = require("path"); // Load environment variables -require('dotenv').config({path: '../app/.env'}); - -/** - * Global dependencies - */ -const gulp = require('gulp'); -const fs = require('fs-extra'); -const del = require('del'); -const plugins = require('gulp-load-plugins')(); +envConfig({ path: "../app/.env" }); // Set up logging -let doILog = (process.env.UF_MODE == 'dev'); -let logger = (message) => { - if (doILog) { - console.log(message); - } -}; - -const sprinklesDir = '../app/sprinkles'; -const sprinklesSchemaPath = '../app/sprinkles.json'; - -// The Sprinkle load order from sprinkles.json -const sprinkles = require(`${sprinklesSchemaPath}`)['base']; - -// The directory where the bundle task should place compiled assets. -// The names of assets in bundle.result.json will be located relative to this path. -const publicAssetsDir = '../public/assets/'; - -// name of the bundle file -const sprinkleBundleFile = 'asset-bundles.json'; - -// Merged bundle config file with relative dir -const bundleConfigFile = './bundle.config.json'; +const doILog = (process.env.UF_MODE === "dev"); /** - * Vendor asset task - * NOTE: This task cannot be run directly from the gulp cli. Use the npm run script instead. + * Prints to stdout with newline when UF_MODE is dev. + * @param {any} message Message to log. */ -gulp.task('assets-install', () => { - 'use strict'; - - // Legacy clean up - let legacyVendorAssets = '../app/sprinkles/*/assets/vendor/**'; - if (del.sync(legacyVendorAssets, { dryRun: true, force: true }).length > 0) { - logger('Frontend vendor assets are now located at "app/assets".\nStarting clean up of legacy vendor assets...'); - del.sync(legacyVendorAssets, { force: true }); - logger('Complete.') - } +function Logger(message) { + if (doILog) console.log(message); +} + +// Path constants +const rootDir = "../"; +const sprinklesDir = rootDir + "app/sprinkles/"; +const sprinklesSchemaPath = rootDir + "app/sprinkles.json"; +const publicAssetsDir = rootDir + "public/assets/"; +const legacyVendorAssetsGlob = rootDir + "sprinkles/*/assets/vendor/**"; +const sprinkleBundleFile = "asset-bundles.json"; +const vendorAssetsDir = rootDir + "app/assets/"; + +// Load sprinkles +let sprinkles; +try { + sprinkles = JSON.parse(readFileSync(sprinklesSchemaPath)).base; +} +catch (error) { + Logger(sprinklesSchemaPath + " could not be loaded, does it exist?"); + throw error; +} - let mergePkg = require('@userfrosting/merge-package-dependencies'); - - // See if there are any yarn packages. - let yarnPaths = []; - for (let sprinkle of sprinkles) { - if (fs.existsSync(`../app/sprinkles/${sprinkle}/package.json`)) { - yarnPaths.push(`../app/sprinkles/${sprinkle}/package.json`); +/** + * Installs vendor assets. Mapped to npm script "uf-assets-install". + */ +task("assets-install", done => { + try { + // This script requires the npm environment, and therefore cannot be run directly with the gulp CLI. + if (!process.env.npm_lifecycle_event) throw new Error("Assets installation must be run via 'npm run uf-assets-install'"); + + // Clean up any legacy assets + if (deleteSync(legacyVendorAssetsGlob, { force: true })) + Logger("Legacy frontend vendor assets were deleted. Frontend vendor assets are now installed to 'app/assets'."); + + // See if there are any yarn packages + // TODO Would be better to read in file here then hand it off since we can avoid redundant `existsSync` calls + const yarnPaths = []; + for (const sprinkle of sprinkles) { + const path = sprinklesDir + sprinkle + "/package.json"; + if (existsSync(path)) yarnPaths.push(path); } - } - if (yarnPaths.length > 0) { - // Yes there are! - - // Delete old package.json and yarn.lock - del.sync(['../app/assets/package.json', '../app/assets/yarn.lock'], { force: true }); - - // Generate package.json - let yarnTemplate = {// Private makes sure it isn't published, and cuts out a lot of unnecessary fields. - private: true - }; - logger('\nMerging packages...\n'); - mergePkg.yarn(yarnTemplate, yarnPaths, '../app/assets/', doILog); - logger('\nMerge complete.\n'); - - // Yarn automatically removes extraneous packages. - - // Perform installation. - // --flat switch cannot be used due to spotty support of --non-interactive switch - // Thankfully, "resolutions" works outside flat mode. - logger('Installing npm/yarn assets...'); - require('child_process').execSync('yarn install --non-interactive', { - cwd: '../app/assets', - stdio: doILog ? 'inherit' : '' - }); - - // Ensure dependency tree is flat manually because Yarn errors out with a TTY error. - logger('\nInspecting dependency tree...\n') - - if (!mergePkg.yarnIsFlat('../app/assets/', doILog)) { - logger(` -Dependency tree is not flat! Dependencies must be flat to prevent abnormal behavior. + + if (yarnPaths.length > 0) { + // Install yarn dependencies + Logger("Installing vendor assets with Yarn...") + + // TODO I think we might be able to get away with removing this, since yarn.lock is synced with package.json + deleteSync([vendorAssetsDir + "package.json", vendorAssetsDir + "yarn.lock"], { force: true }); + + // Generate package.json + const yarnTemplate = { + // Private makes sure it isn't published, and cuts out a lot of unnecessary fields. + private: true + }; + Logger("Collating dependencies..."); + mergeYarnDeps(yarnTemplate, yarnPaths, vendorAssetsDir, doILog); + Logger("Dependency collation complete."); + + // Perform installation + // Yarn will automatically remove extraneous packages (barring algorithm failure) + // --flat switch cannot be used currently due to https://github.com/yarnpkg/yarn/issues/1658 however "resolutions" thankfully will still work + Logger("Running yarn install --non-interactive"); + execSync("yarn install --non-interactive", { + cwd: vendorAssetsDir, + stdio: doILog ? "inherit" : "" + }); + + // Ensure dependency tree is flat + Logger("Inspecting dependency tree..."); + if (!yarnIsFlat(vendorAssetsDir, doILog)) { + Logger(` +Dependency tree is not flat! Dependencies must be flat to prevent abnormal behavior of frontend dependencies. Recommended solution is to adjust dependency versions until issue is resolved to ensure 100% compatibility. Alternatively, resolutions can be used as an override, as documented at https://yarnpkg.com/en/docs/selective-version-resolutions `); - throw 'Dependency tree is not flat!'; - } else { - logger('\nDependency tree is flat and usable.\n') + throw new Error("Dependency tree is not flat."); + } + else Logger("Dependency tree is flat and therefore usable."); } - } - else del.sync([ - '../app/assets/package.json', - '../app/assets/node_modules/', - '../app/assets/yarn.lock' - ], { force: true }); - - // See if there are any bower packages. - let bowerPaths = []; - for (let sprinkle of sprinkles) { - // bower - if (fs.existsSync(`../app/sprinkles/${sprinkle}/bower.json`)) { - console.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`); - bowerPaths.push(`../app/sprinkles/${sprinkle}/bower.json`); + else { + // Delete yarn artefacts + deleteSync([ + vendorAssetsDir + "package.json", + vendorAssetsDir + "node_modules/", + vendorAssetsDir + "yarn.lock" + ], { force: true }); + } + + // See if there are any Bower packages + // TODO Would be better to read in file here then hand it off since we can avoid redundant `existsSync` calls + const bowerPaths = []; + for (const sprinkle of sprinkles) { + const path = sprinklesDir + sprinkle + "/bower.json"; + if (existsSync(path)) { + // TODO: We should really have a link to docs in the message + console.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`); + bowerPaths.push(path); + } + } + + if (bowerPaths.length > 0) { + // Install yarn dependencies + Logger("Installing vendor assets with Bower...") + + // TODO I think we might be able to get away with removing this + deleteSync(vendorAssetsDir + "bower.json", { force: true }); + + // Generate package.json + const bowerTemplate = { + name: "uf-vendor-assets" + }; + Logger("Collating dependencies..."); + mergeBowerDeps(bowerTemplate, bowerPaths, vendorAssetsDir, doILog); + Logger("Dependency collation complete."); + + // Perform installation + Logger("Running bower install -q --allow-root"); + // --allow-root stops bower from complaining about being in 'sudo' in various situations + execSync("bower install -q --allow-root", { + cwd: vendorAssetsDir, + stdio: doILog ? "inherit" : "" + }); + + // Prune any unnecessary dependencies + Logger("Running bower prune -q --allow-root"); + // --allow-root stops bower from complaining about being in 'sudo' in various situations + execSync("bower prune -q --allow-root", { + cwd: vendorAssetsDir, + stdio: doILog ? "inherit" : "" + }); + } + else { + // Remove bower artefacts + deleteSync([ + vendorAssetsDir + "bower.json", + vendorAssetsDir + "bower_components/" + ], { force: true }); } + + done(); } - if (bowerPaths.length > 0) { - // Yes there are! - - // Delete old bower.json - del.sync('../app/assets/bower.json', { force: true }); - - // Generate bower.json - let bowerTemplate = { - name: 'uf-vendor-assets' - }; - logger('\nMerging packages...\n'); - mergePkg.bower(bowerTemplate, bowerPaths, '../app/assets/', doILog); - logger('\nMerge complete.\n'); - - let childProcess = require('child_process'); - - // Remove extraneous packages - childProcess.execSync('bower prune', { - cwd: '../app/assets', - stdio: doILog ? 'inherit' : '' - }); - - // Perform installation - childProcess.execSync('bower install -q --allow-root', { // --allow-root stops bower from complaining about being in 'sudo'. - cwd: '../app/assets', - stdio: doILog ? 'inherit' : '' - }); - // Yarn is able to output its completion. Bower... not so much. - logger('Done.\n'); + catch (error) { + done(error); } - else del.sync([ - '../app/assets/bower.json', - '../app/assets/bower_components/**' - ], { force: true }); }); - /** - * Bundling tasks + * Compiles frontend assets. Mapped to npm script "uf-bundle". */ - -// Executes bundling tasks according to bundle.config.json files in each Sprinkle, as per Sprinkle load order. -// Respects bundle collision rules. -gulp.task('bundle-build', () => { - 'use strict'; - let copy = require('recursive-copy'); - let merge = require('merge-array-object'); - let cleanup = (e) => { - 'use strict'; - // Delete temporary directory if exists - fs.rmdirSync('./temp'); - // Delete created bundle.config.json file - fs.unlinkSync(bundleConfigFile); - // Propagate error - throw e; - }; - let config = { - bundle: {}, - copy: [] +task("bundle", () => { + // Build sources list + const sources = []; + for (const sprinkle of sprinkles) { + sources.push(sprinklesDir + sprinkle + "/assets/**"); + } + sources.push(vendorAssetsDir + "node_modules/**"); + sources.push(vendorAssetsDir + "bower_components/**"); + + // Create bundle stream factories object + const bundleBuilder = { + Scripts: (src, name) => { + return src + .pipe(concatJs(name + ".js")) + .pipe(minifyJs()) + .pipe(rev()); + }, + Styles: (src, name) => { + return src + .pipe(concatCss(name + ".css")) + .pipe(minifyCss()) + .pipe(rev()); + } }; - sprinkles.forEach((sprinkle) => { - 'use strict'; - let location = `${sprinklesDir}/${sprinkle}/`; - if (fs.existsSync(`${location}${sprinkleBundleFile}`)) { - // Require shouldn't be used here. - let currentConfig = require(`${location}${sprinkleBundleFile}`); - // Add bundles to config, respecting collision rules. - for (let bundleName in currentConfig.bundle) { - // If bundle already defined, handle as per collision rules. - if (bundleName in config.bundle) { - let onCollision = 'replace'; - try { - onCollision = (typeof currentConfig.bundle[bundleName].options.sprinkle.onCollision !== 'undefined' ? currentConfig.bundle[bundleName].options.sprinkle.onCollision : 'replace'); - } - catch (e) { - } - switch (onCollision) { - case 'replace': - config.bundle[bundleName] = currentConfig.bundle[bundleName]; - break; - case 'merge': - // If using this collision rule, keep in mind any bundling options will also be merged. - // Inspect the produced 'bundle.config.json' file in the 'build' folder to ensure options are correct. - config.bundle[bundleName] = merge(config.bundle[bundleName], currentConfig.bundle[bundleName]); - break; - case 'ignore': - // Do nothing. This simply exists to prevent falling through to error catchment. - break; - case 'error': - cleanup(`The bundle '${bundleName}' in the Sprinkle '${sprinkle}' has been previously defined, and the bundle's 'onCollision' property is set to 'error'.`); - default: - cleanup(`Unexpected input '${onCollision}' for 'onCollision' for the bundle '${bundleName}' in the Sprinkle '${sprinkle}'.`); + // Load up bundle configurations + const rawConfigs = []; + for (const sprinkle of sprinkles) { + Logger("Looking for asset bundles in sprinkle " + sprinkle); + + // Try to read file + let fileContent; + try { + fileContent = readFileSync(sprinklesDir + sprinkle + "/" + sprinkleBundleFile); + Logger(` Read '${sprinkleBundleFile}'.`); + } + catch (error) { + Logger(` No '${sprinkleBundleFile}' detected, or can't be read.`); + continue; + } + + // Validate (JSON and content) + let rawConfig; + try { + rawConfig = JSON.parse(fileContent); + ValidateRawConfig(rawConfig); + rawConfigs.push(rawConfig); + Logger(" Asset bundles validated and loaded."); + } + catch (error) { + Logger(" Asset bundle is invalid."); + throw error; + } + } + + // Merge bundles + Logger("Merging asset bundles..."); + const rawConfig = MergeRawConfigs(rawConfigs); + + // Set up virtual path rules + rawConfig.VirtualPathRules = [ + ["../app/assets/node_modules", "./assets/vendor"], + ["../app/assets/bower_components", "./assets/vendor"]]; + for (const sprinkle of sprinkles) { + rawConfig.VirtualPathRules.push([ + sprinklesDir + sprinkle + "/assets", "./assets" + ]); + } + + // Set base path for bundle resources to align with virtual paths + rawConfig.BundlesVirtualBasePath = "./assets/"; + + // Bundle results callback + function bundleResults(results) { + /** + * Resolves absolute path to gulp-uf-bundle-assets v2 style path + * @param {string} path Absolute path to resolve. + */ + function resolveToAssetPath(path) { + if (path.startsWith(resolvePath(sprinklesDir))) { + // Handle sprinkle path + for (const sprinkle of sprinkles) { + const sprinklePath = resolvePath(sprinklesDir, sprinkle, "assets"); + if (path.startsWith(sprinklePath)) { + return path.replace(sprinklePath, "").replace(/\\/g, "/").replace("/", ""); } } - // Otherwise, just add. - else { - config.bundle[bundleName] = currentConfig.bundle[bundleName]; + } + else { + // Handle vendor path + if (path.startsWith(resolvePath(vendorAssetsDir, "bower_components"))) { + return path.replace(resolvePath(vendorAssetsDir, "bower_components"), "").replace(/\\/g, "/").replace("/", ""); + } + else if (path.startsWith(resolvePath(vendorAssetsDir, "node_modules"))) { + return path.replace(resolvePath(vendorAssetsDir, "node_modules"), "").replace(/\\/g, "/").replace("/", ""); } } - // Add/merge copy files to config - if ('copy' in currentConfig) { - config.copy = new Set(config.copy, currentConfig.copy); + + throw new Error(`Unable to resolve path '${path}' to relative asset path.`); + } + + const resultsObject = {}; + for (const [name, files] of results) { + if (files.length !== 1) + throw new Error(`The bundle ${name} has not generated exactly one file.`); + else { + if (!resultsObject[name]) { + resultsObject[name] = {}; + } + if (files[0].extname === ".js") + resultsObject[name].scripts = resolveToAssetPath(files[0].path); + else + resultsObject[name].styles = resolveToAssetPath(files[0].path); } } - }); - // Save bundle rules to bundle.config.json - fs.writeFileSync(bundleConfigFile, JSON.stringify(config)); - - // Copy vendor assets (bower, then npm) - /** @todo Should really keep the garbage files out. A filter function can be passed to the copySync settings object. */ - let paths = [ - '../app/assets/bower_components/', - '../app/assets/node_modules/' - ]; - for (let path of paths) { - if (fs.pathExistsSync(path)) fs.copySync(path, `${publicAssetsDir}vendor/`, { overwrite: true }); - } - // Copy sprinkle assets - paths = []; - for (let sprinkle of sprinkles) { - let path = `../app/sprinkles/${sprinkle}/assets/`; - if (fs.pathExistsSync(path)) fs.copySync(path, publicAssetsDir, { overwrite: true }); - } - return; -}); + // Write file + Logger("Rriting results file..."); + writeFileSync("./bundle.result.json", JSON.stringify(resultsObject)); + Logger("Done.") + }; -// Execute gulp-bundle-assets -gulp.task('bundle', () => { - 'use strict'; - return gulp.src(bundleConfigFile) - .pipe(plugins.ufBundleAssets({ - base: publicAssetsDir - })) - .pipe(plugins.ufBundleAssets.results({ - dest: './' - })) - .pipe(gulp.dest(publicAssetsDir)); + // Open stream + Logger("Starting bundle process proper..."); + return src(sources) + .pipe(new Bundler(rawConfig, bundleBuilder, bundleResults)) + .pipe(prune(publicAssetsDir)) + .pipe(dest(publicAssetsDir)); }); - - /** - * Clean up tasks + * Run all frontend tasks. */ +task("frontend", series("assets-install", "bundle")); -gulp.task('public-clean', () => { - 'use strict'; - return del(publicAssetsDir, { force: true }); -}); +/** + * + */ +task("clean", (done) => { + try { + Logger("Cleaning vendor assets..."); + deleteSync(vendorAssetsDir, { force: true }); + Logger("Done."); -// Clean up temporary bundling files -gulp.task('bundle-clean', () => { - 'use strict'; - return del(bundleConfigFile, { force: true }); -}); + Logger("Cleaning public assets..."); + deleteSync(publicAssetsDir, { force: true }) + Logger("Done."); -// Deletes assets fetched by assets-install -gulp.task('assets-clean', () => { - 'use strict'; - return del('../app/assets/*', { force: true }); + done(); + } + catch (error) { + done(error); + } }); - -// Deletes all generated, or acquired files. -gulp.task('clean', ['public-clean', 'bundle-clean', 'assets-clean']); \ No newline at end of file diff --git a/build/package-lock.json b/build/package-lock.json index d9ae5c5f5..5f0dab7a9 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -3,99 +3,70 @@ "lockfileVersion": 1, "dependencies": { "@userfrosting/merge-package-dependencies": { - "version": "1.2.0-rc.2", - "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.0-rc.2.tgz", - "integrity": "sha512-+hDTJMa3PzWqqdXAJ8dRvNNmAFZ2mIQaoFXIJzO6+BvXcRuUciMvw3+HAX60c9O77YhKfLAjnyhkMtHHYtaUTQ==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.1.tgz", + "integrity": "sha512-jv79Suqy087JR1/pc1Gn9Mnp4KJpeUdALFdG2sZS+kiSh68k7jhD/u+k355bhYvcYnsAmmx62BVEXSWiOS2VZQ==", "dev": true, "requires": { - "chalk": "2.3.0", - "fs-extra": "5.0.0", - "lodash": "4.17.4", - "node-exceptions": "3.0.0", + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^2.4.1", + "fs-extra": "^7.0.1", + "lodash": "^4.17.11", + "node-exceptions": "^4.0.1", "package-json-validator": "0.6.3", - "semver": "5.5.0", - "semver-intersect": "1.3.0" + "semver": "^5.6.0", + "semver-intersect": "^1.4.0" }, "dependencies": { "semver": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", - "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", "dev": true } } }, - "accord": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/accord/-/accord-0.23.0.tgz", - "integrity": "sha1-JGjHjlZBLbqTEdOD+4c0UNKGfK8=", + "@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true + }, + "ansi-colors": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", + "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", "dev": true, "requires": { - "convert-source-map": "1.5.0", - "fobject": "0.0.4", - "glob": "7.0.3", - "indx": "0.2.3", - "lodash": "4.11.2", - "resolve": "1.5.0", - "semver": "5.4.1", - "uglify-js": "2.8.29", - "when": "3.7.8" - }, - "dependencies": { - "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", - "dev": true - }, - "glob": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.0.3.tgz", - "integrity": "sha1-CqI1kxpKlqwT1g/6wvuHe9btT1g=", - "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "lodash": { - "version": "4.11.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.11.2.tgz", - "integrity": "sha1-1rQzixEKWOIdrlzrz9u/0rxM2zs=", - "dev": true - } + "ansi-wrap": "^0.1.0" } }, - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "ansi-cyan": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", + "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", "dev": true, - "optional": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "ansi-wrap": "0.1.0" } }, - "align-text": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", - "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "ansi-gray": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", + "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "ansi-wrap": "0.1.0" } }, - "amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", - "dev": true + "ansi-red": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", + "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", + "dev": true, + "requires": { + "ansi-wrap": "0.1.0" + } }, "ansi-regex": { "version": "2.1.1", @@ -104,12 +75,313 @@ "dev": true }, "ansi-styles": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", - "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "ansi-wrap": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", + "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", + "dev": true + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + } + } + }, + "append-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", + "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", "dev": true, "requires": { - "color-convert": "1.9.1" + "buffer-equal": "^1.0.0" } }, "archy": { @@ -119,12 +391,30 @@ "dev": true }, "arr-diff": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", - "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", + "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" + }, + "dependencies": { + "array-slice": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", + "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", + "dev": true + } + } + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "make-iterator": "^1.0.0" } }, "arr-flatten": { @@ -133,6 +423,21 @@ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "dev": true, + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", @@ -145,25 +450,73 @@ "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", "dev": true }, - "array-find-index": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", - "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", - "dev": true + "array-initial": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "dev": true, + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "dev": true, + "requires": { + "is-number": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true + } + } }, "array-slice": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.0.0.tgz", - "integrity": "sha1-5zA08A3MH0CHYAj9IP6ud71LfC8=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", "dev": true }, + "array-sort": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", + "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", + "dev": true, + "requires": { + "default-compare": "^1.0.0", + "get-value": "^2.0.6", + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", "dev": true, "requires": { - "array-uniq": "1.0.3" + "array-uniq": "^1.0.1" } }, "array-uniq": { @@ -172,260 +525,520 @@ "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", "dev": true }, - "array-unique": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", - "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", - "dev": true - }, "arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", "dev": true }, - "asap": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", - "integrity": "sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=", + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", "dev": true }, - "asn1": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", - "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", - "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", - "dev": true, - "optional": true - }, "async": { "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", "dev": true }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "async-done": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", + "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", "dev": true, - "optional": true + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^1.0.7", + "stream-exhaust": "^1.0.1" + } }, - "atob": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/atob/-/atob-1.1.3.tgz", - "integrity": "sha1-lfE2KbEsOlGl0hWr3OKqnzL4B3M=", + "async-each": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", + "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, - "aws-sign2": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", - "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", - "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", - "dev": true, - "optional": true - }, - "balanced-match": { + "async-settle": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", "dev": true, - "optional": true, "requires": { - "tweetnacl": "0.14.5" + "async-done": "^1.2.2" } }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "bluebird": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.3.5.tgz", - "integrity": "sha1-XudH8ce9lnZYtoOTZDCu51OVWjQ=", + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", "dev": true }, - "boom": { - "version": "2.10.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", - "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", + "bach": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", "dev": true, "requires": { - "hoek": "2.16.3" + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" } }, - "bower": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.2.tgz", - "integrity": "sha1-rfU1KcjUrwLvJPuNU0HBQZ0z4vc=", + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", "dev": true }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", "dev": true, "requires": { - "balanced-match": "1.0.0", - "concat-map": "0.0.1" + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } } }, - "braces": { - "version": "1.8.5", - "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", - "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", - "dev": true, - "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" - } + "beeper": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", + "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", + "dev": true }, - "bufferstreams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bufferstreams/-/bufferstreams-1.0.1.tgz", - "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", + "binary-extensions": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", + "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", + "dev": true + }, + "bower": { + "version": "1.8.4", + "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz", + "integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, + "buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", + "dev": true + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, "builtin-modules": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", "dev": true }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, "camelcase": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", - "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", "dev": true }, - "camelcase-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", - "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "dev": true, "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chokidar": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", + "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.0", + "braces": "^2.3.0", + "fsevents": "^1.2.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "lodash.debounce": "^4.0.8", + "normalize-path": "^2.1.1", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0", + "upath": "^1.0.5" }, "dependencies": { - "camelcase": { + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "is-extglob": { "version": "2.1.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", - "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", + "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true } } }, - "caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", - "dev": true, - "optional": true - }, - "center-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", - "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", "dev": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, - "chalk": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz", - "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==", + "clean-css": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", + "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", "dev": true, "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.5.0" + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, - "clean-css": { - "version": "3.4.28", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", - "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", "dev": true, "requires": { - "commander": "2.8.1", - "source-map": "0.4.4" + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" } }, - "cliui": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", - "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", + "dev": true + }, + "clone-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", + "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", + "dev": true + }, + "clone-stats": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", + "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", + "dev": true + }, + "cloneable-readable": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", + "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", "dev": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", - "wordwrap": "0.0.2" + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" }, "dependencies": { - "wordwrap": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", - "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } } } }, - "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", "dev": true }, - "co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", + "collection-map": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", "dev": true, - "optional": true + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } }, - "coffee-script": { - "version": "1.12.7", - "resolved": "https://registry.npmjs.org/coffee-script/-/coffee-script-1.12.7.tgz", - "integrity": "sha512-fLeEhqwymYat/MpTPUjSKHVYYl0ec2mOyALEMLmzr5i1isuG+6jfI2j2d5oBO3VIzgUXgBVIcOT9uH1TFxBckw==", - "dev": true + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } }, "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { "color-name": "1.1.3" @@ -437,23 +1050,23 @@ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true }, - "combined-stream": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", - "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true }, "commander": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", - "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", - "dev": true, - "requires": { - "graceful-readlink": "1.0.1" - } + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "component-emitter": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", + "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", + "dev": true }, "concat-map": { "version": "0.0.1", @@ -461,423 +1074,412 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", "dev": true }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, "concat-with-sourcemaps": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.0.4.tgz", - "integrity": "sha1-9Vs74q60dgGxCi1SWcz7cP0vHdY=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.6.1" }, "dependencies": { "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true } } }, "convert-source-map": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", - "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", + "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", "dev": true }, + "copy-props": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", + "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", + "dev": true, + "requires": { + "each-props": "^1.3.0", + "is-plain-object": "^2.0.1" + } + }, "core-util-is": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", "dev": true }, - "cryptiles": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", - "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", - "dev": true, - "optional": true, - "requires": { - "boom": "2.10.1" - } - }, "css": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.1.tgz", - "integrity": "sha1-c6TIHehdtmTU7mdPfUcIXjstVdw=", + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", "dev": true, "requires": { - "inherits": "2.0.3", - "source-map": "0.1.43", - "source-map-resolve": "0.3.1", - "urix": "0.1.0" + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" }, "dependencies": { "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", - "dev": true, - "requires": { - "amdefine": "1.0.1" - } + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true } } }, - "currently-unhandled": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", - "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "d": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", "dev": true, "requires": { - "array-find-index": "1.0.2" + "es5-ext": "^0.10.9" } }, - "dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dateformat": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", + "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, - "optional": true, "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } + "ms": "2.0.0" } }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "deap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/deap/-/deap-1.0.0.tgz", - "integrity": "sha1-sUi/gkMKJ2mbdIOgPra2dYW/yIg=", - "dev": true - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", "dev": true }, - "defaults": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", - "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", - "dev": true, - "requires": { - "clone": "1.0.3" - } - }, - "del": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", - "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", - "dev": true, - "requires": { - "globby": "5.0.0", - "is-path-cwd": "1.0.0", - "is-path-in-cwd": "1.0.0", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "rimraf": "2.6.2" - } - }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", - "dev": true - }, - "deprecated": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deprecated/-/deprecated-0.0.1.tgz", - "integrity": "sha1-+cmvVGSvoeepcUWKi97yqpTVuxk=", + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, - "detect-file": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-0.1.0.tgz", - "integrity": "sha1-STXe39lIhkjgBrASlWbpOGcR6mM=", + "default-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", + "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", "dev": true, "requires": { - "fs-exists-sync": "0.1.0" + "kind-of": "^5.0.2" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, - "dotenv": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-4.0.0.tgz", - "integrity": "sha1-hk7xN5rO1Vzm+V3r7NzhefegzR0=", - "dev": true - }, - "duplexer": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", - "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", + "default-resolution": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", "dev": true }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", "dev": true, "requires": { - "readable-stream": "1.1.14" + "object-keys": "^1.0.12" } }, - "duplexify": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.5.1.tgz", - "integrity": "sha512-j5goxHTwVED1Fpe5hh3q9R93Kip0Bg2KVAt4f8CEYM3UEwYcPSvWbXaUQOzdX/HtiNomipv+gU7ASQPDbV7pGQ==", + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", "dev": true, "requires": { - "end-of-stream": "1.4.0", - "inherits": "2.0.3", - "readable-stream": "2.3.3", - "stream-shift": "1.0.0" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" }, "dependencies": { - "end-of-stream": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.0.tgz", - "integrity": "sha1-epDYM+/abPpurA9JSduw+tOmMgY=", + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", "dev": true, "requires": { - "once": "1.4.0" + "kind-of": "^6.0.0" } }, - "isarray": { + "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "kind-of": "^6.0.0" } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, - "ecc-jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", - "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", + "del": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", + "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", "dev": true, - "optional": true, "requires": { - "jsbn": "0.1.1" + "globby": "^6.1.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "p-map": "^1.1.1", + "pify": "^3.0.0", + "rimraf": "^2.2.8" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } } }, - "emitter-mixin": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/emitter-mixin/-/emitter-mixin-0.0.3.tgz", - "integrity": "sha1-WUjLKG8uSO3DslGnz8H3iDOW1lw=", + "dotenv": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.1.0.tgz", + "integrity": "sha512-/veDn2ztgRlB7gKmE3i9f6CmDIyXAy6d5nBq+whO9SLX+Zs1sXEgFLPi+aSuWqUuusMfbi84fT8j34fs1HaYUw==", "dev": true }, - "end-of-stream": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-0.1.5.tgz", - "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "once": "1.3.3" + "readable-stream": "~1.1.9" }, "dependencies": { - "once": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz", - "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "wrappy": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true } } }, - "errno": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.4.tgz", - "integrity": "sha1-uJbiOp5ei6M4cfyZar02NfyaHH0=", + "duplexify": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", + "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", "dev": true, "requires": { - "prr": "0.0.0" + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" } }, - "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "each-props": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", + "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-plain-object": "^2.0.1", + "object.defaults": "^1.1.0" } }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } }, - "expand-brackets": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", - "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-arrayish": "^0.2.1" } }, - "expand-range": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz", - "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", + "es5-ext": { + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", "dev": true, "requires": { - "fill-range": "2.2.3" + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" } }, - "expand-tilde": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz", - "integrity": "sha1-C4HrqJflo9MdHD0QL48BRB5VlEk=", + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" } }, - "extend": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", - "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", - "dev": true + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } }, - "extglob": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", - "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" } }, - "extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", "dev": true }, - "fancy-log": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.0.tgz", - "integrity": "sha1-Rb4X0Cu5kX1gzP/UmVyZnmyMmUg=", + "esm": { + "version": "3.0.84", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.0.84.tgz", + "integrity": "sha512-SzSGoZc17S7P+12R9cg21Bdb7eybX25RnIeRZ80xZs+VZ3kdQKzqTp2k4hZJjR7p9l0186TTXSgrxzlMDBktlw==", + "dev": true + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "chalk": "1.1.3", - "time-stamp": "1.1.0" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "is-plain-object": "^2.0.4" } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true } } }, - "filename-regex": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", - "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", - "dev": true - }, - "fill-range": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.3.tgz", - "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" } }, - "find-index": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/find-index/-/find-index-0.1.1.tgz", - "integrity": "sha1-Z101iyyjiS15Whq0cjL4tuLg3eQ=", - "dev": true - }, "find-up": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" - } - }, - "findup-sync": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-0.4.3.tgz", - "integrity": "sha1-QAQ5Kee8YK3wt/SCfExudaDeyhI=", - "dev": true, - "requires": { - "detect-file": "0.1.0", - "is-glob": "2.0.1", - "micromatch": "2.3.11", - "resolve-dir": "0.1.1" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "fined": { @@ -886,11 +1488,11 @@ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.1" + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" }, "dependencies": { "expand-tilde": { @@ -899,32 +1501,34 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1" + "homedir-polyfill": "^1.0.1" } } } }, "first-chunk-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz", - "integrity": "sha1-Wb+1DNkF9g18OUzT2ayqtOatk04=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", + "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } }, "flagged-respawn": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-0.3.2.tgz", - "integrity": "sha1-/xke3c1wiKZ1smEP/8l2vpuAdLU=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", + "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", "dev": true }, - "fobject": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fobject/-/fobject-0.0.4.tgz", - "integrity": "sha1-g5nmuRBdLrjm353MQRI6FxaIrf4=", + "flush-write-stream": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", + "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "semver": "5.4.1", - "when": "3.7.8" + "inherits": "^2.0.1", + "readable-stream": "^2.0.4" } }, "for-in": { @@ -933,55 +1537,34 @@ "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", "dev": true }, - "for-own": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", - "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "for-in": "1.0.2" + "map-cache": "^0.2.2" } }, - "forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", - "dev": true, - "optional": true - }, - "fork-stream": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/fork-stream/-/fork-stream-0.0.4.tgz", - "integrity": "sha1-24Sfznf2cIpfjzhq5TOgkHtUrnA=", - "dev": true - }, - "form-data": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", - "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, - "optional": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.17" + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" } }, - "fs-exists-sync": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/fs-exists-sync/-/fs-exists-sync-0.1.0.tgz", - "integrity": "sha1-mC1ok6+RjnLQjeyehnP/K1qNat0=", - "dev": true - }, - "fs-extra": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", - "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "fs-mkdirp-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", + "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "4.0.0", - "universalify": "0.1.1" + "graceful-fs": "^4.1.11", + "through2": "^2.0.3" } }, "fs.realpath": { @@ -990,1123 +1573,933 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "gaze": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/gaze/-/gaze-0.5.2.tgz", - "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", - "dev": true, - "requires": { - "globule": "0.1.0" - } - }, - "get-imports": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-imports/-/get-imports-1.0.0.tgz", - "integrity": "sha1-R8C07piTUWQsVJdxk79Pyqv1N48=", - "dev": true, - "requires": { - "array-uniq": "1.0.3", - "import-regex": "1.1.0" - } - }, - "get-stdin": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", - "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", - "dev": true - }, - "getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", "dev": true, "optional": true, "requires": { - "assert-plus": "1.0.0" + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" }, "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "abbrev": { + "version": "1.1.1", + "bundled": true, "dev": true, "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "glob-base": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz", - "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", - "dev": true, - "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" - } - }, - "glob-parent": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz", - "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", - "dev": true, - "requires": { - "is-glob": "2.0.1" - } - }, - "glob-stream": { - "version": "3.1.18", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-3.1.18.tgz", - "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", - "dev": true, - "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" - }, - "dependencies": { - "glob": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-4.5.3.tgz", - "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, "dev": true, - "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" - } + "optional": true }, - "minimatch": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-2.0.10.tgz", - "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, "dev": true, + "optional": true, "requires": { - "brace-expansion": "1.1.8" + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" } }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "chownr": { + "version": "1.0.1", + "bundled": true, "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - } - } - }, - "glob-watcher": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-0.0.6.tgz", - "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", - "dev": true, - "requires": { - "gaze": "0.5.2" - } - }, - "glob2base": { - "version": "0.0.12", - "resolved": "https://registry.npmjs.org/glob2base/-/glob2base-0.0.12.tgz", - "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", - "dev": true, - "requires": { - "find-index": "0.1.1" - } - }, - "global-modules": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-0.2.3.tgz", - "integrity": "sha1-6lo77ULG1s6ZWk+KEmm12uIjgo0=", - "dev": true, - "requires": { - "global-prefix": "0.1.5", - "is-windows": "0.2.0" - } - }, - "global-prefix": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-0.1.5.tgz", - "integrity": "sha1-jTvGuNo8qBEqFg2NSW/wRiv+948=", - "dev": true, - "requires": { - "homedir-polyfill": "1.0.1", - "ini": "1.3.4", - "is-windows": "0.2.0", - "which": "1.3.0" - } - }, - "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "1.0.2", - "arrify": "1.0.1", - "glob": "7.1.2", - "object-assign": "4.1.1", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" - } - }, - "globule": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/globule/-/globule-0.1.0.tgz", - "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", - "dev": true, - "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" - }, - "dependencies": { - "glob": { - "version": "3.1.21", - "resolved": "https://registry.npmjs.org/glob/-/glob-3.1.21.tgz", - "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", - "dev": true, - "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" - } + "optional": true }, - "graceful-fs": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz", - "integrity": "sha1-FaSAaldUfLLS2/J/QuiajDRRs2Q=", + "code-point-at": { + "version": "1.1.0", + "bundled": true, "dev": true }, - "inherits": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz", - "integrity": "sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=", + "concat-map": { + "version": "0.0.1", + "bundled": true, "dev": true }, - "lodash": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-1.0.2.tgz", - "integrity": "sha1-j1dWDIO1n8JwvT1WG2kAQ0MOJVE=", + "console-control-strings": { + "version": "1.1.0", + "bundled": true, "dev": true }, - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "debug": { + "version": "2.6.9", + "bundled": true, "dev": true, + "optional": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "ms": "2.0.0" } - } - } - }, - "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", - "dev": true, - "requires": { - "sparkles": "1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "graceful-readlink": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", - "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", - "dev": true - }, - "gulp": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", - "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", - "dev": true, - "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.0.4", - "liftoff": "2.3.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "minipass": "^2.2.1" } }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true }, - "semver": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", - "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", - "dev": true + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "gulp-clean-css": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-2.0.7.tgz", - "integrity": "sha1-2Go9haeQvsg+Pdbd+wPWWmKPm6A=", - "dev": true, - "requires": { - "clean-css": "3.4.28", - "gulp-util": "3.0.8", - "object-assign": "4.1.1", - "readable-stream": "2.3.3", - "vinyl-bufferstream": "1.0.1", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, "dev": true }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "number-is-nan": "^1.0.0" } }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, "dev": true, "requires": { - "safe-buffer": "5.1.1" + "brace-expansion": "^1.1.7" } - } - } - }, - "gulp-coffee": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/gulp-coffee/-/gulp-coffee-2.3.2.tgz", - "integrity": "sha1-6FQTyVpvdpXqFg+1kMxXjz29pbE=", - "dev": true, - "requires": { - "coffee-script": "1.12.7", - "gulp-util": "3.0.8", - "merge": "1.2.0", - "through2": "0.6.5", - "vinyl-sourcemaps-apply": "0.1.4" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" } }, - "source-map": { - "version": "0.1.43", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", - "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "minizlib": { + "version": "1.1.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "amdefine": "1.0.1" + "minipass": "^2.2.1" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "mkdirp": { + "version": "0.5.1", + "bundled": true, "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "minimist": "0.0.8" } }, - "vinyl-sourcemaps-apply": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.1.4.tgz", - "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", + "ms": { + "version": "2.0.0", + "bundled": true, "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "source-map": "0.1.43" + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" } - } - } - }, - "gulp-concat": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.5.2.tgz", - "integrity": "sha1-1kQ3LNwrPNtCGoqUHI104h2BXxQ=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "1.0.4", - "gulp-util": "3.0.8", - "through2": "0.6.5" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, "dev": true, + "optional": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "nopt": { + "version": "4.0.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "abbrev": "1", + "osenv": "^0.1.4" } - } - } - }, - "gulp-concat-css": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/gulp-concat-css/-/gulp-concat-css-2.3.0.tgz", - "integrity": "sha1-TBWGEhqEEf9LLcRPz6TcdA6P4bY=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "lodash.defaults": "3.1.2", - "parse-import": "2.0.0", - "rework": "1.0.1", - "rework-import": "2.1.0", - "rework-plugin-url": "1.1.0", - "through2": "1.1.1" - }, - "dependencies": { - "through2": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-1.1.1.tgz", - "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "readable-stream": "1.1.14", - "xtend": "4.0.1" + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" } - } - } - }, - "gulp-if": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/gulp-if/-/gulp-if-2.0.1.tgz", - "integrity": "sha1-VfPt+Czs389gNapdBoaXmqsNrCg=", - "dev": true, - "requires": { - "gulp-match": "1.0.3", - "ternary-stream": "2.0.1", - "through2": "2.0.3" - } - }, - "gulp-less": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/gulp-less/-/gulp-less-3.1.0.tgz", - "integrity": "sha1-xUwu4BTr5uE1v8sBadtN25NQbeY=", - "dev": true, - "requires": { - "accord": "0.23.0", - "gulp-util": "3.0.8", - "less": "2.7.3", - "object-assign": "4.1.1", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" - } - }, - "gulp-load-plugins": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/gulp-load-plugins/-/gulp-load-plugins-1.5.0.tgz", - "integrity": "sha1-TEGffldk2aDjMGG6uWGPgbc9QXE=", - "dev": true, - "requires": { - "array-unique": "0.2.1", - "fancy-log": "1.3.0", - "findup-sync": "0.4.3", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "micromatch": "2.3.11", - "resolve": "1.5.0" - } - }, - "gulp-match": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/gulp-match/-/gulp-match-1.0.3.tgz", - "integrity": "sha1-kcfA1/Kb7NZgbVfYCn+Hdqh6uo4=", - "dev": true, - "requires": { - "minimatch": "3.0.4" - } - }, - "gulp-order": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/gulp-order/-/gulp-order-1.1.1.tgz", - "integrity": "sha1-C47wgzI1vtZfHvvHnGrtl7HbQek=", - "dev": true, - "requires": { - "minimatch": "0.2.14", - "through": "2.3.8" - }, - "dependencies": { - "lru-cache": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", - "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", - "dev": true }, - "minimatch": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", - "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "npmlog": { + "version": "4.1.2", + "bundled": true, "dev": true, + "optional": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" } - } - } - }, - "gulp-rev": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gulp-rev/-/gulp-rev-4.0.0.tgz", - "integrity": "sha1-Zj2RhOdyJHsvJcSk5XE4h0LlXuk=", - "dev": true, - "requires": { - "gulp-util": "3.0.8", - "object-assign": "2.1.1", - "rev-hash": "1.0.0", - "rev-path": "1.0.0", - "through2": "0.6.5", - "vinyl-file": "1.3.0" - }, - "dependencies": { - "object-assign": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", - "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, "dev": true }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "wrappy": "1" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "os-homedir": { + "version": "1.0.2", + "bundled": true, "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" } - } - } - }, - "gulp-sourcemaps": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.5.2.tgz", - "integrity": "sha1-eW9v9pWklCFfPT1mqnrIU9fnNRE=", - "dev": true, - "requires": { - "convert-source-map": "1.5.0", - "graceful-fs": "3.0.11", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true }, - "convert-source-map": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.5.0.tgz", - "integrity": "sha1-ms1whRxtXf3ZPZKC5e35SgP/RrU=", - "dev": true + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "natives": "1.1.0" + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } } }, "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "version": "2.3.6", + "bundled": true, "dev": true, + "optional": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "rimraf": { + "version": "2.6.2", + "bundled": true, "dev": true, + "optional": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "glob": "^7.0.5" } }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, "dev": true, "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" } - } - } - }, - "gulp-streamify": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/gulp-streamify/-/gulp-streamify-0.0.5.tgz", - "integrity": "sha1-aF0gUSVSrFdlYktBMbSx7K3wDsE=", - "dev": true, - "requires": { - "gulp-util": "2.2.20", - "plexer": "0.0.2", - "readable-stream": "1.1.14" - }, - "dependencies": { - "ansi-regex": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", - "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", - "dev": true }, - "ansi-styles": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", - "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", - "dev": true + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } }, - "chalk": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", - "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "strip-ansi": { + "version": "3.0.1", + "bundled": true, "dev": true, "requires": { - "ansi-styles": "1.1.0", - "escape-string-regexp": "1.0.5", - "has-ansi": "0.1.0", - "strip-ansi": "0.3.0", - "supports-color": "0.2.0" + "ansi-regex": "^2.0.0" } }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, "dev": true, + "optional": true, "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" } }, - "gulp-util": { - "version": "2.2.20", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-2.2.20.tgz", - "integrity": "sha1-1xRuVyiRC9jwR6awseVJvCLb1kw=", + "util-deprecate": { + "version": "1.0.2", + "bundled": true, "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, "requires": { - "chalk": "0.5.1", - "dateformat": "1.0.12", - "lodash._reinterpolate": "2.4.1", - "lodash.template": "2.4.1", - "minimist": "0.2.0", - "multipipe": "0.1.2", - "through2": "0.5.1", - "vinyl": "0.2.3" + "string-width": "^1.0.2" } }, - "has-ansi": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", - "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", + "dev": true + }, + "get-imports": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-imports/-/get-imports-1.0.0.tgz", + "integrity": "sha1-R8C07piTUWQsVJdxk79Pyqv1N48=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1", + "import-regex": "^1.1.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-stream": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", + "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^7.1.1", + "glob-parent": "^3.1.0", + "is-negated-glob": "^1.0.0", + "ordered-read-streams": "^1.0.0", + "pumpify": "^1.3.5", + "readable-stream": "^2.1.5", + "remove-trailing-separator": "^1.0.1", + "to-absolute-glob": "^2.0.0", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "ansi-regex": "0.2.1" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" } }, - "lodash._reinterpolate": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-2.4.1.tgz", - "integrity": "sha1-TxInqlqHEfxjL1sHofRgequLMiI=", + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true }, - "lodash.defaults": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-2.4.1.tgz", - "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1", - "lodash.keys": "2.4.1" - } - }, - "lodash.escape": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-2.4.1.tgz", - "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", - "dev": true, - "requires": { - "lodash._escapehtmlchar": "2.4.1", - "lodash._reunescapedhtml": "2.4.1", - "lodash.keys": "2.4.1" - } - }, - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - }, - "lodash.template": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-2.4.1.tgz", - "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "lodash._escapestringchar": "2.4.1", - "lodash._reinterpolate": "2.4.1", - "lodash.defaults": "2.4.1", - "lodash.escape": "2.4.1", - "lodash.keys": "2.4.1", - "lodash.templatesettings": "2.4.1", - "lodash.values": "2.4.1" + "is-extglob": "^2.1.0" } - }, - "lodash.templatesettings": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-2.4.1.tgz", - "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", + } + } + }, + "glob-watcher": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", + "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-done": "^1.2.0", + "chokidar": "^2.0.0", + "is-negated-glob": "^1.0.0", + "just-debounce": "^1.0.0", + "object.defaults": "^1.1.0" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "glogg": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", + "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "dev": true, + "requires": { + "sparkles": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "gulp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", + "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", + "dev": true, + "requires": { + "glob-watcher": "^5.0.0", + "gulp-cli": "^2.0.0", + "undertaker": "^1.0.0", + "vinyl-fs": "^3.0.0" + }, + "dependencies": { + "fancy-log": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", + "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "lodash._reinterpolate": "2.4.1", - "lodash.escape": "2.4.1" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" } }, - "minimist": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.2.0.tgz", - "integrity": "sha1-Tf/lJdriuGTGbC4jxicdev3s784=", - "dev": true - }, - "strip-ansi": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", - "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "gulp-cli": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", + "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", "dev": true, "requires": { - "ansi-regex": "0.2.1" + "ansi-colors": "^1.0.1", + "archy": "^1.0.0", + "array-sort": "^1.0.0", + "color-support": "^1.1.3", + "concat-stream": "^1.6.0", + "copy-props": "^2.0.1", + "fancy-log": "^1.3.2", + "gulplog": "^1.0.0", + "interpret": "^1.1.0", + "isobject": "^3.0.1", + "liftoff": "^2.5.0", + "matchdep": "^2.0.0", + "mute-stdout": "^1.0.0", + "pretty-hrtime": "^1.0.0", + "replace-homedir": "^1.0.0", + "semver-greatest-satisfied-range": "^1.1.0", + "v8flags": "^3.0.1", + "yargs": "^7.1.0" } }, - "supports-color": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", - "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", "dev": true - }, + } + } + }, + "gulp-clean-css": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-3.10.0.tgz", + "integrity": "sha512-7Isf9Y690o/Q5MVjEylH1H7L8WeZ89woW7DnhD5unTintOdZb67KdOayRgp9trUFo+f9UyJtuatV42e/+kghPg==", + "dev": true, + "requires": { + "clean-css": "4.2.1", + "plugin-error": "1.0.1", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" + }, + "dependencies": { "through2": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", - "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "3.0.0" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - } - } - }, - "vinyl": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.2.3.tgz", - "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", + "version": "2.0.3", + "resolved": "http://registry.npmjs.org/through2/-/through2-2.0.3.tgz", + "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "clone-stats": "0.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" } - }, - "xtend": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", - "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", - "dev": true } } }, - "gulp-uf-bundle-assets": { - "version": "2.27.2", - "resolved": "https://registry.npmjs.org/gulp-uf-bundle-assets/-/gulp-uf-bundle-assets-2.27.2.tgz", - "integrity": "sha1-uET3POm9hOU5nV+rDeBcODXVyPg=", - "dev": true, - "requires": { - "bluebird": "3.3.5", - "duplexer2": "0.0.2", - "graceful-fs": "4.1.4", - "gulp": "3.9.1", - "gulp-clean-css": "2.0.7", - "gulp-coffee": "2.3.2", - "gulp-concat": "2.5.2", - "gulp-concat-css": "2.3.0", - "gulp-if": "2.0.1", - "gulp-less": "3.1.0", - "gulp-order": "1.1.1", - "gulp-rev": "4.0.0", - "gulp-sourcemaps": "1.5.2", - "gulp-streamify": "0.0.5", - "gulp-uglify": "1.5.3", - "gulp-util": "3.0.7", - "lazypipe": "0.2.3", - "lodash": "3.9.3", - "map-stream": "0.0.6", - "merge-stream": "0.1.7", - "mkdirp": "0.5.1", - "pretty-hrtime": "1.0.2", - "readable-stream": "2.0.0", - "through2": "2.0.1", - "vinyl": "1.1.1" + "gulp-concat": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", + "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", + "dev": true, + "requires": { + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" + } + }, + "gulp-concat-css": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/gulp-concat-css/-/gulp-concat-css-3.1.0.tgz", + "integrity": "sha512-iLTBPS+cutlgLyK3bp9DMts+WuS8n2mQpjzQ7p/ZVQc8FO5fvpN+ntg9U6jsuNvPeuii82aKm8XeOzF0nUK+TA==", + "dev": true, + "requires": { + "lodash.defaults": "^3.0.0", + "parse-import": "^2.0.0", + "plugin-error": "^0.1.2", + "rework": "~1.0.0", + "rework-import": "^2.0.0", + "rework-plugin-url": "^1.0.1", + "through2": "~1.1.1", + "vinyl": "^2.1.0" }, "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "arr-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", + "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", "dev": true }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" - } - }, - "dateformat": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-1.0.12.tgz", - "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", + "extend-shallow": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", + "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" - } - }, - "graceful-fs": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz", - "integrity": "sha1-7widKIDwM7ARgjzlyPrnmNp3Xb0=", - "dev": true - }, - "gulp-util": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.7.tgz", - "integrity": "sha1-eJJcS4+LSQBawBoBHFV+YhiUHLs=", - "dev": true, - "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "1.0.12", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", - "replace-ext": "0.0.1", - "through2": "2.0.1", - "vinyl": "0.5.3" - }, - "dependencies": { - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } + "kind-of": "^1.1.0" } }, - "lodash": { - "version": "3.9.3", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.9.3.tgz", - "integrity": "sha1-AVnoaDL+/8bWHYUrEqlTuZSWvTI=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", "dev": true }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "kind-of": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", + "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", "dev": true }, - "pretty-hrtime": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz", - "integrity": "sha1-cMqW9NBiikQ7kYdY95QWqae8n6g=", - "dev": true + "plugin-error": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", + "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", + "dev": true, + "requires": { + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" + } }, "readable-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.0.0.tgz", - "integrity": "sha1-q24pLYrjku+IgVExBVTnB4/LOMo=", + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "process-nextick-args": "1.0.7", - "string_decoder": "0.10.31", - "util-deprecate": "1.0.2" + "string_decoder": "~0.10.x" } }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", "dev": true }, "through2": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.1.tgz", - "integrity": "sha1-OE51MU1J8y3hLuu4E2uOtrXVnak=", - "dev": true, - "requires": { - "readable-stream": "2.0.0", - "xtend": "4.0.1" - } - }, - "vinyl": { "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.1.1.tgz", - "integrity": "sha1-eUCIfu8JOB6zYmrEwPmrU9S35FA=", + "resolved": "http://registry.npmjs.org/through2/-/through2-1.1.1.tgz", + "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", "dev": true, "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" + "readable-stream": ">=1.1.13-1 <1.2.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } } } }, - "gulp-uglify": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/gulp-uglify/-/gulp-uglify-1.5.3.tgz", - "integrity": "sha1-YKALOXWrpBhkQqSUl56d+j8T0NY=", + "gulp-prune": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/gulp-prune/-/gulp-prune-0.2.0.tgz", + "integrity": "sha1-a7jady8PaMcAjv/TexqiXAuJ2A8=", "dev": true, "requires": { - "deap": "1.0.0", - "fancy-log": "1.3.0", - "gulp-util": "3.0.8", - "isobject": "2.1.0", - "through2": "2.0.3", - "uglify-js": "2.6.2", - "uglify-save-license": "0.4.1", - "vinyl-sourcemaps-apply": "0.2.1" + "globby": "^5.0.0", + "gulp-util": "^3.0.7" }, "dependencies": { - "async": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", - "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", - "dev": true - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "uglify-js": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.2.tgz", - "integrity": "sha1-9QvoikLNOWpiUdxSqzcvccwS/vA=", + "globby": { + "version": "5.0.0", + "resolved": "http://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", "dev": true, "requires": { - "async": "0.2.10", - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } } } }, + "gulp-rev": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/gulp-rev/-/gulp-rev-9.0.0.tgz", + "integrity": "sha512-Ytx/uzDA2xNxHlPG8GReS1ut00msd0HlKDk9Ai/0xF2yvg+DAeGRAviCFlQzQmdZtqAoXznYspwWoGEoxDvhyA==", + "dev": true, + "requires": { + "modify-filename": "^1.1.0", + "plugin-error": "^1.0.1", + "rev-hash": "^2.0.0", + "rev-path": "^2.0.0", + "sort-keys": "^2.0.0", + "through2": "^2.0.0", + "vinyl": "^2.1.0", + "vinyl-file": "^3.0.0" + } + }, + "gulp-uf-bundle-assets": { + "version": "3.0.0-alpha.4", + "resolved": "https://registry.npmjs.org/gulp-uf-bundle-assets/-/gulp-uf-bundle-assets-3.0.0-alpha.4.tgz", + "integrity": "sha512-WlIggdxNru5rPBCKtL3HNhAmFIjCzJC0AsO9w+smtwUtuwSuSuSkqzvf11X1CLCfp1LibgYerkIXQ0doTk1+LQ==", + "dev": true, + "requires": { + "esm": "^3.0.84", + "just-extend": "^4.0.2", + "plugin-error": "^1.0.1", + "vinyl": "^2.2.0" + } + }, + "gulp-uglify-es": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/gulp-uglify-es/-/gulp-uglify-es-1.0.4.tgz", + "integrity": "sha512-UMRufZsBmQizCYpftutaiVoLswpbzFEfY90EJLU4YlTgculeHnanb794s88TMd5tpCZVC638sAX6JrLVYTP/Wg==", + "dev": true, + "requires": { + "o-stream": "^0.2.2", + "plugin-error": "^1.0.1", + "terser": "^3.7.5", + "vinyl": "^2.1.0", + "vinyl-sourcemaps-apply": "^0.2.1" + } + }, "gulp-util": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.2.0", - "fancy-log": "1.3.0", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" + "through2": "^2.0.0", + "vinyl": "^0.5.0" }, "dependencies": { "ansi-styles": { @@ -2117,20 +2510,32 @@ }, "chalk": { "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" } }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true + }, + "clone-stats": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", + "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", + "dev": true + }, "minimist": { "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true }, @@ -2140,11 +2545,28 @@ "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", "dev": true }, + "replace-ext": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", + "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "dev": true + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true + }, + "vinyl": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", + "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } } } }, @@ -2154,25 +2576,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.0" - } - }, - "har-schema": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", - "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", - "dev": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", - "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", - "dev": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "glogg": "^1.0.0" } }, "has-ansi": { @@ -2181,13 +2585,13 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-flag": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", - "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", "dev": true }, "has-gulplog": { @@ -2196,61 +2600,89 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" } }, - "hawk": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", - "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, - "optional": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } } }, - "hoek": { - "version": "2.16.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", - "dev": true - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "parse-passwd": "1.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } } }, - "hosted-git-info": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.5.0.tgz", - "integrity": "sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg==", - "dev": true - }, - "http-signature": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", - "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", + "homedir-polyfill": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", + "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, - "optional": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.13.1" + "parse-passwd": "^1.0.0" } }, - "image-size": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", - "integrity": "sha1-Cd/Uq50g4p6xw+gLiZA3jfnjy5w=", - "dev": true, - "optional": true + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", + "dev": true }, "import-regex": { "version": "1.1.0", @@ -2258,29 +2690,14 @@ "integrity": "sha1-pVxS5McFx2XKIQ6SQqBrvMiqf2Y=", "dev": true }, - "indent-string": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", - "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", - "dev": true, - "requires": { - "repeating": "2.0.1" - } - }, - "indx": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/indx/-/indx-0.2.3.tgz", - "integrity": "sha1-Fdz1bunPZcAjTFE8J/vVgOcPvFA=", - "dev": true - }, "inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -2296,9 +2713,15 @@ "dev": true }, "interpret": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.0.4.tgz", - "integrity": "sha1-ggzdWIuGj/sZGoCVBtbJyPISsbA=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", + "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", + "dev": true + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, "ip-regex": { @@ -2308,13 +2731,30 @@ "dev": true }, "is-absolute": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.2.6.tgz", - "integrity": "sha1-IN5p89uULvLYe5wto28XIjWxtes=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "dev": true, + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + }, + "dependencies": { + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + } + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "is-relative": "0.2.1", - "is-windows": "0.2.0" + "kind-of": "^3.0.2" } }, "is-arrayish": { @@ -2323,6 +2763,15 @@ "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", "dev": true }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", @@ -2331,26 +2780,39 @@ }, "is-builtin-module": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, - "is-dotfile": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz", - "integrity": "sha1-pqLzL/0t+wT1yiXs0Pa4PPeYoeE=", - "dev": true + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } }, - "is-equal-shallow": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz", - "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", "dev": true, "requires": { - "is-primitive": "2.0.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } } }, "is-extendable": { @@ -2359,38 +2821,20 @@ "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", "dev": true }, - "is-extglob": { + "is-fullwidth-code-point": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", - "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", - "dev": true - }, - "is-finite": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.0.2.tgz", - "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, - "is-glob": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", - "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", - "dev": true, - "requires": { - "is-extglob": "1.0.0" - } - }, - "is-number": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", - "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } + "is-negated-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", + "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", + "dev": true }, "is-path-cwd": { "version": "1.0.0", @@ -2399,30 +2843,36 @@ "dev": true }, "is-path-in-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.0.tgz", - "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", "dev": true, "requires": { - "is-path-inside": "1.0.0" + "is-path-inside": "^1.0.0" } }, "is-path-inside": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz", - "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", "dev": true, "requires": { - "path-is-inside": "1.0.2" + "path-is-inside": "^1.0.1" } }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, "is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" }, "dependencies": { "isobject": { @@ -2433,41 +2883,22 @@ } } }, - "is-posix-bracket": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", - "integrity": "sha1-MzTceXdDaOkvAW5vvAqI9c1ua8Q=", - "dev": true - }, - "is-primitive": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz", - "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", - "dev": true - }, "is-relative": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.2.1.tgz", - "integrity": "sha1-0n9MfVFtF1+2ENuEu+7yPDvJeqU=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, "requires": { - "is-unc-path": "0.1.2" + "is-unc-path": "^1.0.0" } }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true, - "optional": true - }, "is-unc-path": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-0.1.2.tgz", - "integrity": "sha1-arBTpyVzwQJQ/0FqOBTDUXivObk=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, "requires": { - "unc-path-regex": "0.1.2" + "unc-path-regex": "^0.1.2" } }, "is-utf8": { @@ -2476,16 +2907,16 @@ "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, - "is-windows": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-0.2.0.tgz", - "integrity": "sha1-3hqm1j6indJIc3tp8f+LgALSEIw=", + "is-valid-glob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", + "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", "dev": true }, "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", "dev": true }, "isexe": { @@ -2494,199 +2925,479 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - } - } - }, - "isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", - "dev": true, - "optional": true - }, - "jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", - "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", - "dev": true, - "optional": true - }, "json-stable-stringify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, - "optional": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", - "dev": true, - "optional": true - }, "jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.6" } }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", + "dev": true + }, + "just-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", + "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", + "dev": true + }, + "just-extend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", + "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, - "optional": true + "requires": { + "is-buffer": "^1.1.5" + } }, - "jsprim": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", - "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "last-run": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "dev": true, + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "dev": true, + "requires": { + "invert-kv": "^1.0.0" + } + }, + "lead": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", + "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", "dev": true, - "optional": true, "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.2.3", - "verror": "1.10.0" + "flush-write-stream": "^1.0.2" + } + }, + "liftoff": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", + "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" }, "dependencies": { - "assert-plus": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, - "optional": true - } - } - }, - "junk": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/junk/-/junk-1.0.3.tgz", - "integrity": "sha1-h75jSIZJy9ym9Tqzm+yczSNH9ZI=", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "1.1.6" - } - }, - "lazy-cache": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", - "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", - "dev": true - }, - "lazypipe": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/lazypipe/-/lazypipe-0.2.3.tgz", - "integrity": "sha1-RUtKvmW4+MP4ivI10AmLXdXcbk4=", - "dev": true, - "requires": { - "stream-combiner": "0.2.2" - } - }, - "less": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", - "integrity": "sha512-KPdIJKWcEAb02TuJtaLrhue0krtRLoRoo7x6BNJIBelO00t/CCdJQUnHW5V34OnHMWzIktSalJxRO+FvytQlCQ==", - "dev": true, - "requires": { - "errno": "0.1.4", - "graceful-fs": "4.1.11", - "image-size": "0.5.5", - "mime": "1.4.1", - "mkdirp": "0.5.1", - "promise": "7.3.1", - "request": "2.81.0", - "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, - "optional": true + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } } } }, - "liftoff": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.3.0.tgz", - "integrity": "sha1-qY8v9nGD2Lp8+soQVIvX/wVQs4U=", - "dev": true, - "requires": { - "extend": "3.0.1", - "findup-sync": "0.4.3", - "fined": "1.1.0", - "flagged-respawn": "0.3.2", - "lodash.isplainobject": "4.0.6", - "lodash.isstring": "4.0.1", - "lodash.mapvalues": "4.6.0", - "rechoir": "0.6.2", - "resolve": "1.5.0" - } - }, "load-json-file": { "version": "1.1.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - } + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" } }, "lodash": { - "version": "4.17.4", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", "dev": true }, "lodash._baseassign": { @@ -2695,8 +3406,8 @@ "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash.keys": "3.1.2" + "lodash._basecopy": "^3.0.0", + "lodash.keys": "^3.0.0" } }, "lodash._basecopy": { @@ -2729,56 +3440,23 @@ "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", "dev": true, "requires": { - "lodash._bindcallback": "3.0.1", - "lodash._isiterateecall": "3.0.9", - "lodash.restparam": "3.6.1" - } - }, - "lodash._escapehtmlchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapehtmlchar/-/lodash._escapehtmlchar-2.4.1.tgz", - "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", - "dev": true, - "requires": { - "lodash._htmlescapes": "2.4.1" + "lodash._bindcallback": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash.restparam": "^3.0.0" } }, - "lodash._escapestringchar": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._escapestringchar/-/lodash._escapestringchar-2.4.1.tgz", - "integrity": "sha1-7P4iYYoq3lC/7qQ5N+Ud9m8O23I=", - "dev": true - }, "lodash._getnative": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", "dev": true }, - "lodash._htmlescapes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._htmlescapes/-/lodash._htmlescapes-2.4.1.tgz", - "integrity": "sha1-MtFL8IRLbeb4tioFG09nwii2JMs=", - "dev": true - }, "lodash._isiterateecall": { "version": "3.0.9", "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", "dev": true }, - "lodash._isnative": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._isnative/-/lodash._isnative-2.4.1.tgz", - "integrity": "sha1-PqZAS3hKe+g2x7V1gOHN95sUgyw=", - "dev": true - }, - "lodash._objecttypes": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._objecttypes/-/lodash._objecttypes-2.4.1.tgz", - "integrity": "sha1-fAt/admKH3ZSn4kLDNsbTf7BHBE=", - "dev": true - }, "lodash._reescape": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", @@ -2797,63 +3475,37 @@ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, - "lodash._reunescapedhtml": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._reunescapedhtml/-/lodash._reunescapedhtml-2.4.1.tgz", - "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", - "dev": true, - "requires": { - "lodash._htmlescapes": "2.4.1", - "lodash.keys": "2.4.1" - }, - "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } - } - } - }, "lodash._root": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", "dev": true }, - "lodash._shimkeys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash._shimkeys/-/lodash._shimkeys-2.4.1.tgz", - "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1" - } - }, "lodash.assign": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", "dev": true, "requires": { - "lodash._baseassign": "3.2.0", - "lodash._createassigner": "3.1.1", - "lodash.keys": "3.1.2" + "lodash._baseassign": "^3.0.0", + "lodash._createassigner": "^3.0.0", + "lodash.keys": "^3.0.0" } }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, "lodash.defaults": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=", "dev": true, "requires": { - "lodash.assign": "3.2.0", - "lodash.restparam": "3.6.1" + "lodash.assign": "^3.0.0", + "lodash.restparam": "^3.0.0" } }, "lodash.escape": { @@ -2862,7 +3514,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "3.0.1" + "lodash._root": "^3.0.0" } }, "lodash.isarguments": { @@ -2877,44 +3529,17 @@ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", "dev": true }, - "lodash.isobject": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", - "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", - "dev": true, - "requires": { - "lodash._objecttypes": "2.4.1" - } - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=", - "dev": true - }, - "lodash.isstring": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=", - "dev": true - }, "lodash.keys": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" } }, - "lodash.mapvalues": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz", - "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw=", - "dev": true - }, "lodash.restparam": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", @@ -2927,15 +3552,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" } }, "lodash.templatesettings": { @@ -2944,202 +3569,419 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" } }, - "lodash.values": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.values/-/lodash.values-2.4.1.tgz", - "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", + "make-iterator": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", "dev": true, "requires": { - "lodash.keys": "2.4.1" + "kind-of": "^6.0.2" }, "dependencies": { - "lodash.keys": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-2.4.1.tgz", - "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", - "dev": true, - "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" - } + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, - "longest": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", - "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=", - "dev": true - }, - "loud-rejection": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", - "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", - "dev": true, - "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" - } - }, "map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", "dev": true }, - "map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", - "dev": true - }, - "map-stream": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.6.tgz", - "integrity": "sha1-0u9OuBGihkTHqJiZhcacL91JaCc=", - "dev": true - }, - "maximatch": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/maximatch/-/maximatch-0.1.0.tgz", - "integrity": "sha1-hs2NawTJ8wfAWmuUGZBtA2D7E6I=", + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-union": "1.0.2", - "arrify": "1.0.1", - "minimatch": "3.0.4" + "object-visit": "^1.0.0" } }, - "meow": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", - "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "matchdep": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", + "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", "dev": true, "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" + "findup-sync": "^2.0.0", + "micromatch": "^3.0.4", + "resolve": "^1.4.0", + "stack-trace": "0.0.10" }, "dependencies": { - "minimist": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "findup-sync": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", + "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", "dev": true - } - } - }, - "merge": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/merge/-/merge-1.2.0.tgz", - "integrity": "sha1-dTHjnUlJwoGma4xabgJl6LBYlNo=", - "dev": true - }, - "merge-array-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/merge-array-object/-/merge-array-object-1.0.5.tgz", - "integrity": "sha1-uBfILEGnzgCr9u2CHNscbVM7bRk=", - "dev": true, - "requires": { - "lodash": "4.17.4" - } - }, - "merge-stream": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-0.1.7.tgz", - "integrity": "sha1-Md664T+XN7oX97T74zwWV0yG/Hk=", - "dev": true, - "requires": { - "through2": "0.6.5" - }, - "dependencies": { - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + }, + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" + "is-extglob": "^2.1.0" } }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" } } } }, - "micromatch": { - "version": "2.3.11", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", - "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", - "dev": true, - "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" - } - }, - "mime": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", - "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", - "dev": true, - "optional": true - }, - "mime-db": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", - "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", - "dev": true - }, - "mime-types": { - "version": "2.1.17", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", - "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", - "dev": true, - "requires": { - "mime-db": "1.30.0" - } - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", "dev": true, "requires": { - "brace-expansion": "1.1.8" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -3148,20 +3990,24 @@ "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", "dev": true }, - "mkdirp": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", - "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "mixin-deep": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", + "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", "dev": true, "requires": { - "minimist": "0.0.8" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { - "minimist": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", - "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", - "dev": true + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } } } }, @@ -3171,6 +4017,12 @@ "integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=", "dev": true }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, "multipipe": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", @@ -3180,16 +4032,74 @@ "duplexer2": "0.0.2" } }, - "natives": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.0.tgz", - "integrity": "sha1-6f+EFBimsux6SV6TmYT3jxY+bjE=", + "mute-stdout": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", + "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", + "dev": true + }, + "nan": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", + "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } + }, + "next-tick": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", "dev": true }, "node-exceptions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-3.0.0.tgz", - "integrity": "sha512-pFhMAqdN1avrFwtZs66HxYiVnbnH9wjXB4m8IKs5Z9+r7U5voqxT+EDbVkRfge+V7JnkOgKhN4HfKBn1o5g9Wg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-4.0.1.tgz", + "integrity": "sha512-KJI+FawYOv74x60H6+zrBPfO2vvp9m0pHZi6SH8BBBuc67Irv11DsqY4Le4EBFq1/T5aXFU3hkLrMgtW7RNXxA==", "dev": true }, "normalize-package-data": { @@ -3198,10 +4108,10 @@ "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "dev": true, "requires": { - "hosted-git-info": "2.5.0", - "is-builtin-module": "1.0.0", - "semver": "5.4.1", - "validate-npm-package-license": "3.0.1" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { @@ -3210,7 +4120,16 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "^1.0.1" + } + }, + "now-and-later": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", + "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", + "dev": true, + "requires": { + "once": "^1.3.2" } }, "number-is-nan": { @@ -3219,12 +4138,11 @@ "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", "dev": true }, - "oauth-sign": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", - "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", - "dev": true, - "optional": true + "o-stream": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/o-stream/-/o-stream-0.2.2.tgz", + "integrity": "sha512-V3j76KU3g/Gyl8rpdi2z72rn5zguMvTCQgAXfBe3pxEefKqXmOUOD7mvx/mNjykdxGqDVfpSoo8r+WdrkWg/1Q==", + "dev": true }, "object-assign": { "version": "4.1.1", @@ -3232,16 +4150,73 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } + } + }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + }, + "dependencies": { + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, "object.defaults": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "1.0.1", - "array-slice": "1.0.0", - "for-own": "1.0.0", - "isobject": "3.0.1" + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" }, "dependencies": { "for-own": { @@ -3250,7 +4225,7 @@ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } }, "isobject": { @@ -3261,14 +4236,25 @@ } } }, - "object.omit": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz", - "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", + "object.map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } } }, "object.pick": { @@ -3277,7 +4263,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" }, "dependencies": { "isobject": { @@ -3288,13 +4274,34 @@ } } }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "dev": true, + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + }, + "dependencies": { + "for-own": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "dev": true, + "requires": { + "for-in": "^1.0.1" + } + } + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, "optimist": { @@ -3303,31 +4310,32 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.10", - "wordwrap": "0.0.3" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" } }, - "orchestrator": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", - "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", + "ordered-read-streams": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", + "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", "dev": true, "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.0" + "readable-stream": "^2.0.1" } }, - "ordered-read-streams": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.1.0.tgz", - "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", - "dev": true + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "^1.0.0" + } }, - "os-homedir": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", - "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", + "p-map": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", + "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", "dev": true }, "package-json-validator": { @@ -3336,30 +4344,18 @@ "integrity": "sha512-juKiFboV4UKUvWQ+OSxstnyukhuluyuEoFmgZw1Rx21XzmwlgDWLcbl3qzjA3789IRORYhVFs7cmAO0YFGwHCg==", "dev": true, "requires": { - "optimist": "0.6.1" + "optimist": "~0.6.0" } }, "parse-filepath": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.1.tgz", - "integrity": "sha1-FZ1hVdQ5BNFsEO9piRHaHpGWm3M=", - "dev": true, - "requires": { - "is-absolute": "0.2.6", - "map-cache": "0.2.2", - "path-root": "0.1.1" - } - }, - "parse-glob": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz", - "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" } }, "parse-import": { @@ -3368,7 +4364,7 @@ "integrity": "sha1-KyR0Aw4AirmNt2xLy/TbWucwb18=", "dev": true, "requires": { - "get-imports": "1.0.0" + "get-imports": "^1.0.0" } }, "parse-json": { @@ -3377,7 +4373,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.2.0" } }, "parse-passwd": { @@ -3386,13 +4382,25 @@ "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", "dev": true }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, "path-exists": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "^2.0.0" } }, "path-is-absolute": { @@ -3419,7 +4427,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "0.1.2" + "path-root-regex": "^0.1.0" } }, "path-root-regex": { @@ -3434,18 +4442,11 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, - "performance-now": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", - "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", - "dev": true, - "optional": true - }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", @@ -3464,22 +4465,33 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, - "plexer": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/plexer/-/plexer-0.0.2.tgz", - "integrity": "sha1-Ij1YAGKKBkagCX0wq1doZqLzeE4=", + "plugin-error": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", + "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", "dev": true, "requires": { - "readable-stream": "1.1.14" + "ansi-colors": "^1.0.1", + "arr-diff": "^4.0.0", + "arr-union": "^3.1.0", + "extend-shallow": "^3.0.2" + }, + "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + } } }, - "preserve": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz", - "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", "dev": true }, "pretty-hrtime": { @@ -3494,52 +4506,310 @@ "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", "dev": true }, - "promise": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", - "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", "dev": true, "requires": { - "asap": "2.0.6" + "end-of-stream": "^1.1.0", + "once": "^1.3.1" } }, - "prr": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/prr/-/prr-0.0.0.tgz", - "integrity": "sha1-GoS4WQgyVQFBGFPQCB7j+obikmo=", - "dev": true + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } }, - "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "read-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, - "optional": true + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } }, - "qs": { - "version": "6.4.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", - "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, - "optional": true + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", + "dev": true + } + } }, - "randomatic": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz", - "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==", + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" }, "dependencies": { + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -3548,99 +4818,84 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { - "is-buffer": "1.1.6" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } } } }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, "rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.5.0" + "resolve": "^1.1.6" } }, - "recursive-copy": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/recursive-copy/-/recursive-copy-2.0.7.tgz", - "integrity": "sha1-JNuFxxKdj63uQC5UAM/PDLYPyjw=", + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", "dev": true, "requires": { - "del": "2.2.2", - "emitter-mixin": "0.0.3", - "errno": "0.1.4", - "graceful-fs": "4.1.11", - "junk": "1.0.3", - "maximatch": "0.1.0", - "mkdirp": "0.5.1", - "pify": "2.3.0", - "promise": "7.3.1", - "slash": "1.0.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, - "redent": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", - "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "remove-bom-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", + "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", "dev": true, "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" + "is-buffer": "^1.1.5", + "is-utf8": "^0.2.1" } }, - "regex-cache": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz", - "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==", + "remove-bom-stream": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", + "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", "dev": true, "requires": { - "is-equal-shallow": "0.1.3" + "remove-bom-buffer": "^3.0.0", + "safe-buffer": "^5.1.0", + "through2": "^2.0.3" } }, "remove-trailing-separator": { @@ -3661,69 +4916,51 @@ "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", "dev": true }, - "repeating": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/repeating/-/repeating-2.0.1.tgz", - "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", - "dev": true, - "requires": { - "is-finite": "1.0.2" - } - }, "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", "dev": true }, - "request": { - "version": "2.81.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", - "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", + "replace-homedir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", + "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", "dev": true, - "optional": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.17", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.3", - "tunnel-agent": "0.6.0", - "uuid": "3.1.0" + "homedir-polyfill": "^1.0.1", + "is-absolute": "^1.0.0", + "remove-trailing-separator": "^1.1.0" } }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", + "dev": true + }, "resolve": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, - "resolve-dir": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-0.1.1.tgz", - "integrity": "sha1-shklmlYC+sXFxJatiUpujMQwJh4=", + "resolve-options": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", + "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", "dev": true, "requires": { - "expand-tilde": "1.2.2", - "global-modules": "0.2.3" + "value-or-function": "^3.0.0" } }, "resolve-url": { @@ -3732,19 +4969,25 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, "rev-hash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rev-hash/-/rev-hash-1.0.0.tgz", - "integrity": "sha1-lpk5Weqb+xxZsTrfAqwuNLs3NgM=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rev-hash/-/rev-hash-2.0.0.tgz", + "integrity": "sha1-dyCiNu0MJY3z5kvsA+wEiwW5JMQ=", "dev": true }, "rev-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rev-path/-/rev-path-1.0.0.tgz", - "integrity": "sha1-1My0NqwzcMRgcXXOiOr8XGXF1lM=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/rev-path/-/rev-path-2.0.0.tgz", + "integrity": "sha512-G5R2L9gYu9kEuqPfIFgO9gO+OhBWOAT83HyauOQmGHO6y9Fsa4acv+XsmNhNDrod0HDh1/VxJRmsffThzeHJlQ==", "dev": true, "requires": { - "modify-filename": "1.1.0" + "modify-filename": "^1.0.0" } }, "rework": { @@ -3753,8 +4996,16 @@ "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", "dev": true, "requires": { - "convert-source-map": "0.3.5", - "css": "2.2.1" + "convert-source-map": "^0.3.3", + "css": "^2.0.0" + }, + "dependencies": { + "convert-source-map": { + "version": "0.3.5", + "resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", + "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", + "dev": true + } } }, "rework-import": { @@ -3763,10 +5014,10 @@ "integrity": "sha1-wm7StTFZrHvi7GDaIj74lgPB7x8=", "dev": true, "requires": { - "css": "2.2.1", - "globby": "2.1.0", - "parse-import": "2.0.0", - "url-regex": "3.2.0" + "css": "^2.0.0", + "globby": "^2.0.0", + "parse-import": "^2.0.0", + "url-regex": "^3.0.0" }, "dependencies": { "glob": { @@ -3775,23 +5026,23 @@ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "globby": { "version": "2.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-2.1.0.tgz", + "resolved": "http://registry.npmjs.org/globby/-/globby-2.1.0.tgz", "integrity": "sha1-npGSvNM/Srak+JTl5+qLcTITxII=", "dev": true, "requires": { - "array-union": "1.0.2", - "async": "1.5.2", - "glob": "5.0.15", - "object-assign": "3.0.0" + "array-union": "^1.0.1", + "async": "^1.2.1", + "glob": "^5.0.3", + "object-assign": "^3.0.0" } }, "object-assign": { @@ -3808,7 +5059,7 @@ "integrity": "sha1-Es5G+1sptdk1FGaD9rmM9J0jc7k=", "dev": true, "requires": { - "rework-visit": "1.0.0" + "rework-visit": "^1.0.0" } }, "rework-plugin-url": { @@ -3817,7 +5068,7 @@ "integrity": "sha1-q1PosQV7nV7MHIJz/32xhgg3XEU=", "dev": true, "requires": { - "rework-plugin-function": "1.0.2" + "rework-plugin-function": "^1.0.0" } }, "rework-visit": { @@ -3826,22 +5077,13 @@ "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", "dev": true }, - "right-align": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", - "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", - "dev": true, - "requires": { - "align-text": "0.1.4" - } - }, "rimraf": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "safe-buffer": { @@ -3850,80 +5092,226 @@ "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", "dev": true }, + "safe-regex": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, "semver": { "version": "5.4.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", "dev": true }, + "semver-greatest-satisfied-range": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", + "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", + "dev": true, + "requires": { + "sver-compat": "^1.5.0" + } + }, "semver-intersect": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.3.0.tgz", - "integrity": "sha512-923f1TGXGb2+OCkLvsmNPijmurMQxEMFOhC80N4NL8/Jo5rBKufHZ3sBtJJ7GNhh4RhdsB6+vj+6W68kmr43Lg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", + "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", "dev": true, "requires": { - "semver": "5.4.1" + "semver": "^5.0.0" } }, - "sequencify": { - "version": "0.0.7", - "resolved": "https://registry.npmjs.org/sequencify/-/sequencify-0.0.7.tgz", - "integrity": "sha1-kM/xnQLgcCf9dn9erT57ldHnOAw=", + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", "dev": true }, - "sigmund": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", - "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", - "dev": true + "set-value": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", + "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } }, - "signal-exit": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", - "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=", - "dev": true + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } }, - "slash": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", - "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", - "dev": true + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true + } + } }, - "sntp": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", - "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", "dev": true, - "optional": true, "requires": { - "hoek": "2.16.3" + "kind-of": "^3.2.0" } }, - "source-map": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", - "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", "dev": true, "requires": { - "amdefine": "1.0.1" + "is-plain-obj": "^1.0.0" } }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, "source-map-resolve": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.3.1.tgz", - "integrity": "sha1-YQ9hIqRFuN1RU1oqcbeD38Ekh2E=", + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", + "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", + "dev": true, + "requires": { + "atob": "^2.1.1", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", + "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", "dev": true, "requires": { - "atob": "1.1.3", - "resolve-url": "0.2.1", - "source-map-url": "0.3.0", - "urix": "0.1.0" + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } } }, "source-map-url": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.3.0.tgz", - "integrity": "sha1-fsrxO1e80J2opAxdJp2zN5nUqvk=", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", + "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", "dev": true }, "sparkles": { @@ -3933,66 +5321,77 @@ "dev": true }, "spdx-correct": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-1.0.2.tgz", - "integrity": "sha1-SzBz2TP/UfORLwOsVRlJikFQ20A=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", "dev": true, "requires": { - "spdx-license-ids": "1.2.2" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, - "spdx-expression-parse": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-1.0.4.tgz", - "integrity": "sha1-m98vIOH0DtRH++JzJmGR/O1RYmw=", + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", "dev": true }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, "spdx-license-ids": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-1.2.2.tgz", - "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", + "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", "dev": true }, - "sshpk": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", - "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", "dev": true, - "optional": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } + "extend-shallow": "^3.0.0" } }, - "stream-combiner": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", - "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", + "dev": true + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "duplexer": "0.1.1", - "through": "2.3.8" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + } } }, - "stream-consume": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz", - "integrity": "sha1-pB6tGm1ggc63n2WwYZAbbY89HQ8=", + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", "dev": true }, "stream-shift": { @@ -4001,18 +5400,25 @@ "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", "dev": true }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", "dev": true, - "optional": true + "requires": { + "safe-buffer": "~5.1.0" + } }, "strip-ansi": { "version": "3.0.1", @@ -4020,166 +5426,93 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-bom": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-1.0.0.tgz", - "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" + "is-utf8": "^0.2.0" } }, - "strip-bom-stream": { + "strip-bom-buf": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", - "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz", + "integrity": "sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI=", "dev": true, "requires": { - "first-chunk-stream": "1.0.0", - "strip-bom": "2.0.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - } + "is-utf8": "^0.2.1" } }, - "strip-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", - "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "strip-bom-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", + "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", "dev": true, "requires": { - "get-stdin": "4.0.1" + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" } }, "supports-color": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", - "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=", + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "requires": { - "has-flag": "2.0.0" + "has-flag": "^3.0.0" } }, - "ternary-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ternary-stream/-/ternary-stream-2.0.1.tgz", - "integrity": "sha1-Bk5Im0tb9gumpre8fy9cJ07Pgmk=", + "sver-compat": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", + "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", + "dev": true, + "requires": { + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "terser": { + "version": "3.10.11", + "resolved": "https://registry.npmjs.org/terser/-/terser-3.10.11.tgz", + "integrity": "sha512-iruZ7j14oBbRYJC5cP0/vTU7YOWjN+J1ZskEGoF78tFzXdkK2hbCL/3TRZN8XB+MuvFhvOHMp7WkOCBO4VEL5g==", "dev": true, "requires": { - "duplexify": "3.5.1", - "fork-stream": "0.0.4", - "merge-stream": "1.0.1", - "through2": "2.0.3" + "commander": "~2.17.1", + "source-map": "~0.6.1", + "source-map-support": "~0.5.6" }, "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true - }, - "merge-stream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz", - "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", - "dev": true, - "requires": { - "readable-stream": "2.3.3" - } - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } } } }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", - "dev": true - }, "through2": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", "dev": true, "requires": { - "readable-stream": "2.3.3", - "xtend": "4.0.1" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "readable-stream": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" - } - }, - "string_decoder": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", - "dev": true, - "requires": { - "safe-buffer": "5.1.1" - } - } + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" } }, - "tildify": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", - "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "through2": "~2.0.0", + "xtend": "~4.0.0" } }, "time-stamp": { @@ -4188,68 +5521,71 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, - "tough-cookie": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", - "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", + "to-absolute-glob": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", + "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", "dev": true, - "optional": true, "requires": { - "punycode": "1.4.1" + "is-absolute": "^1.0.0", + "is-negated-glob": "^1.0.0" } }, - "trim-newlines": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", - "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", - "dev": true - }, - "tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, - "optional": true, "requires": { - "safe-buffer": "5.1.1" + "kind-of": "^3.0.2" } }, - "tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", "dev": true, - "optional": true + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + } }, - "uglify-js": { - "version": "2.8.29", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", - "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" }, "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } } } }, - "uglify-save-license": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/uglify-save-license/-/uglify-save-license-0.4.1.tgz", - "integrity": "sha1-lXJsF8xv0XHDYX479NjYKqjEzOE=", - "dev": true + "to-through": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", + "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", + "dev": true, + "requires": { + "through2": "^2.0.3" + } }, - "uglify-to-browserify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", - "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=", + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", "dev": true }, "unc-path-regex": { @@ -4258,16 +5594,130 @@ "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", "dev": true }, - "unique-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-1.0.0.tgz", - "integrity": "sha1-1ZpKdUJ0R9mqbJHnAmP40mpLEEs=", + "undertaker": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", + "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", "dev": true }, + "union-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", + "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "set-value": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", + "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" + } + } + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } + }, "universalify": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.1.tgz", - "integrity": "sha1-+nG63UQ3r0wUiEHjs7Fl+enlkLc=", + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + } + } + }, + "upath": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", + "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", "dev": true }, "urix": { @@ -4282,13 +5732,13 @@ "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", "dev": true, "requires": { - "ip-regex": "1.0.3" + "ip-regex": "^1.0.1" } }, - "user-home": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/user-home/-/user-home-1.1.1.tgz", - "integrity": "sha1-K1viOjK2Onyd640PKNSFcko98ZA=", + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, "util-deprecate": { @@ -4297,170 +5747,96 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, - "uuid": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", - "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", - "dev": true, - "optional": true - }, "v8flags": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-2.1.1.tgz", - "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", + "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", "dev": true, "requires": { - "user-home": "1.1.1" + "homedir-polyfill": "^1.0.1" } }, "validate-npm-package-license": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz", - "integrity": "sha1-KAS6vnEq0zeUWaz74kdGqywwP7w=", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", "dev": true, "requires": { - "spdx-correct": "1.0.2", - "spdx-expression-parse": "1.0.4" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, - "verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "1.3.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", - "dev": true, - "optional": true - } - } + "value-or-function": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", + "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", + "dev": true }, "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - }, - "vinyl-bufferstream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", - "integrity": "sha1-BTeGn1gO/6TKRay0dXnkuf5jCBo=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", + "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", "dev": true, "requires": { - "bufferstreams": "1.0.1" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" } }, "vinyl-file": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-1.3.0.tgz", - "integrity": "sha1-qgVjTTqGe6kUR77bs0r8sm9E9uc=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-3.0.0.tgz", + "integrity": "sha1-sQTZ5ECf+jJfqt1SBkLQo7SIs2U=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "strip-bom": "2.0.0", - "strip-bom-stream": "1.0.0", - "vinyl": "1.2.0" - }, - "dependencies": { - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "0.2.1" - } - }, - "vinyl": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", - "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", - "dev": true, - "requires": { - "clone": "1.0.3", - "clone-stats": "0.0.1", - "replace-ext": "0.0.1" - } - } + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "strip-bom-buf": "^1.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^2.0.1" } }, "vinyl-fs": { - "version": "0.3.14", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-0.3.14.tgz", - "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", - "dev": true, - "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" - }, - "dependencies": { - "clone": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", - "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", - "dev": true - }, - "graceful-fs": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz", - "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", - "dev": true, - "requires": { - "natives": "1.1.0" - } - }, - "readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", - "dev": true, - "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "0.0.1", - "string_decoder": "0.10.31" - } - }, - "through2": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", - "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", - "dev": true, - "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" - } - }, - "vinyl": { - "version": "0.4.6", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", - "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", - "dev": true, - "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" - } - } + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", + "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", + "dev": true, + "requires": { + "fs-mkdirp-stream": "^1.0.0", + "glob-stream": "^6.1.0", + "graceful-fs": "^4.0.0", + "is-valid-glob": "^1.0.0", + "lazystream": "^1.0.0", + "lead": "^1.0.0", + "object.assign": "^4.0.4", + "pumpify": "^1.3.5", + "readable-stream": "^2.3.3", + "remove-bom-buffer": "^3.0.0", + "remove-bom-stream": "^1.2.0", + "resolve-options": "^1.1.0", + "through2": "^2.0.0", + "to-through": "^2.0.0", + "value-or-function": "^3.0.0", + "vinyl": "^2.0.0", + "vinyl-sourcemap": "^1.1.0" + } + }, + "vinyl-sourcemap": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", + "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", + "dev": true, + "requires": { + "append-buffer": "^1.0.2", + "convert-source-map": "^1.5.0", + "graceful-fs": "^4.1.6", + "normalize-path": "^2.1.1", + "now-and-later": "^2.0.0", + "remove-bom-buffer": "^3.0.0", + "vinyl": "^2.0.0" } }, "vinyl-sourcemaps-apply": { @@ -4469,36 +5845,22 @@ "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, "requires": { - "source-map": "0.5.7" - }, - "dependencies": { - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - } + "source-map": "^0.5.1" } }, - "when": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/when/-/when-3.7.8.tgz", - "integrity": "sha1-xxMLan6gRpPoQs3J56Hyqjmjn4I=", - "dev": true - }, "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, - "window-size": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", - "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=", + "which-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", "dev": true }, "wordwrap": { @@ -4507,6 +5869,16 @@ "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", "dev": true }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "dev": true, + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4519,22 +5891,46 @@ "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", "dev": true }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", + "dev": true + }, "yargs": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", - "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "dev": true, + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", + "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", "dev": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", - "window-size": "0.1.0" + "camelcase": "^3.0.0" } }, "yarn": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.3.2.tgz", - "integrity": "sha1-WTl2JYG1tN3NNBjA9r5C3zruGV8=", + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.12.3.tgz", + "integrity": "sha512-8f5rWNDvkhAmCxmn8C0LsNWMxTYVk4VGKiq0sIB6HGZjaZTHsGIH87SUmVDUEd2Wk54bqKoUlbVWgQFCQhRkVw==", "dev": true } } diff --git a/build/package.json b/build/package.json index 70279e9b9..ae83586ff 100755 --- a/build/package.json +++ b/build/package.json @@ -1,25 +1,28 @@ { "private": true, "devDependencies": { - "@userfrosting/merge-package-dependencies": "^1.2.0-rc.2", - "bower": "^1.8.0", - "del": "^2.2.2", - "dotenv": "^4.0.0", - "fs-extra": "^5.0.0", - "gulp": "^3.9.1", - "gulp-load-plugins": "^1.4.0", - "gulp-uf-bundle-assets": "2.28.0", - "merge-array-object": "^1.0.3", - "recursive-copy": "^2.0.5", - "yarn": "^1.3.2" + "@userfrosting/merge-package-dependencies": "^1.2.1", + "bower": "^1.8.4", + "del": "^3.0.0", + "dotenv": "^6.1.0", + "gulp": "^4.0.0", + "gulp-clean-css": "^3.10.0", + "gulp-concat": "^2.6.1", + "gulp-concat-css": "^3.1.0", + "gulp-prune": "^0.2.0", + "gulp-rev": "^9.0.0", + "gulp-uf-bundle-assets": "^3.0.0-alpha.4", + "gulp-uglify-es": "^1.0.4", + "yarn": "^1.12.3" }, "scripts": { - "uf-bundle-build": "gulp bundle-build", "uf-bundle": "gulp bundle", "uf-assets-install": "gulp assets-install", - "uf-bundle-clean": "gulp bundle-clean", - "uf-assets-clean": "gulp assets-clean", - "uf-public-clean": "gulp public-clean", + "uf-frontend": "gulp frontend", "uf-clean": "gulp clean" - } + }, + "engines": { + "node": ">=8.0.0" + }, + "engineStrict": true } From bc3c973dee8e0e186d8b0cb67713779603421d90 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 24 Nov 2018 17:43:56 +1100 Subject: [PATCH 154/237] Sourcemaps for JS bundles --- build/gulpfile.js | 21 +++-- build/package-lock.json | 177 +++++++++++++++++++++++++++++++++++++--- build/package.json | 5 +- 3 files changed, 185 insertions(+), 18 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index bbef76c2b..66aec1e98 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -13,6 +13,7 @@ const { ValidateRawConfig, MergeRawConfigs, default: Bundler } = require("gulp-u const rev = require("gulp-rev"); const prune = require("gulp-prune"); const { resolve: resolvePath } = require("path"); +const sourcemaps = require("gulp-sourcemaps"); // Load environment variables envConfig({ path: "../app/.env" }); @@ -187,9 +188,11 @@ task("bundle", () => { const bundleBuilder = { Scripts: (src, name) => { return src + .pipe(sourcemaps.init()) .pipe(concatJs(name + ".js")) .pipe(minifyJs()) - .pipe(rev()); + .pipe(rev()) + .pipe(sourcemaps.write("./")); }, Styles: (src, name) => { return src @@ -277,16 +280,24 @@ task("bundle", () => { const resultsObject = {}; for (const [name, files] of results) { - if (files.length !== 1) + // Filter to compatible files (permits sourcemaps) + const filteredFiles = []; + for (const file of files) { + if (file.extname === ".js" || file.extname === ".css") { + filteredFiles.push(file); + } + } + + if (filteredFiles.length !== 1) throw new Error(`The bundle ${name} has not generated exactly one file.`); else { if (!resultsObject[name]) { resultsObject[name] = {}; } - if (files[0].extname === ".js") - resultsObject[name].scripts = resolveToAssetPath(files[0].path); + if (filteredFiles[0].extname === ".js") + resultsObject[name].scripts = resolveToAssetPath(filteredFiles[0].path); else - resultsObject[name].styles = resolveToAssetPath(files[0].path); + resultsObject[name].styles = resolveToAssetPath(filteredFiles[0].path); } } // Write file diff --git a/build/package-lock.json b/build/package-lock.json index 5f0dab7a9..e0209f31c 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -2,6 +2,37 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@gulp-sourcemaps/identity-map": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", + "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", + "dev": true, + "requires": { + "acorn": "^5.0.3", + "css": "^2.2.1", + "normalize-path": "^2.1.1", + "source-map": "^0.6.0", + "through2": "^2.0.3" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@gulp-sourcemaps/map-sources": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", + "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", + "dev": true, + "requires": { + "normalize-path": "^2.0.1", + "through2": "^2.0.3" + } + }, "@userfrosting/merge-package-dependencies": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.1.tgz", @@ -32,6 +63,12 @@ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", "dev": true }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, "ansi-colors": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -1178,6 +1215,34 @@ "ms": "2.0.0" } }, + "debug-fabulous": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", + "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", + "dev": true, + "requires": { + "debug": "3.X", + "memoizee": "0.4.X", + "object-assign": "4.X" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + } + } + }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -1297,6 +1362,12 @@ } } }, + "detect-newline": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", + "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", + "dev": true + }, "dotenv": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.1.0.tgz", @@ -1434,6 +1505,16 @@ "integrity": "sha512-SzSGoZc17S7P+12R9cg21Bdb7eybX25RnIeRZ80xZs+VZ3kdQKzqTp2k4hZJjR7p9l0186TTXSgrxzlMDBktlw==", "dev": true }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2289,24 +2370,24 @@ } }, "gulp-clean-css": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-3.10.0.tgz", - "integrity": "sha512-7Isf9Y690o/Q5MVjEylH1H7L8WeZ89woW7DnhD5unTintOdZb67KdOayRgp9trUFo+f9UyJtuatV42e/+kghPg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-4.0.0.tgz", + "integrity": "sha512-/Hs+dmclQfFBSpwrAKd4wTVsahJvrVIg2ga0J7Eo7DKVTVfJrM7wXlfU1mK9iJ9Y7OmkO/YstZVtmhfAKzZ00g==", "dev": true, "requires": { "clean-css": "4.2.1", "plugin-error": "1.0.1", - "through2": "2.0.3", + "through2": "3.0.0", "vinyl-sourcemaps-apply": "0.2.1" }, "dependencies": { "through2": { - "version": "2.0.3", - "resolved": "http://registry.npmjs.org/through2/-/through2-2.0.3.tgz", - "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.0.tgz", + "integrity": "sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ==", "dev": true, "requires": { - "readable-stream": "^2.1.5", + "readable-stream": "2 || 3", "xtend": "~4.0.1" } } @@ -2451,10 +2532,37 @@ "vinyl-file": "^3.0.0" } }, + "gulp-sourcemaps": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", + "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", + "dev": true, + "requires": { + "@gulp-sourcemaps/identity-map": "1.X", + "@gulp-sourcemaps/map-sources": "1.X", + "acorn": "5.X", + "convert-source-map": "1.X", + "css": "2.X", + "debug-fabulous": "1.X", + "detect-newline": "2.X", + "graceful-fs": "4.X", + "source-map": "~0.6.0", + "strip-bom-string": "1.X", + "through2": "2.X" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, "gulp-uf-bundle-assets": { - "version": "3.0.0-alpha.4", - "resolved": "https://registry.npmjs.org/gulp-uf-bundle-assets/-/gulp-uf-bundle-assets-3.0.0-alpha.4.tgz", - "integrity": "sha512-WlIggdxNru5rPBCKtL3HNhAmFIjCzJC0AsO9w+smtwUtuwSuSuSkqzvf11X1CLCfp1LibgYerkIXQ0doTk1+LQ==", + "version": "3.0.0-alpha.5", + "resolved": "https://registry.npmjs.org/gulp-uf-bundle-assets/-/gulp-uf-bundle-assets-3.0.0-alpha.5.tgz", + "integrity": "sha512-J/ijBMagZqPe2xdpodedS6y/8yVAQn4RW/YVxJ97WAwghRNunaLVYW4/AbM4Hwea84sOQdIwDg/MfjC+BJ1U1w==", "dev": true, "requires": { "esm": "^3.0.84", @@ -2883,6 +2991,12 @@ } } }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true + }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -3573,6 +3687,15 @@ "lodash.escape": "^3.0.0" } }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dev": true, + "requires": { + "es5-ext": "~0.10.2" + } + }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -3975,6 +4098,22 @@ } } }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "dev": true, + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -5457,6 +5596,12 @@ "strip-bom": "^2.0.0" } }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -5521,6 +5666,16 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dev": true, + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", diff --git a/build/package.json b/build/package.json index ae83586ff..c8b80d5c8 100755 --- a/build/package.json +++ b/build/package.json @@ -6,12 +6,13 @@ "del": "^3.0.0", "dotenv": "^6.1.0", "gulp": "^4.0.0", - "gulp-clean-css": "^3.10.0", + "gulp-clean-css": "^4.0.0", "gulp-concat": "^2.6.1", "gulp-concat-css": "^3.1.0", "gulp-prune": "^0.2.0", "gulp-rev": "^9.0.0", - "gulp-uf-bundle-assets": "^3.0.0-alpha.4", + "gulp-sourcemaps": "^2.6.4", + "gulp-uf-bundle-assets": "^3.0.0-alpha.5", "gulp-uglify-es": "^1.0.4", "yarn": "^1.12.3" }, From 41de66c0885c74df4f4e24649f3cfe9a4456fb15 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 24 Nov 2018 19:06:48 +1100 Subject: [PATCH 155/237] Updated gulp tasks to reflect new best practises --- build/gulpfile.js | 26 +++++++++++++++++--------- build/package.json | 2 +- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 66aec1e98..5fcc79e57 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -1,6 +1,6 @@ "use strict"; const { config: envConfig } = require("dotenv"); -const { task, src, dest, parallel, series } = require("gulp"); +const { src, dest, series } = require("gulp"); const { readFileSync, existsSync, writeFileSync } = require("fs"); const { bower: mergeBowerDeps, yarn: mergeYarnDeps, yarnIsFlat } = require("@userfrosting/merge-package-dependencies"); const { sync: deleteSync } = require("del"); @@ -50,8 +50,9 @@ catch (error) { /** * Installs vendor assets. Mapped to npm script "uf-assets-install". + * @param {() => {}} done Used to mark task completion. */ -task("assets-install", done => { +function assetsInstall(done) { try { // This script requires the npm environment, and therefore cannot be run directly with the gulp CLI. if (!process.env.npm_lifecycle_event) throw new Error("Assets installation must be run via 'npm run uf-assets-install'"); @@ -170,12 +171,12 @@ Alternatively, resolutions can be used as an override, as documented at https:// catch (error) { done(error); } -}); +}; /** * Compiles frontend assets. Mapped to npm script "uf-bundle". */ -task("bundle", () => { +function bundle() { // Build sources list const sources = []; for (const sprinkle of sprinkles) { @@ -312,17 +313,18 @@ task("bundle", () => { .pipe(new Bundler(rawConfig, bundleBuilder, bundleResults)) .pipe(prune(publicAssetsDir)) .pipe(dest(publicAssetsDir)); -}); +}; /** * Run all frontend tasks. */ -task("frontend", series("assets-install", "bundle")); +const frontend = series(assetsInstall, bundle); /** - * + * Clean vendor and public asset folders. + * @param {() => {}} done Used to mark task completion. */ -task("clean", (done) => { +function clean(done) { try { Logger("Cleaning vendor assets..."); deleteSync(vendorAssetsDir, { force: true }); @@ -337,4 +339,10 @@ task("clean", (done) => { catch (error) { done(error); } -}); +}; + +// Export public tasks +exports.frontend = frontend; +exports.assetsInstall = assetsInstall; +exports.bundle = bundle; +exports.clean = clean; diff --git a/build/package.json b/build/package.json index c8b80d5c8..6d2e363b1 100755 --- a/build/package.json +++ b/build/package.json @@ -18,7 +18,7 @@ }, "scripts": { "uf-bundle": "gulp bundle", - "uf-assets-install": "gulp assets-install", + "uf-assets-install": "gulp assetsInstall", "uf-frontend": "gulp frontend", "uf-clean": "gulp clean" }, From b8042fe31ce37801df59ca69b345da384b4ba0d8 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Tue, 27 Nov 2018 18:11:04 +1100 Subject: [PATCH 156/237] Use new bundle package and integrate with logger --- build/gulpfile.js | 15 ++++++++++++--- build/package-lock.json | 24 ++++++++++++------------ build/package.json | 2 +- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 5fcc79e57..6a77162c2 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -9,7 +9,7 @@ const concatJs = require("gulp-concat"); const { default: minifyJs } = require("gulp-uglify-es"); const concatCss = require("gulp-concat-css"); const minifyCss = require("gulp-clean-css"); -const { ValidateRawConfig, MergeRawConfigs, default: Bundler } = require("gulp-uf-bundle-assets"); +const { ValidateRawConfig, MergeRawConfigs, default: Bundler } = require("@userfrosting/gulp-bundle-assets"); const rev = require("gulp-rev"); const prune = require("gulp-prune"); const { resolve: resolvePath } = require("path"); @@ -26,7 +26,7 @@ const doILog = (process.env.UF_MODE === "dev"); * @param {any} message Message to log. */ function Logger(message) { - if (doILog) console.log(message); + if (!doILog) console.log(message); } // Path constants @@ -302,11 +302,20 @@ function bundle() { } } // Write file - Logger("Rriting results file..."); + Logger("Writing results file..."); writeFileSync("./bundle.result.json", JSON.stringify(resultsObject)); Logger("Done.") }; + // Logger adapter + function LoggerAdapter(message, loglevel) { + // Normal level and above + if (loglevel > 0) { + Logger(message); + } + } + rawConfig.Logger = LoggerAdapter; + // Open stream Logger("Starting bundle process proper..."); return src(sources) diff --git a/build/package-lock.json b/build/package-lock.json index e0209f31c..3ee6c034b 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -33,6 +33,18 @@ "through2": "^2.0.3" } }, + "@userfrosting/gulp-bundle-assets": { + "version": "3.0.0-alpha.6", + "resolved": "https://registry.npmjs.org/@userfrosting/gulp-bundle-assets/-/gulp-bundle-assets-3.0.0-alpha.6.tgz", + "integrity": "sha512-B5lh2hqSFU7cWe11d5eJtvlYOsvjzingCLZQXogECO2DVanb79Sh/QIelXZ6ytax011P6CLLg7oP2vHxYxmp1g==", + "dev": true, + "requires": { + "esm": "^3.0.84", + "just-extend": "^4.0.2", + "plugin-error": "^1.0.1", + "vinyl": "^2.2.0" + } + }, "@userfrosting/merge-package-dependencies": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.1.tgz", @@ -2559,18 +2571,6 @@ } } }, - "gulp-uf-bundle-assets": { - "version": "3.0.0-alpha.5", - "resolved": "https://registry.npmjs.org/gulp-uf-bundle-assets/-/gulp-uf-bundle-assets-3.0.0-alpha.5.tgz", - "integrity": "sha512-J/ijBMagZqPe2xdpodedS6y/8yVAQn4RW/YVxJ97WAwghRNunaLVYW4/AbM4Hwea84sOQdIwDg/MfjC+BJ1U1w==", - "dev": true, - "requires": { - "esm": "^3.0.84", - "just-extend": "^4.0.2", - "plugin-error": "^1.0.1", - "vinyl": "^2.2.0" - } - }, "gulp-uglify-es": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/gulp-uglify-es/-/gulp-uglify-es-1.0.4.tgz", diff --git a/build/package.json b/build/package.json index 6d2e363b1..26602bbd8 100755 --- a/build/package.json +++ b/build/package.json @@ -12,7 +12,7 @@ "gulp-prune": "^0.2.0", "gulp-rev": "^9.0.0", "gulp-sourcemaps": "^2.6.4", - "gulp-uf-bundle-assets": "^3.0.0-alpha.5", + "@userfrosting/gulp-bundle-assets": "^3.0.0-alpha.6", "gulp-uglify-es": "^1.0.4", "yarn": "^1.12.3" }, From ab49b1327e5f798c7f18e7cf94d267717ba8ee73 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 3 Dec 2018 20:57:14 -0500 Subject: [PATCH 157/237] Fix issue with test, change in Resource ctor --- .../tests/Integration/MigrationLocatorTest.php | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php index d3da7fdfd..dfaeefb57 100644 --- a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php @@ -70,20 +70,21 @@ public function testGetMigrations() $resourceCoreLocation = m::mock(ResourceLocation::class); $resourceCoreLocation->shouldReceive('getName')->andReturn('Core'); $resourceCoreLocation->shouldReceive('getPath')->andReturn('app/sprinkles/Core'); + $resourceAccountLocation = m::mock(ResourceLocation::class); $resourceAccountLocation->shouldReceive('getName')->andReturn('account'); $resourceAccountLocation->shouldReceive('getPath')->andReturn('app/sprinkles/Account'); // When `MigrationLocator` will ask the resource locator to `listResources`, we simulate returning Resources $resourceLocator->shouldReceive('listResources')->once()->andReturn([ - new Resource($resourceStream, $resourceCoreLocation, '', 'one/CreateUsersTable.php'), - new Resource($resourceStream, $resourceCoreLocation, '', 'one/CreatePasswordResetsTable.php'), - new Resource($resourceStream, $resourceCoreLocation, '', 'two/CreateFlightsTable.php'), - new Resource($resourceStream, $resourceCoreLocation, '', 'CreateMainTable.php'), - new Resource($resourceStream, $resourceAccountLocation, '', 'one/CreateUsersTable.php'), - new Resource($resourceStream, $resourceAccountLocation, '', 'one/CreatePasswordResetsTable.php'), - new Resource($resourceStream, $resourceAccountLocation, '', 'two/CreateFlightsTable.php'), - new Resource($resourceStream, $resourceAccountLocation, '', 'CreateMainTable.php') + new Resource($resourceStream, $resourceCoreLocation, 'one/CreateUsersTable.php'), + new Resource($resourceStream, $resourceCoreLocation, 'one/CreatePasswordResetsTable.php'), + new Resource($resourceStream, $resourceCoreLocation, 'two/CreateFlightsTable.php'), + new Resource($resourceStream, $resourceCoreLocation, 'CreateMainTable.php'), + new Resource($resourceStream, $resourceAccountLocation, 'one/CreateUsersTable.php'), + new Resource($resourceStream, $resourceAccountLocation, 'one/CreatePasswordResetsTable.php'), + new Resource($resourceStream, $resourceAccountLocation, 'two/CreateFlightsTable.php'), + new Resource($resourceStream, $resourceAccountLocation, 'CreateMainTable.php') ]); // Create a new MigrationLocator instance with our simulated ResourceLocation From 9d028383bf7e3c9cf5526189ccc0dbfbb58369e2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 3 Dec 2018 21:09:25 -0500 Subject: [PATCH 158/237] Fix issue where migrate would prevent build-asset to run in bake command --- app/sprinkles/core/src/Bakery/MigrateCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/Bakery/MigrateCommand.php b/app/sprinkles/core/src/Bakery/MigrateCommand.php index cbef3aa4b..3cdeee1a9 100644 --- a/app/sprinkles/core/src/Bakery/MigrateCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateCommand.php @@ -58,7 +58,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // Don't go further if no migration is pending if (empty($pending)) { $this->io->success('Nothing to migrate'); - exit(1); + return; } // Show migrations about to be ran when in production mode From 5b56a902b5d83fbd7b8838b1e04747861961f7d9 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 11 Dec 2018 21:43:46 -0500 Subject: [PATCH 159/237] Improved error handling in Bakery --- app/sprinkles/core/config/default.php | 3 +- app/system/Bakery/Bakery.php | 51 ++++++++++++++++++--------- app/system/Bakery/BaseCommand.php | 4 +-- 3 files changed, 38 insertions(+), 20 deletions(-) diff --git a/app/sprinkles/core/config/default.php b/app/sprinkles/core/config/default.php index 256c6d5ef..7da7f0940 100755 --- a/app/sprinkles/core/config/default.php +++ b/app/sprinkles/core/config/default.php @@ -280,7 +280,8 @@ * "Site" settings that are automatically passed to Twig */ 'site' => [ - // AdminLTE Settings + // AdminLTE skin color + // See https://adminlte.io/themes/AdminLTE/documentation/index.html#layout 'AdminLTE' => [ 'skin' => 'blue' ], diff --git a/app/system/Bakery/Bakery.php b/app/system/Bakery/Bakery.php index c3208c94d..387e05d8b 100644 --- a/app/system/Bakery/Bakery.php +++ b/app/system/Bakery/Bakery.php @@ -11,6 +11,7 @@ use Illuminate\Support\Str; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Output\ConsoleOutput; use UserFrosting\System\UserFrosting; use UserFrosting\UniformResourceLocator\Resource; use UserFrosting\UniformResourceLocator\ResourceLocator; @@ -42,15 +43,20 @@ class Bakery */ public function __construct() { + // Create Symfony Console App + $this->app = new Application('UserFrosting Bakery', \UserFrosting\VERSION); + // Check for Sprinkles schema file $sprinklesFile = @file_get_contents(\UserFrosting\SPRINKLES_SCHEMA_FILE); if ($sprinklesFile === false) { - $sprinklesFile = $this->setupBaseSprinkleList(); + try { + $sprinklesFile = $this->setupBaseSprinkleList(); + } catch (\Exception $e) { + $this->app->renderException($e, new ConsoleOutput()); + exit(1); + } } - // Create Symfony Console App - $this->app = new Application('UserFrosting Bakery', \UserFrosting\VERSION); - // Setup the sprinkles $uf = new UserFrosting(true); @@ -58,7 +64,12 @@ public function __construct() $this->ci = $uf->getContainer(); // Add each commands to the Console App - $this->loadCommands(); + try { + $this->loadCommands(); + } catch (\Exception $e) { + $this->app->renderException($e, new ConsoleOutput()); + exit(1); + } } /** @@ -93,7 +104,7 @@ protected function loadCommands() // Class must be an instance of symfony command if (!$instance instanceof Command) { - throw new \Exception('Bakery command class must be an instance of `' . Command::class . '`'); + throw new \Exception("Bakery `$command` must be an instance of `" . Command::class . "`"); } // Add command to the Console app @@ -116,16 +127,9 @@ protected function getResourceClass(Resource $file) // Format the sprinkle name for the namespace $sprinkleName = $file->getLocation()->getName(); $sprinkleName = Str::studly($sprinkleName); - - // Getting the classpath - $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); - $className = str_replace('/', '\\', $basePath) . $file->getFilename(); - $classPath = "\\UserFrosting\\Sprinkle\\$sprinkleName\\Bakery\\$className"; + $classPath = "\\UserFrosting\\Sprinkle\\$sprinkleName\\Bakery\\{$this->getClassNameFromFile($file)}"; } else { - // Getting the classpath - $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); - $className = str_replace('/', '\\', $basePath) . $file->getFilename(); - $classPath = "\\UserFrosting\\System\\Bakery\\Command\\$className"; + $classPath = "\\UserFrosting\\System\\Bakery\\Command\\{$this->getClassNameFromFile($file)}"; } // Make sure class exist @@ -136,6 +140,20 @@ protected function getResourceClass(Resource $file) return $classPath; } + /** + * Return the classname from the file instance + * + * @param \UserFrosting\UniformResourceLocator\Resource $file The command resource + * @return string + */ + protected function getClassNameFromFile(Resource $file) + { + $basePath = str_replace($file->getBasename(), '', $file->getBasePath()); + $className = str_replace('/', '\\', $basePath) . $file->getFilename(); + + return $className; + } + /** * Write the base `sprinkles.json` file if none exist. * @@ -147,8 +165,7 @@ protected function setupBaseSprinkleList() $destination = \UserFrosting\SPRINKLES_SCHEMA_FILE; $sprinklesModelFile = @file_get_contents($model); if ($sprinklesModelFile === false) { - $this->io->error("File `$sprinklesModelFile` not found. Please create '$destination' manually and try again."); - exit(1); + throw new \Exception("File `$model` not found. Please create '$destination' manually and try again."); } file_put_contents($destination, $sprinklesModelFile); diff --git a/app/system/Bakery/BaseCommand.php b/app/system/Bakery/BaseCommand.php index 146f47919..99ec1b554 100644 --- a/app/system/Bakery/BaseCommand.php +++ b/app/system/Bakery/BaseCommand.php @@ -41,9 +41,9 @@ protected function initialize(InputInterface $input, OutputInterface $output) } /** - * Setup the global container object + * Setup the global container object * - * @param ContainerInterface $ci + * @param ContainerInterface $ci */ public function setContainer(ContainerInterface $ci) { From baddcde64674f6224be077562b9f0cd68963ddfe Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 14 Dec 2018 07:56:00 +1100 Subject: [PATCH 160/237] Improved build logging and removed unneeded gulp-sourcemaps plugin --- build/gulpfile.js | 37 ++++----- build/package-lock.json | 161 +--------------------------------------- build/package.json | 6 +- 3 files changed, 26 insertions(+), 178 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 6a77162c2..a1378c81b 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -1,19 +1,19 @@ "use strict"; +const { bower: mergeBowerDeps, yarn: mergeYarnDeps, yarnIsFlat } = require("@userfrosting/merge-package-dependencies"); const { config: envConfig } = require("dotenv"); -const { src, dest, series } = require("gulp"); +const { default: Bundler, ValidateRawConfig, MergeRawConfigs } = require("@userfrosting/gulp-bundle-assets"); +const { default: minifyJs } = require("gulp-uglify-es"); +const { execSync } = require("child_process"); const { readFileSync, existsSync, writeFileSync } = require("fs"); -const { bower: mergeBowerDeps, yarn: mergeYarnDeps, yarnIsFlat } = require("@userfrosting/merge-package-dependencies"); +const { resolve: resolvePath } = require("path"); +const { src, dest, series } = require("gulp"); const { sync: deleteSync } = require("del"); -const { execSync } = require("child_process"); -const concatJs = require("gulp-concat"); -const { default: minifyJs } = require("gulp-uglify-es"); const concatCss = require("gulp-concat-css"); +const concatJs = require("gulp-concat"); +const log = require("gulplog"); const minifyCss = require("gulp-clean-css"); -const { ValidateRawConfig, MergeRawConfigs, default: Bundler } = require("@userfrosting/gulp-bundle-assets"); -const rev = require("gulp-rev"); const prune = require("gulp-prune"); -const { resolve: resolvePath } = require("path"); -const sourcemaps = require("gulp-sourcemaps"); +const rev = require("gulp-rev"); // Load environment variables envConfig({ path: "../app/.env" }); @@ -25,8 +25,13 @@ const doILog = (process.env.UF_MODE === "dev"); * Prints to stdout with newline when UF_MODE is dev. * @param {any} message Message to log. */ -function Logger(message) { - if (!doILog) console.log(message); +function Logger(message, source) { + if (!doILog) { + if (source) + log.info(`${source}: ${message}`); + else + log.info(message); + } } // Path constants @@ -189,11 +194,9 @@ function bundle() { const bundleBuilder = { Scripts: (src, name) => { return src - .pipe(sourcemaps.init()) .pipe(concatJs(name + ".js")) .pipe(minifyJs()) - .pipe(rev()) - .pipe(sourcemaps.write("./")); + .pipe(rev()); }, Styles: (src, name) => { return src @@ -311,17 +314,17 @@ function bundle() { function LoggerAdapter(message, loglevel) { // Normal level and above if (loglevel > 0) { - Logger(message); + Logger(message, "gulp-bundle-assets"); } } rawConfig.Logger = LoggerAdapter; // Open stream Logger("Starting bundle process proper..."); - return src(sources) + return src(sources, { sourcemaps: true }) .pipe(new Bundler(rawConfig, bundleBuilder, bundleResults)) .pipe(prune(publicAssetsDir)) - .pipe(dest(publicAssetsDir)); + .pipe(dest(publicAssetsDir, { sourcemaps: "." })); }; /** diff --git a/build/package-lock.json b/build/package-lock.json index 3ee6c034b..14742ecfe 100644 --- a/build/package-lock.json +++ b/build/package-lock.json @@ -2,37 +2,6 @@ "requires": true, "lockfileVersion": 1, "dependencies": { - "@gulp-sourcemaps/identity-map": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/identity-map/-/identity-map-1.0.2.tgz", - "integrity": "sha512-ciiioYMLdo16ShmfHBXJBOFm3xPC4AuwO4xeRpFeHz7WK9PYsWCmigagG2XyzZpubK4a3qNKoUBDhbzHfa50LQ==", - "dev": true, - "requires": { - "acorn": "^5.0.3", - "css": "^2.2.1", - "normalize-path": "^2.1.1", - "source-map": "^0.6.0", - "through2": "^2.0.3" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "@gulp-sourcemaps/map-sources": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@gulp-sourcemaps/map-sources/-/map-sources-1.0.0.tgz", - "integrity": "sha1-iQrnxdjId/bThIYCFazp1+yUW9o=", - "dev": true, - "requires": { - "normalize-path": "^2.0.1", - "through2": "^2.0.3" - } - }, "@userfrosting/gulp-bundle-assets": { "version": "3.0.0-alpha.6", "resolved": "https://registry.npmjs.org/@userfrosting/gulp-bundle-assets/-/gulp-bundle-assets-3.0.0-alpha.6.tgz", @@ -75,12 +44,6 @@ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", "dev": true }, - "acorn": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", - "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", - "dev": true - }, "ansi-colors": { "version": "1.1.0", "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", @@ -1227,34 +1190,6 @@ "ms": "2.0.0" } }, - "debug-fabulous": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/debug-fabulous/-/debug-fabulous-1.1.0.tgz", - "integrity": "sha512-GZqvGIgKNlUnHUPQhepnUZFIMoi3dgZKQBzKDeL2g7oJF9SNAji/AAu36dusFUas0O+pae74lNeoIPHqXWDkLg==", - "dev": true, - "requires": { - "debug": "3.X", - "memoizee": "0.4.X", - "object-assign": "4.X" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - } - } - }, "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", @@ -1374,12 +1309,6 @@ } } }, - "detect-newline": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-2.1.0.tgz", - "integrity": "sha1-9B8cEL5LAOh7XxPaaAdZ8sW/0+I=", - "dev": true - }, "dotenv": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.1.0.tgz", @@ -1517,16 +1446,6 @@ "integrity": "sha512-SzSGoZc17S7P+12R9cg21Bdb7eybX25RnIeRZ80xZs+VZ3kdQKzqTp2k4hZJjR7p9l0186TTXSgrxzlMDBktlw==", "dev": true }, - "event-emitter": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", - "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, "extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -2310,9 +2229,9 @@ } }, "glogg": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.0.tgz", - "integrity": "sha1-f+DxmfV6yQbPUS/urY+Q7kooT8U=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", + "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", "dev": true, "requires": { "sparkles": "^1.0.0" @@ -2544,33 +2463,6 @@ "vinyl-file": "^3.0.0" } }, - "gulp-sourcemaps": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-2.6.4.tgz", - "integrity": "sha1-y7IAhFCxvM5s0jv5gze+dRv24wo=", - "dev": true, - "requires": { - "@gulp-sourcemaps/identity-map": "1.X", - "@gulp-sourcemaps/map-sources": "1.X", - "acorn": "5.X", - "convert-source-map": "1.X", - "css": "2.X", - "debug-fabulous": "1.X", - "detect-newline": "2.X", - "graceful-fs": "4.X", - "source-map": "~0.6.0", - "strip-bom-string": "1.X", - "through2": "2.X" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, "gulp-uglify-es": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/gulp-uglify-es/-/gulp-uglify-es-1.0.4.tgz", @@ -2991,12 +2883,6 @@ } } }, - "is-promise": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", - "dev": true - }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", @@ -3687,15 +3573,6 @@ "lodash.escape": "^3.0.0" } }, - "lru-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", - "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", - "dev": true, - "requires": { - "es5-ext": "~0.10.2" - } - }, "make-iterator": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", @@ -4098,22 +3975,6 @@ } } }, - "memoizee": { - "version": "0.4.14", - "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", - "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.45", - "es6-weak-map": "^2.0.2", - "event-emitter": "^0.3.5", - "is-promise": "^2.1", - "lru-queue": "0.1", - "next-tick": "1", - "timers-ext": "^0.1.5" - } - }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -5596,12 +5457,6 @@ "strip-bom": "^2.0.0" } }, - "strip-bom-string": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", - "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", - "dev": true - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -5666,16 +5521,6 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, - "timers-ext": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", - "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", - "dev": true, - "requires": { - "es5-ext": "~0.10.46", - "next-tick": "1" - } - }, "to-absolute-glob": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", diff --git a/build/package.json b/build/package.json index 26602bbd8..49b853496 100755 --- a/build/package.json +++ b/build/package.json @@ -1,19 +1,19 @@ { "private": true, "devDependencies": { + "@userfrosting/gulp-bundle-assets": "^3.0.0-alpha.6", "@userfrosting/merge-package-dependencies": "^1.2.1", "bower": "^1.8.4", "del": "^3.0.0", - "dotenv": "^6.1.0", + "dotenv": "^6.2.0", "gulp": "^4.0.0", "gulp-clean-css": "^4.0.0", "gulp-concat": "^2.6.1", "gulp-concat-css": "^3.1.0", "gulp-prune": "^0.2.0", "gulp-rev": "^9.0.0", - "gulp-sourcemaps": "^2.6.4", - "@userfrosting/gulp-bundle-assets": "^3.0.0-alpha.6", "gulp-uglify-es": "^1.0.4", + "gulplog": "^1.0.0", "yarn": "^1.12.3" }, "scripts": { From 05f598474823b2556df950c2b04354228aba2adc Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 21 Dec 2018 07:03:22 +1100 Subject: [PATCH 161/237] Skip `npm install` in `bakery assets-install` if no changes --- app/system/Bakery/Command/BuildAssets.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/system/Bakery/Command/BuildAssets.php index 0faa60960..3c3015b7b 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/system/Bakery/Command/BuildAssets.php @@ -55,7 +55,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } // Perform tasks - $this->npmInstall(); + $this->npmInstall($input->getOption('force')); $this->assetsInstall(); // Compile if requested @@ -69,10 +69,19 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Install npm package + * + * @param bool $force Force `npm install` to be run, ignoring evidence of a previous run. */ - protected function npmInstall() + protected function npmInstall($force) { $this->io->section('Installing npm dependencies'); + + // Skip install if lockfile is newer + if (!$force || filemtime("package.json") > filemtime("package-lock.json") + 1000) { + $this->io->writeln('> Skipping npm install which has been previously run'); + return; + } + $this->io->writeln('> npm install'); // Temporarily change the working directory so we can install npm dependencies From f05e205b2f96f1bd7f077ab8e063fc6eecb35330 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 21 Dec 2018 12:44:54 +1100 Subject: [PATCH 162/237] #863 Ignored and removed `package-lock.json` --- .gitignore | 3 + build/package-lock.json | 5937 --------------------------------------- 2 files changed, 3 insertions(+), 5937 deletions(-) delete mode 100644 build/package-lock.json diff --git a/.gitignore b/.gitignore index 4eb87a889..329be784a 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,6 @@ app/assets/* # Ignore Vagrant & Homestead VM vagrant/Homestead/ .vagrant/* + +# Igore npm lockfile +build/package-lock.json diff --git a/build/package-lock.json b/build/package-lock.json deleted file mode 100644 index 14742ecfe..000000000 --- a/build/package-lock.json +++ /dev/null @@ -1,5937 +0,0 @@ -{ - "requires": true, - "lockfileVersion": 1, - "dependencies": { - "@userfrosting/gulp-bundle-assets": { - "version": "3.0.0-alpha.6", - "resolved": "https://registry.npmjs.org/@userfrosting/gulp-bundle-assets/-/gulp-bundle-assets-3.0.0-alpha.6.tgz", - "integrity": "sha512-B5lh2hqSFU7cWe11d5eJtvlYOsvjzingCLZQXogECO2DVanb79Sh/QIelXZ6ytax011P6CLLg7oP2vHxYxmp1g==", - "dev": true, - "requires": { - "esm": "^3.0.84", - "just-extend": "^4.0.2", - "plugin-error": "^1.0.1", - "vinyl": "^2.2.0" - } - }, - "@userfrosting/merge-package-dependencies": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@userfrosting/merge-package-dependencies/-/merge-package-dependencies-1.2.1.tgz", - "integrity": "sha512-jv79Suqy087JR1/pc1Gn9Mnp4KJpeUdALFdG2sZS+kiSh68k7jhD/u+k355bhYvcYnsAmmx62BVEXSWiOS2VZQ==", - "dev": true, - "requires": { - "@yarnpkg/lockfile": "^1.1.0", - "chalk": "^2.4.1", - "fs-extra": "^7.0.1", - "lodash": "^4.17.11", - "node-exceptions": "^4.0.1", - "package-json-validator": "0.6.3", - "semver": "^5.6.0", - "semver-intersect": "^1.4.0" - }, - "dependencies": { - "semver": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", - "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==", - "dev": true - } - } - }, - "@yarnpkg/lockfile": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", - "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", - "dev": true - }, - "ansi-colors": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/ansi-colors/-/ansi-colors-1.1.0.tgz", - "integrity": "sha512-SFKX67auSNoVR38N3L+nvsPjOE0bybKTYbkf5tRvushrAPQ9V75huw0ZxBkKVeRU9kqH3d6HA4xTckbwZ4ixmA==", - "dev": true, - "requires": { - "ansi-wrap": "^0.1.0" - } - }, - "ansi-cyan": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-cyan/-/ansi-cyan-0.1.1.tgz", - "integrity": "sha1-U4rlKK+JgvKK4w2G8vF0VtJgmHM=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-gray": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz", - "integrity": "sha1-KWLPVOyXksSFEKPetSRDaGHvclE=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-red": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/ansi-red/-/ansi-red-0.1.1.tgz", - "integrity": "sha1-jGOPnRCAgAo1PJwoyKgcpHBdlGw=", - "dev": true, - "requires": { - "ansi-wrap": "0.1.0" - } - }, - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "ansi-wrap": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz", - "integrity": "sha1-qCJQ3bABXponyoLoLqYDu/pF768=", - "dev": true - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "append-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/append-buffer/-/append-buffer-1.0.2.tgz", - "integrity": "sha1-2CIM9GYIFSXv6lBhTz3mUU36WPE=", - "dev": true, - "requires": { - "buffer-equal": "^1.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arr-diff": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-1.1.0.tgz", - "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" - }, - "dependencies": { - "array-slice": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-0.2.3.tgz", - "integrity": "sha1-3Tz7gO15c6dRF82sabC5nshhhvU=", - "dev": true - } - } - }, - "arr-filter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/arr-filter/-/arr-filter-1.1.2.tgz", - "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true - }, - "arr-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/arr-map/-/arr-map-2.0.2.tgz", - "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", - "dev": true, - "requires": { - "make-iterator": "^1.0.0" - } - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true - }, - "array-differ": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", - "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", - "dev": true - }, - "array-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/array-each/-/array-each-1.0.1.tgz", - "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=", - "dev": true - }, - "array-initial": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-initial/-/array-initial-1.1.0.tgz", - "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", - "dev": true, - "requires": { - "array-slice": "^1.0.0", - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-last": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/array-last/-/array-last-1.3.0.tgz", - "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", - "dev": true, - "requires": { - "is-number": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", - "dev": true - } - } - }, - "array-slice": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/array-slice/-/array-slice-1.1.0.tgz", - "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==", - "dev": true - }, - "array-sort": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-sort/-/array-sort-1.0.0.tgz", - "integrity": "sha512-ihLeJkonmdiAsD7vpgN3CRcx2J2S0TiYW+IS/5zHBI7mKUq3ySvBdzzBfD236ubDBQFiiyG3SWCPc+msQ9KoYg==", - "dev": true, - "requires": { - "default-compare": "^1.0.0", - "get-value": "^2.0.6", - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "array-union": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", - "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1" - } - }, - "array-uniq": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", - "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", - "dev": true - }, - "arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true - }, - "async": { - "version": "1.5.2", - "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=", - "dev": true - }, - "async-done": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/async-done/-/async-done-1.3.1.tgz", - "integrity": "sha512-R1BaUeJ4PMoLNJuk+0tLJgjmEqVsdN118+Z8O+alhnQDQgy0kmD5Mqi0DNEmMx2LM0Ed5yekKu+ZXYvIHceicg==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.2", - "process-nextick-args": "^1.0.7", - "stream-exhaust": "^1.0.1" - } - }, - "async-each": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.1.tgz", - "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", - "dev": true - }, - "async-settle": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/async-settle/-/async-settle-1.0.0.tgz", - "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", - "dev": true, - "requires": { - "async-done": "^1.2.2" - } - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true - }, - "bach": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/bach/-/bach-1.2.0.tgz", - "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", - "dev": true, - "requires": { - "arr-filter": "^1.1.1", - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "array-each": "^1.0.0", - "array-initial": "^1.0.0", - "array-last": "^1.1.1", - "async-done": "^1.2.2", - "async-settle": "^1.0.0", - "now-and-later": "^2.0.0" - } - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "beeper": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz", - "integrity": "sha1-5tXqjF2tABMEpwsiY4RH9pyy+Ak=", - "dev": true - }, - "binary-extensions": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.12.0.tgz", - "integrity": "sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg==", - "dev": true - }, - "bower": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/bower/-/bower-1.8.4.tgz", - "integrity": "sha1-54dqB23rgTf30GUl3F6MZtuC8oo=", - "dev": true - }, - "brace-expansion": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", - "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "buffer-equal": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", - "integrity": "sha1-WWFrSYME1Var1GaWayLu2j7KX74=", - "dev": true - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "builtin-modules": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", - "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "camelcase": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz", - "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=", - "dev": true - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "chokidar": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.4.tgz", - "integrity": "sha512-z9n7yt9rOvIJrMhvDtDictKrkFHeihkNl6uWMmZlmL6tJtX9Cs+87oK+teBx+JIgzvbX3yZHT3eF8vpbDxHJXQ==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.0", - "braces": "^2.3.0", - "fsevents": "^1.2.2", - "glob-parent": "^3.1.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "lodash.debounce": "^4.0.8", - "normalize-path": "^2.1.1", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0", - "upath": "^1.0.5" - }, - "dependencies": { - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.0.tgz", - "integrity": "sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A=", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "clean-css": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.1.tgz", - "integrity": "sha512-4ZxI6dy4lrY6FHzfiy1aEOXgu4LIsW2MhwG0VBKdcoGoH/XLFgaHSdLTGr4O8Be6A8r3MOphEiI8Gc1n0ecf3g==", - "dev": true, - "requires": { - "source-map": "~0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "cliui": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", - "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wrap-ansi": "^2.0.0" - } - }, - "clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=", - "dev": true - }, - "clone-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-buffer/-/clone-buffer-1.0.0.tgz", - "integrity": "sha1-4+JbIHrE5wGvch4staFnksrD3Fg=", - "dev": true - }, - "clone-stats": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-1.0.0.tgz", - "integrity": "sha1-s3gt/4u1R04Yuba/D9/ngvh3doA=", - "dev": true - }, - "cloneable-readable": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/cloneable-readable/-/cloneable-readable-1.1.2.tgz", - "integrity": "sha512-Bq6+4t+lbM8vhTs/Bef5c5AdEMtapp/iFb6+s4/Hh9MVTt8OLKH7ZOOZSCT+Ys7hsHvqv0GuMPJ1lnQJVHvxpg==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "code-point-at": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", - "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", - "dev": true - }, - "collection-map": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-map/-/collection-map-1.0.0.tgz", - "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", - "dev": true, - "requires": { - "arr-map": "^2.0.2", - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "commander": { - "version": "2.17.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", - "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", - "dev": true - }, - "component-emitter": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.2.1.tgz", - "integrity": "sha1-E3kY1teCg/ffemt8WmPhQOaUJeY=", - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "concat-stream": { - "version": "1.6.2", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", - "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" - } - }, - "concat-with-sourcemaps": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", - "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", - "dev": true, - "requires": { - "source-map": "^0.6.1" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "convert-source-map": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.6.0.tgz", - "integrity": "sha512-eFu7XigvxdZ1ETfbgPBohgyQ/Z++C0eEhTor0qRwBw9unw+L0/6V8wkSuGgzdThkiS5lSpdptOQPD8Ak40a+7A==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true - }, - "copy-props": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/copy-props/-/copy-props-2.0.4.tgz", - "integrity": "sha512-7cjuUME+p+S3HZlbllgsn2CDwS+5eCCX16qBgNC4jgSTf49qR1VKy/Zhl400m0IQXl/bPGEVqncgUUMjrr4s8A==", - "dev": true, - "requires": { - "each-props": "^1.3.0", - "is-plain-object": "^2.0.1" - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true - }, - "css": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", - "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "source-map": "^0.6.1", - "source-map-resolve": "^0.5.2", - "urix": "^0.1.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "d": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/d/-/d-1.0.0.tgz", - "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, - "requires": { - "es5-ext": "^0.10.9" - } - }, - "dateformat": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz", - "integrity": "sha1-QGXiATz5+5Ft39gu+1Bq1MZ2kGI=", - "dev": true - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true - }, - "default-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/default-compare/-/default-compare-1.0.0.tgz", - "integrity": "sha512-QWfXlM0EkAbqOCbD/6HjdwT19j7WCkMyiRhWilc4H9/5h/RzTF9gv5LYh1+CmDV5d1rki6KAWLtQale0xt20eQ==", - "dev": true, - "requires": { - "kind-of": "^5.0.2" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "default-resolution": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/default-resolution/-/default-resolution-2.0.0.tgz", - "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=", - "dev": true - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "del": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/del/-/del-3.0.0.tgz", - "integrity": "sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU=", - "dev": true, - "requires": { - "globby": "^6.1.0", - "is-path-cwd": "^1.0.0", - "is-path-in-cwd": "^1.0.0", - "p-map": "^1.1.1", - "pify": "^3.0.0", - "rimraf": "^2.2.8" - }, - "dependencies": { - "pify": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", - "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", - "dev": true - } - } - }, - "dotenv": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.1.0.tgz", - "integrity": "sha512-/veDn2ztgRlB7gKmE3i9f6CmDIyXAy6d5nBq+whO9SLX+Zs1sXEgFLPi+aSuWqUuusMfbi84fT8j34fs1HaYUw==", - "dev": true - }, - "duplexer2": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", - "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", - "dev": true, - "requires": { - "readable-stream": "~1.1.9" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - } - } - }, - "duplexify": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.1.tgz", - "integrity": "sha512-vM58DwdnKmty+FSPzT14K9JXb90H+j5emaR4KYbr2KTIz00WHGbWOe5ghQTx233ZCLZtrGDALzKwcjEtSt35mA==", - "dev": true, - "requires": { - "end-of-stream": "^1.0.0", - "inherits": "^2.0.1", - "readable-stream": "^2.0.0", - "stream-shift": "^1.0.0" - } - }, - "each-props": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/each-props/-/each-props-1.3.2.tgz", - "integrity": "sha512-vV0Hem3zAGkJAyU7JSjixeU66rwdynTAa1vofCrSA5fEln+m67Az9CcnkVD776/fsN/UjIWmBDoNRS6t6G9RfA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.1", - "object.defaults": "^1.1.0" - } - }, - "end-of-stream": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", - "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", - "dev": true, - "requires": { - "once": "^1.4.0" - } - }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, - "es5-ext": { - "version": "0.10.46", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", - "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", - "dev": true, - "requires": { - "es6-iterator": "~2.0.3", - "es6-symbol": "~3.1.1", - "next-tick": "1" - } - }, - "es6-iterator": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", - "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.35", - "es6-symbol": "^3.1.1" - } - }, - "es6-symbol": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", - "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "~0.10.14" - } - }, - "es6-weak-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", - "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", - "dev": true, - "requires": { - "d": "1", - "es5-ext": "^0.10.14", - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esm": { - "version": "3.0.84", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.0.84.tgz", - "integrity": "sha512-SzSGoZc17S7P+12R9cg21Bdb7eybX25RnIeRZ80xZs+VZ3kdQKzqTp2k4hZJjR7p9l0186TTXSgrxzlMDBktlw==", - "dev": true - }, - "extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "time-stamp": "^1.0.0" - } - }, - "find-up": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", - "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", - "dev": true, - "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "fined": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fined/-/fined-1.1.0.tgz", - "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" - }, - "dependencies": { - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - } - } - }, - "first-chunk-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-2.0.0.tgz", - "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", - "dev": true, - "requires": { - "readable-stream": "^2.0.2" - } - }, - "flagged-respawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/flagged-respawn/-/flagged-respawn-1.0.0.tgz", - "integrity": "sha1-Tnmumy6zi/hrO7Vr8+ClaqX8q9c=", - "dev": true - }, - "flush-write-stream": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.0.3.tgz", - "integrity": "sha512-calZMC10u0FMUqoiunI2AiGIIUtUIvifNwkHhNupZH4cbNnW1Itkoh/Nf5HFYmDrwWPjrUxpkZT0KhuCq0jmGw==", - "dev": true, - "requires": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.4" - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fs-extra": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", - "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^4.0.0", - "universalify": "^0.1.0" - } - }, - "fs-mkdirp-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-mkdirp-stream/-/fs-mkdirp-stream-1.0.0.tgz", - "integrity": "sha1-C3gV/DIBxqaeFNuYzgmMFpNSWes=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "through2": "^2.0.3" - } - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", - "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.9.2", - "node-pre-gyp": "^0.10.0" - }, - "dependencies": { - "abbrev": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^2.0.6" - } - }, - "balanced-match": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "brace-expansion": { - "version": "1.1.11", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "chownr": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "debug": { - "version": "2.6.9", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "optional": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "fs-minipass": { - "version": "1.2.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "^1.0.3", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.0", - "object-assign": "^4.1.0", - "signal-exit": "^3.0.0", - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1", - "wide-align": "^1.1.0" - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "iconv-lite": { - "version": "0.4.21", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safer-buffer": "^2.1.0" - } - }, - "ignore-walk": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.5", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "minipass": { - "version": "2.2.4", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "^5.1.1", - "yallist": "^3.0.0" - } - }, - "minizlib": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "minipass": "^2.2.1" - } - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "needle": { - "version": "2.2.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "^2.1.2", - "iconv-lite": "^0.4.4", - "sax": "^1.2.4" - } - }, - "node-pre-gyp": { - "version": "0.10.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "^1.0.2", - "mkdirp": "^0.5.1", - "needle": "^2.2.0", - "nopt": "^4.0.1", - "npm-packlist": "^1.1.6", - "npmlog": "^4.0.2", - "rc": "^1.1.7", - "rimraf": "^2.6.1", - "semver": "^5.3.0", - "tar": "^4" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1", - "osenv": "^0.1.4" - } - }, - "npm-bundled": { - "version": "1.0.3", - "bundled": true, - "dev": true, - "optional": true - }, - "npm-packlist": { - "version": "1.1.10", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ignore-walk": "^3.0.1", - "npm-bundled": "^1.0.1" - } - }, - "npmlog": { - "version": "4.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "~1.1.2", - "console-control-strings": "~1.1.0", - "gauge": "~2.7.3", - "set-blocking": "~2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "^1.0.0", - "os-tmpdir": "^1.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "^0.5.1", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "rimraf": { - "version": "2.6.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "bundled": true, - "dev": true - }, - "safer-buffer": { - "version": "2.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sax": { - "version": "1.2.4", - "bundled": true, - "dev": true, - "optional": true - }, - "semver": { - "version": "5.5.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "4.4.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "chownr": "^1.0.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.2.4", - "minizlib": "^1.1.0", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.1", - "yallist": "^3.0.2" - } - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "^1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "yallist": { - "version": "3.0.2", - "bundled": true, - "dev": true - } - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "get-caller-file": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", - "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", - "dev": true - }, - "get-imports": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-imports/-/get-imports-1.0.0.tgz", - "integrity": "sha1-R8C07piTUWQsVJdxk79Pyqv1N48=", - "dev": true, - "requires": { - "array-uniq": "^1.0.1", - "import-regex": "^1.1.0" - } - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true - }, - "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-stream": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-6.1.0.tgz", - "integrity": "sha1-cEXJlBOz65SIjYOrRtC0BMx73eQ=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "glob": "^7.1.1", - "glob-parent": "^3.1.0", - "is-negated-glob": "^1.0.0", - "ordered-read-streams": "^1.0.0", - "pumpify": "^1.3.5", - "readable-stream": "^2.1.5", - "remove-trailing-separator": "^1.0.1", - "to-absolute-glob": "^2.0.0", - "unique-stream": "^2.0.2" - }, - "dependencies": { - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "glob-watcher": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/glob-watcher/-/glob-watcher-5.0.3.tgz", - "integrity": "sha512-8tWsULNEPHKQ2MR4zXuzSmqbdyV5PtwwCaWSGQ1WwHsJ07ilNeN1JB8ntxhckbnpSHaf9dXFUHzIWvm1I13dsg==", - "dev": true, - "requires": { - "anymatch": "^2.0.0", - "async-done": "^1.2.0", - "chokidar": "^2.0.0", - "is-negated-glob": "^1.0.0", - "just-debounce": "^1.0.0", - "object.defaults": "^1.1.0" - } - }, - "globby": { - "version": "6.1.0", - "resolved": "http://registry.npmjs.org/globby/-/globby-6.1.0.tgz", - "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "glogg": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz", - "integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "graceful-fs": { - "version": "4.1.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", - "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", - "dev": true - }, - "gulp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gulp/-/gulp-4.0.0.tgz", - "integrity": "sha1-lXZsYB2t5Kd+0+eyttwDiBtZY2Y=", - "dev": true, - "requires": { - "glob-watcher": "^5.0.0", - "gulp-cli": "^2.0.0", - "undertaker": "^1.0.0", - "vinyl-fs": "^3.0.0" - }, - "dependencies": { - "fancy-log": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.2.tgz", - "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", - "dev": true, - "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "time-stamp": "^1.0.0" - } - }, - "gulp-cli": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/gulp-cli/-/gulp-cli-2.0.1.tgz", - "integrity": "sha512-RxujJJdN8/O6IW2nPugl7YazhmrIEjmiVfPKrWt68r71UCaLKS71Hp0gpKT+F6qOUFtr7KqtifDKaAJPRVvMYQ==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "archy": "^1.0.0", - "array-sort": "^1.0.0", - "color-support": "^1.1.3", - "concat-stream": "^1.6.0", - "copy-props": "^2.0.1", - "fancy-log": "^1.3.2", - "gulplog": "^1.0.0", - "interpret": "^1.1.0", - "isobject": "^3.0.1", - "liftoff": "^2.5.0", - "matchdep": "^2.0.0", - "mute-stdout": "^1.0.0", - "pretty-hrtime": "^1.0.0", - "replace-homedir": "^1.0.0", - "semver-greatest-satisfied-range": "^1.1.0", - "v8flags": "^3.0.1", - "yargs": "^7.1.0" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "gulp-clean-css": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/gulp-clean-css/-/gulp-clean-css-4.0.0.tgz", - "integrity": "sha512-/Hs+dmclQfFBSpwrAKd4wTVsahJvrVIg2ga0J7Eo7DKVTVfJrM7wXlfU1mK9iJ9Y7OmkO/YstZVtmhfAKzZ00g==", - "dev": true, - "requires": { - "clean-css": "4.2.1", - "plugin-error": "1.0.1", - "through2": "3.0.0", - "vinyl-sourcemaps-apply": "0.2.1" - }, - "dependencies": { - "through2": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.0.tgz", - "integrity": "sha512-8B+sevlqP4OiCjonI1Zw03Sf8PuV1eRsYQgLad5eonILOdyeRsY27A/2Ze8IlvlMvq31OH+3fz/styI7Ya62yQ==", - "dev": true, - "requires": { - "readable-stream": "2 || 3", - "xtend": "~4.0.1" - } - } - } - }, - "gulp-concat": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/gulp-concat/-/gulp-concat-2.6.1.tgz", - "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", - "dev": true, - "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" - } - }, - "gulp-concat-css": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/gulp-concat-css/-/gulp-concat-css-3.1.0.tgz", - "integrity": "sha512-iLTBPS+cutlgLyK3bp9DMts+WuS8n2mQpjzQ7p/ZVQc8FO5fvpN+ntg9U6jsuNvPeuii82aKm8XeOzF0nUK+TA==", - "dev": true, - "requires": { - "lodash.defaults": "^3.0.0", - "parse-import": "^2.0.0", - "plugin-error": "^0.1.2", - "rework": "~1.0.0", - "rework-import": "^2.0.0", - "rework-plugin-url": "^1.0.1", - "through2": "~1.1.1", - "vinyl": "^2.1.0" - }, - "dependencies": { - "arr-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-2.1.0.tgz", - "integrity": "sha1-IPnqtexw9cfSFbEHexw5Fh0pLH0=", - "dev": true - }, - "extend-shallow": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-1.1.4.tgz", - "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", - "dev": true, - "requires": { - "kind-of": "^1.1.0" - } - }, - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - }, - "kind-of": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/kind-of/-/kind-of-1.1.0.tgz", - "integrity": "sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ=", - "dev": true - }, - "plugin-error": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-0.1.2.tgz", - "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", - "dev": true, - "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" - } - }, - "readable-stream": { - "version": "1.1.14", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", - "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", - "dev": true - }, - "through2": { - "version": "1.1.1", - "resolved": "http://registry.npmjs.org/through2/-/through2-1.1.1.tgz", - "integrity": "sha1-CEfLxESfNAVXTb3M2buEG4OsNUU=", - "dev": true, - "requires": { - "readable-stream": ">=1.1.13-1 <1.2.0-0", - "xtend": ">=4.0.0 <4.1.0-0" - } - } - } - }, - "gulp-prune": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/gulp-prune/-/gulp-prune-0.2.0.tgz", - "integrity": "sha1-a7jady8PaMcAjv/TexqiXAuJ2A8=", - "dev": true, - "requires": { - "globby": "^5.0.0", - "gulp-util": "^3.0.7" - }, - "dependencies": { - "globby": { - "version": "5.0.0", - "resolved": "http://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "arrify": "^1.0.0", - "glob": "^7.0.3", - "object-assign": "^4.0.1", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - } - } - }, - "gulp-rev": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/gulp-rev/-/gulp-rev-9.0.0.tgz", - "integrity": "sha512-Ytx/uzDA2xNxHlPG8GReS1ut00msd0HlKDk9Ai/0xF2yvg+DAeGRAviCFlQzQmdZtqAoXznYspwWoGEoxDvhyA==", - "dev": true, - "requires": { - "modify-filename": "^1.1.0", - "plugin-error": "^1.0.1", - "rev-hash": "^2.0.0", - "rev-path": "^2.0.0", - "sort-keys": "^2.0.0", - "through2": "^2.0.0", - "vinyl": "^2.1.0", - "vinyl-file": "^3.0.0" - } - }, - "gulp-uglify-es": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/gulp-uglify-es/-/gulp-uglify-es-1.0.4.tgz", - "integrity": "sha512-UMRufZsBmQizCYpftutaiVoLswpbzFEfY90EJLU4YlTgculeHnanb794s88TMd5tpCZVC638sAX6JrLVYTP/Wg==", - "dev": true, - "requires": { - "o-stream": "^0.2.2", - "plugin-error": "^1.0.1", - "terser": "^3.7.5", - "vinyl": "^2.1.0", - "vinyl-sourcemaps-apply": "^0.2.1" - } - }, - "gulp-util": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz", - "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", - "dev": true, - "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", - "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" - }, - "dependencies": { - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", - "dev": true - }, - "clone-stats": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz", - "integrity": "sha1-uI+UqCzzi4eR1YBG6kAprYjKmdE=", - "dev": true - }, - "minimist": { - "version": "1.2.0", - "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", - "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", - "dev": true - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - }, - "replace-ext": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz", - "integrity": "sha1-KbvZIHinOfC8zitO5B6DeVNSKSQ=", - "dev": true - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - }, - "vinyl": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz", - "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", - "dev": true, - "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", - "replace-ext": "0.0.1" - } - } - } - }, - "gulplog": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz", - "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", - "dev": true, - "requires": { - "glogg": "^1.0.0" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-gulplog": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz", - "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", - "dev": true, - "requires": { - "sparkles": "^1.0.0" - } - }, - "has-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", - "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "homedir-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.1.tgz", - "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", - "dev": true, - "requires": { - "parse-passwd": "^1.0.0" - } - }, - "hosted-git-info": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", - "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", - "dev": true - }, - "import-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/import-regex/-/import-regex-1.1.0.tgz", - "integrity": "sha1-pVxS5McFx2XKIQ6SQqBrvMiqf2Y=", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", - "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", - "dev": true - }, - "ini": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.4.tgz", - "integrity": "sha1-BTfLedr1m1mhpRff9wbIbsA5Fi4=", - "dev": true - }, - "interpret": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.1.0.tgz", - "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", - "dev": true - }, - "invert-kv": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", - "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", - "dev": true - }, - "ip-regex": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", - "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", - "dev": true - }, - "is-absolute": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", - "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", - "dev": true, - "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" - }, - "dependencies": { - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - } - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", - "dev": true - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true - }, - "is-builtin-module": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", - "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", - "dev": true, - "requires": { - "builtin-modules": "^1.0.0" - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", - "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", - "dev": true, - "requires": { - "number-is-nan": "^1.0.0" - } - }, - "is-negated-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-negated-glob/-/is-negated-glob-1.0.0.tgz", - "integrity": "sha1-aRC8pdqMleeEtXUbl2z1oQ/uNtI=", - "dev": true - }, - "is-path-cwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", - "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", - "dev": true - }, - "is-path-in-cwd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", - "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", - "dev": true, - "requires": { - "is-path-inside": "^1.0.0" - } - }, - "is-path-inside": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", - "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", - "dev": true, - "requires": { - "path-is-inside": "^1.0.1" - } - }, - "is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", - "dev": true - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "is-relative": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", - "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", - "dev": true, - "requires": { - "is-unc-path": "^1.0.0" - } - }, - "is-unc-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", - "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", - "dev": true, - "requires": { - "unc-path-regex": "^0.1.2" - } - }, - "is-utf8": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", - "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", - "dev": true - }, - "is-valid-glob": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-1.0.0.tgz", - "integrity": "sha1-Kb8+/3Ab4tTTFdusw5vDn+j2Aao=", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", - "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", - "dev": true, - "requires": { - "jsonify": "~0.0.0" - } - }, - "jsonfile": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", - "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.6" - } - }, - "jsonify": { - "version": "0.0.0", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", - "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", - "dev": true - }, - "just-debounce": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/just-debounce/-/just-debounce-1.0.0.tgz", - "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", - "dev": true - }, - "just-extend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.0.2.tgz", - "integrity": "sha512-FrLwOgm+iXrPV+5zDU6Jqu4gCRXbWEQg2O3SKONsWE4w7AXFRkryS53bpWdaL9cNol+AmR3AEYz6kn+o0fCPnw==", - "dev": true - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - }, - "last-run": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/last-run/-/last-run-1.1.1.tgz", - "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", - "dev": true, - "requires": { - "default-resolution": "^2.0.0", - "es6-weak-map": "^2.0.1" - } - }, - "lazystream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", - "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", - "dev": true, - "requires": { - "readable-stream": "^2.0.5" - } - }, - "lcid": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", - "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", - "dev": true, - "requires": { - "invert-kv": "^1.0.0" - } - }, - "lead": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/lead/-/lead-1.0.0.tgz", - "integrity": "sha1-bxT5mje+Op3XhPVJVpDlkDRm7kI=", - "dev": true, - "requires": { - "flush-write-stream": "^1.0.2" - } - }, - "liftoff": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-2.5.0.tgz", - "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", - "dev": true, - "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - } - } - }, - "load-json-file": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", - "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "lodash": { - "version": "4.17.11", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", - "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==", - "dev": true - }, - "lodash._baseassign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", - "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash._basecopy": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", - "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", - "dev": true - }, - "lodash._basetostring": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz", - "integrity": "sha1-0YYdh3+CSlL2aYMtyvPuFVZqB9U=", - "dev": true - }, - "lodash._basevalues": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz", - "integrity": "sha1-W3dXYoAr3j0yl1A+JjAIIP32Ybc=", - "dev": true - }, - "lodash._bindcallback": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz", - "integrity": "sha1-5THCdkTPi1epnhftlbNcdIeJOS4=", - "dev": true - }, - "lodash._createassigner": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash._createassigner/-/lodash._createassigner-3.1.1.tgz", - "integrity": "sha1-g4pbri/aymOsIt7o4Z+k5taXCxE=", - "dev": true, - "requires": { - "lodash._bindcallback": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash.restparam": "^3.0.0" - } - }, - "lodash._getnative": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", - "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", - "dev": true - }, - "lodash._isiterateecall": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", - "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", - "dev": true - }, - "lodash._reescape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz", - "integrity": "sha1-Kx1vXf4HyKNVdT5fJ/rH8c3hYWo=", - "dev": true - }, - "lodash._reevaluate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz", - "integrity": "sha1-WLx0xAZklTrgsSTYBpltrKQx4u0=", - "dev": true - }, - "lodash._reinterpolate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", - "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", - "dev": true - }, - "lodash._root": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz", - "integrity": "sha1-+6HEUkwZ7ppfgTa0YJ8BfPTe1pI=", - "dev": true - }, - "lodash.assign": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-3.2.0.tgz", - "integrity": "sha1-POnwI0tLIiPilrj6CsH+6OvKZPo=", - "dev": true, - "requires": { - "lodash._baseassign": "^3.0.0", - "lodash._createassigner": "^3.0.0", - "lodash.keys": "^3.0.0" - } - }, - "lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", - "dev": true - }, - "lodash.defaults": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-3.1.2.tgz", - "integrity": "sha1-xzCLGNv4vJNy1wGnNJPGEZK9Liw=", - "dev": true, - "requires": { - "lodash.assign": "^3.0.0", - "lodash.restparam": "^3.0.0" - } - }, - "lodash.escape": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz", - "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", - "dev": true, - "requires": { - "lodash._root": "^3.0.0" - } - }, - "lodash.isarguments": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", - "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", - "dev": true - }, - "lodash.isarray": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", - "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", - "dev": true - }, - "lodash.keys": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", - "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", - "dev": true, - "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" - } - }, - "lodash.restparam": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz", - "integrity": "sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU=", - "dev": true - }, - "lodash.template": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz", - "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", - "dev": true, - "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" - } - }, - "lodash.templatesettings": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz", - "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", - "dev": true, - "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" - } - }, - "make-iterator": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.1.tgz", - "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - }, - "dependencies": { - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "matchdep": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/matchdep/-/matchdep-2.0.0.tgz", - "integrity": "sha1-xvNINKDY28OzfCfui7yyfHd1WC4=", - "dev": true, - "requires": { - "findup-sync": "^2.0.0", - "micromatch": "^3.0.4", - "resolve": "^1.4.0", - "stack-trace": "0.0.10" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "detect-file": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", - "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "expand-tilde": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", - "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "findup-sync": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-2.0.0.tgz", - "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", - "dev": true, - "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" - } - }, - "global-modules": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", - "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", - "dev": true, - "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" - } - }, - "global-prefix": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", - "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "requires": { - "is-extglob": "^2.1.0" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "resolve-dir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", - "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", - "dev": true, - "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" - } - } - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", - "integrity": "sha1-3j+YVD2/lggr5IrRoMfNqDYwHc8=", - "dev": true - }, - "mixin-deep": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.1.tgz", - "integrity": "sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ==", - "dev": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "modify-filename": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/modify-filename/-/modify-filename-1.1.0.tgz", - "integrity": "sha1-mi3sg4Bvuy2XXyK+7IWcoms5OqE=", - "dev": true - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "multipipe": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz", - "integrity": "sha1-Ko8t33Du1WTf8tV/HhoTfZ8FB4s=", - "dev": true, - "requires": { - "duplexer2": "0.0.2" - } - }, - "mute-stdout": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mute-stdout/-/mute-stdout-1.0.1.tgz", - "integrity": "sha512-kDcwXR4PS7caBpuRYYBUz9iVixUk3anO3f5OYFiIPwK/20vCzKCHyKoulbiDY1S53zD2bxUpxN/IJ+TnXjfvxg==", - "dev": true - }, - "nan": { - "version": "2.11.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz", - "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==", - "dev": true, - "optional": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "next-tick": { - "version": "1.0.0", - "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true - }, - "node-exceptions": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/node-exceptions/-/node-exceptions-4.0.1.tgz", - "integrity": "sha512-KJI+FawYOv74x60H6+zrBPfO2vvp9m0pHZi6SH8BBBuc67Irv11DsqY4Le4EBFq1/T5aXFU3hkLrMgtW7RNXxA==", - "dev": true - }, - "normalize-package-data": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", - "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - }, - "now-and-later": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/now-and-later/-/now-and-later-2.0.0.tgz", - "integrity": "sha1-vGHLtFbXnLMiB85HygUTb/Ln1u4=", - "dev": true, - "requires": { - "once": "^1.3.2" - } - }, - "number-is-nan": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", - "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", - "dev": true - }, - "o-stream": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/o-stream/-/o-stream-0.2.2.tgz", - "integrity": "sha512-V3j76KU3g/Gyl8rpdi2z72rn5zguMvTCQgAXfBe3pxEefKqXmOUOD7mvx/mNjykdxGqDVfpSoo8r+WdrkWg/1Q==", - "dev": true - }, - "object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "object-keys": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", - "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "requires": { - "isobject": "^3.0.0" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "object.defaults": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/object.defaults/-/object.defaults-1.1.0.tgz", - "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", - "dev": true, - "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.map/-/object.map-1.0.1.tgz", - "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "requires": { - "isobject": "^3.0.1" - }, - "dependencies": { - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "object.reduce": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.reduce/-/object.reduce-1.0.1.tgz", - "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", - "dev": true, - "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" - }, - "dependencies": { - "for-own": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/for-own/-/for-own-1.0.0.tgz", - "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", - "dev": true, - "requires": { - "for-in": "^1.0.1" - } - } - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "optimist": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", - "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", - "dev": true, - "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" - } - }, - "ordered-read-streams": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-1.0.1.tgz", - "integrity": "sha1-d8DLN8QVJdZBZtmQ/61+xqDhNj4=", - "dev": true, - "requires": { - "readable-stream": "^2.0.1" - } - }, - "os-locale": { - "version": "1.4.0", - "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", - "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", - "dev": true, - "requires": { - "lcid": "^1.0.0" - } - }, - "p-map": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-1.2.0.tgz", - "integrity": "sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA==", - "dev": true - }, - "package-json-validator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/package-json-validator/-/package-json-validator-0.6.3.tgz", - "integrity": "sha512-juKiFboV4UKUvWQ+OSxstnyukhuluyuEoFmgZw1Rx21XzmwlgDWLcbl3qzjA3789IRORYhVFs7cmAO0YFGwHCg==", - "dev": true, - "requires": { - "optimist": "~0.6.0" - } - }, - "parse-filepath": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", - "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" - } - }, - "parse-import": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/parse-import/-/parse-import-2.0.0.tgz", - "integrity": "sha1-KyR0Aw4AirmNt2xLy/TbWucwb18=", - "dev": true, - "requires": { - "get-imports": "^1.0.0" - } - }, - "parse-json": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", - "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", - "dev": true, - "requires": { - "error-ex": "^1.2.0" - } - }, - "parse-passwd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", - "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", - "dev": true - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true - }, - "path-exists": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", - "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", - "dev": true, - "requires": { - "pinkie-promise": "^2.0.0" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-is-inside": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", - "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", - "dev": true - }, - "path-parse": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", - "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", - "dev": true - }, - "path-root": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", - "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", - "dev": true, - "requires": { - "path-root-regex": "^0.1.0" - } - }, - "path-root-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", - "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=", - "dev": true - }, - "path-type": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", - "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" - } - }, - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - }, - "pinkie": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", - "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", - "dev": true - }, - "pinkie-promise": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", - "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", - "dev": true, - "requires": { - "pinkie": "^2.0.0" - } - }, - "plugin-error": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/plugin-error/-/plugin-error-1.0.1.tgz", - "integrity": "sha512-L1zP0dk7vGweZME2i+EeakvUNqSrdiI3F91TwEoYiGrAfUXmVv6fJIq4g82PAXxNsWOp0J7ZqQy/3Szz0ajTxA==", - "dev": true, - "requires": { - "ansi-colors": "^1.0.1", - "arr-diff": "^4.0.0", - "arr-union": "^3.1.0", - "extend-shallow": "^3.0.2" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true - }, - "pretty-hrtime": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", - "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", - "dev": true - }, - "process-nextick-args": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", - "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=", - "dev": true - }, - "pump": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", - "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", - "dev": true, - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "pumpify": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", - "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", - "dev": true, - "requires": { - "duplexify": "^3.6.0", - "inherits": "^2.0.3", - "pump": "^2.0.0" - } - }, - "read-pkg": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", - "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", - "dev": true, - "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" - } - }, - "read-pkg-up": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", - "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", - "dev": true, - "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" - } - }, - "readable-stream": { - "version": "2.3.6", - "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", - "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", - "dev": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - }, - "dependencies": { - "process-nextick-args": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", - "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==", - "dev": true - } - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - }, - "dependencies": { - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - } - }, - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - } - } - }, - "rechoir": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", - "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", - "dev": true, - "requires": { - "resolve": "^1.1.6" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "remove-bom-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", - "integrity": "sha512-8v2rWhaakv18qcvNeli2mZ/TMTL2nEyAKRvzo1WtnZBl15SHyEhrCu2/xKlJyUFKHiHgfXIyuY6g2dObJJycXQ==", - "dev": true, - "requires": { - "is-buffer": "^1.1.5", - "is-utf8": "^0.2.1" - } - }, - "remove-bom-stream": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/remove-bom-stream/-/remove-bom-stream-1.2.0.tgz", - "integrity": "sha1-BfGlk/FuQuH7kOv1nejlaVJflSM=", - "dev": true, - "requires": { - "remove-bom-buffer": "^3.0.0", - "safe-buffer": "^5.1.0", - "through2": "^2.0.3" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true - }, - "repeat-element": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", - "dev": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true - }, - "replace-ext": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", - "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", - "dev": true - }, - "replace-homedir": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/replace-homedir/-/replace-homedir-1.0.0.tgz", - "integrity": "sha1-6H9tUTuSjd6AgmDBK+f+xv9ueYw=", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1", - "is-absolute": "^1.0.0", - "remove-trailing-separator": "^1.1.0" - } - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", - "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=", - "dev": true - }, - "resolve": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz", - "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==", - "dev": true, - "requires": { - "path-parse": "^1.0.5" - } - }, - "resolve-options": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/resolve-options/-/resolve-options-1.1.0.tgz", - "integrity": "sha1-MrueOcBtZzONyTeMDW1gdFZq0TE=", - "dev": true, - "requires": { - "value-or-function": "^3.0.0" - } - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true - }, - "rev-hash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rev-hash/-/rev-hash-2.0.0.tgz", - "integrity": "sha1-dyCiNu0MJY3z5kvsA+wEiwW5JMQ=", - "dev": true - }, - "rev-path": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/rev-path/-/rev-path-2.0.0.tgz", - "integrity": "sha512-G5R2L9gYu9kEuqPfIFgO9gO+OhBWOAT83HyauOQmGHO6y9Fsa4acv+XsmNhNDrod0HDh1/VxJRmsffThzeHJlQ==", - "dev": true, - "requires": { - "modify-filename": "^1.0.0" - } - }, - "rework": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/rework/-/rework-1.0.1.tgz", - "integrity": "sha1-MIBqhBNCtUUQqkEQhQzUhTQUSqc=", - "dev": true, - "requires": { - "convert-source-map": "^0.3.3", - "css": "^2.0.0" - }, - "dependencies": { - "convert-source-map": { - "version": "0.3.5", - "resolved": "http://registry.npmjs.org/convert-source-map/-/convert-source-map-0.3.5.tgz", - "integrity": "sha1-8dgClQr33SYxof6+BZZVDIarMZA=", - "dev": true - } - } - }, - "rework-import": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/rework-import/-/rework-import-2.1.0.tgz", - "integrity": "sha1-wm7StTFZrHvi7GDaIj74lgPB7x8=", - "dev": true, - "requires": { - "css": "^2.0.0", - "globby": "^2.0.0", - "parse-import": "^2.0.0", - "url-regex": "^3.0.0" - }, - "dependencies": { - "glob": { - "version": "5.0.15", - "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", - "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", - "dev": true, - "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "2 || 3", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "globby": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/globby/-/globby-2.1.0.tgz", - "integrity": "sha1-npGSvNM/Srak+JTl5+qLcTITxII=", - "dev": true, - "requires": { - "array-union": "^1.0.1", - "async": "^1.2.1", - "glob": "^5.0.3", - "object-assign": "^3.0.0" - } - }, - "object-assign": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", - "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", - "dev": true - } - } - }, - "rework-plugin-function": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/rework-plugin-function/-/rework-plugin-function-1.0.2.tgz", - "integrity": "sha1-Es5G+1sptdk1FGaD9rmM9J0jc7k=", - "dev": true, - "requires": { - "rework-visit": "^1.0.0" - } - }, - "rework-plugin-url": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/rework-plugin-url/-/rework-plugin-url-1.1.0.tgz", - "integrity": "sha1-q1PosQV7nV7MHIJz/32xhgg3XEU=", - "dev": true, - "requires": { - "rework-plugin-function": "^1.0.0" - } - }, - "rework-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rework-visit/-/rework-visit-1.0.0.tgz", - "integrity": "sha1-mUWygD8hni96ygCtuLyfZA+ELJo=", - "dev": true - }, - "rimraf": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", - "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", - "dev": true, - "requires": { - "glob": "^7.0.5" - } - }, - "safe-buffer": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", - "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "http://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "requires": { - "ret": "~0.1.10" - } - }, - "semver": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", - "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==", - "dev": true - }, - "semver-greatest-satisfied-range": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/semver-greatest-satisfied-range/-/semver-greatest-satisfied-range-1.1.0.tgz", - "integrity": "sha1-E+jCZYq5aRywzXEJMkAoDTb3els=", - "dev": true, - "requires": { - "sver-compat": "^1.5.0" - } - }, - "semver-intersect": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/semver-intersect/-/semver-intersect-1.4.0.tgz", - "integrity": "sha512-d8fvGg5ycKAq0+I6nfWeCx6ffaWJCsBYU0H2Rq56+/zFePYfT8mXkB3tWBSjR5BerkHNZ5eTPIk1/LBYas35xQ==", - "dev": true, - "requires": { - "semver": "^5.0.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.0.tgz", - "integrity": "sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg==", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "kind-of": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", - "dev": true - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "requires": { - "kind-of": "^3.2.0" - } - }, - "sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", - "dev": true, - "requires": { - "is-plain-obj": "^1.0.0" - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", - "integrity": "sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA==", - "dev": true, - "requires": { - "atob": "^2.1.1", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", - "integrity": "sha512-gR6Rw4MvUlYy83vP0vxoVNzM6t8MUXqNuRsuBmBHQDu1Fh6X015FrLdgoDKcNdkwGubozq0P4N0Q37UyFVr1EA==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true - }, - "sparkles": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.0.tgz", - "integrity": "sha1-Gsu/tZJDbRC76PeFt8xvgoFQEsM=", - "dev": true - }, - "spdx-correct": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", - "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-exceptions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", - "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==", - "dev": true - }, - "spdx-expression-parse": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", - "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", - "dev": true, - "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" - } - }, - "spdx-license-ids": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.2.tgz", - "integrity": "sha512-qky9CVt0lVIECkEsYbNILVnPvycuEBkXoMFLRWsREkomQLevYhtRKC+R91a5TOAQ3bCMjikRwhyaRqj1VYatYg==", - "dev": true - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "stack-trace": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", - "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-exhaust": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/stream-exhaust/-/stream-exhaust-1.0.2.tgz", - "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==", - "dev": true - }, - "stream-shift": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", - "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", - "dev": true - }, - "string-width": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", - "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", - "dev": true, - "requires": { - "code-point-at": "^1.0.0", - "is-fullwidth-code-point": "^1.0.0", - "strip-ansi": "^3.0.0" - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "strip-bom": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", - "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", - "dev": true, - "requires": { - "is-utf8": "^0.2.0" - } - }, - "strip-bom-buf": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-buf/-/strip-bom-buf-1.0.0.tgz", - "integrity": "sha1-HLRar1dTD0yvhsf3UXnSyaUd1XI=", - "dev": true, - "requires": { - "is-utf8": "^0.2.1" - } - }, - "strip-bom-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-2.0.0.tgz", - "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", - "dev": true, - "requires": { - "first-chunk-stream": "^2.0.0", - "strip-bom": "^2.0.0" - } - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "sver-compat": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/sver-compat/-/sver-compat-1.5.0.tgz", - "integrity": "sha1-PPh9/rTQe0o/FIJ7wYaz/QxkXNg=", - "dev": true, - "requires": { - "es6-iterator": "^2.0.1", - "es6-symbol": "^3.1.1" - } - }, - "terser": { - "version": "3.10.11", - "resolved": "https://registry.npmjs.org/terser/-/terser-3.10.11.tgz", - "integrity": "sha512-iruZ7j14oBbRYJC5cP0/vTU7YOWjN+J1ZskEGoF78tFzXdkK2hbCL/3TRZN8XB+MuvFhvOHMp7WkOCBO4VEL5g==", - "dev": true, - "requires": { - "commander": "~2.17.1", - "source-map": "~0.6.1", - "source-map-support": "~0.5.6" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "through2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", - "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", - "dev": true, - "requires": { - "readable-stream": "~2.3.6", - "xtend": "~4.0.1" - } - }, - "through2-filter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", - "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", - "dev": true, - "requires": { - "through2": "~2.0.0", - "xtend": "~4.0.0" - } - }, - "time-stamp": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", - "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", - "dev": true - }, - "to-absolute-glob": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", - "integrity": "sha1-GGX0PZ50sIItufFFt4z/fQ98hJs=", - "dev": true, - "requires": { - "is-absolute": "^1.0.0", - "is-negated-glob": "^1.0.0" - } - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - } - } - }, - "to-through": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-through/-/to-through-2.0.0.tgz", - "integrity": "sha1-/JKtq6ByZHvAtn1rA2ZKoZUJOvY=", - "dev": true, - "requires": { - "through2": "^2.0.3" - } - }, - "typedarray": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", - "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", - "dev": true - }, - "unc-path-regex": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", - "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=", - "dev": true - }, - "undertaker": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", - "integrity": "sha1-M52kZGJS0ILcN45wgGcpl1DhG0k=", - "dev": true, - "requires": { - "arr-flatten": "^1.0.1", - "arr-map": "^2.0.0", - "bach": "^1.0.0", - "collection-map": "^1.0.0", - "es6-weak-map": "^2.0.1", - "last-run": "^1.1.0", - "object.defaults": "^1.0.0", - "object.reduce": "^1.0.0", - "undertaker-registry": "^1.0.0" - } - }, - "undertaker-registry": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/undertaker-registry/-/undertaker-registry-1.0.1.tgz", - "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=", - "dev": true - }, - "union-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz", - "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", - "dev": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "set-value": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-0.4.3.tgz", - "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", - "dev": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" - } - } - } - }, - "unique-stream": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", - "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", - "dev": true, - "requires": { - "json-stable-stringify": "^1.0.0", - "through2-filter": "^2.0.0" - } - }, - "universalify": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", - "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", - "dev": true - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - } - } - }, - "upath": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.1.0.tgz", - "integrity": "sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw==", - "dev": true - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true - }, - "url-regex": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", - "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", - "dev": true, - "requires": { - "ip-regex": "^1.0.1" - } - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true - }, - "v8flags": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/v8flags/-/v8flags-3.1.1.tgz", - "integrity": "sha512-iw/1ViSEaff8NJ3HLyEjawk/8hjJib3E7pvG4pddVXfUg1983s3VGsiClDjhK64MQVDGqc1Q8r18S4VKQZS9EQ==", - "dev": true, - "requires": { - "homedir-polyfill": "^1.0.1" - } - }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, - "value-or-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/value-or-function/-/value-or-function-3.0.0.tgz", - "integrity": "sha1-HCQ6ULWVwb5Up1S/7OhWO5/42BM=", - "dev": true - }, - "vinyl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-2.2.0.tgz", - "integrity": "sha512-MBH+yP0kC/GQ5GwBqrTPTzEfiiLjta7hTtvQtbxBgTeSXsmKQRQecjibMbxIXzVT3Y9KJK+drOz1/k+vsu8Nkg==", - "dev": true, - "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" - } - }, - "vinyl-file": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/vinyl-file/-/vinyl-file-3.0.0.tgz", - "integrity": "sha1-sQTZ5ECf+jJfqt1SBkLQo7SIs2U=", - "dev": true, - "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.3.0", - "strip-bom-buf": "^1.0.0", - "strip-bom-stream": "^2.0.0", - "vinyl": "^2.0.1" - } - }, - "vinyl-fs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-3.0.3.tgz", - "integrity": "sha512-vIu34EkyNyJxmP0jscNzWBSygh7VWhqun6RmqVfXePrOwi9lhvRs//dOaGOTRUQr4tx7/zd26Tk5WeSVZitgng==", - "dev": true, - "requires": { - "fs-mkdirp-stream": "^1.0.0", - "glob-stream": "^6.1.0", - "graceful-fs": "^4.0.0", - "is-valid-glob": "^1.0.0", - "lazystream": "^1.0.0", - "lead": "^1.0.0", - "object.assign": "^4.0.4", - "pumpify": "^1.3.5", - "readable-stream": "^2.3.3", - "remove-bom-buffer": "^3.0.0", - "remove-bom-stream": "^1.2.0", - "resolve-options": "^1.1.0", - "through2": "^2.0.0", - "to-through": "^2.0.0", - "value-or-function": "^3.0.0", - "vinyl": "^2.0.0", - "vinyl-sourcemap": "^1.1.0" - } - }, - "vinyl-sourcemap": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/vinyl-sourcemap/-/vinyl-sourcemap-1.1.0.tgz", - "integrity": "sha1-kqgAWTo4cDqM2xHYswCtS+Y7PhY=", - "dev": true, - "requires": { - "append-buffer": "^1.0.2", - "convert-source-map": "^1.5.0", - "graceful-fs": "^4.1.6", - "normalize-path": "^2.1.1", - "now-and-later": "^2.0.0", - "remove-bom-buffer": "^3.0.0", - "vinyl": "^2.0.0" - } - }, - "vinyl-sourcemaps-apply": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/vinyl-sourcemaps-apply/-/vinyl-sourcemaps-apply-0.2.1.tgz", - "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", - "dev": true, - "requires": { - "source-map": "^0.5.1" - } - }, - "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz", - "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=", - "dev": true - }, - "wordwrap": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", - "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=", - "dev": true - }, - "wrap-ansi": { - "version": "2.1.0", - "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", - "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", - "dev": true, - "requires": { - "string-width": "^1.0.1", - "strip-ansi": "^3.0.1" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "xtend": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", - "dev": true - }, - "y18n": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", - "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", - "dev": true - }, - "yargs": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz", - "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", - "dev": true, - "requires": { - "camelcase": "^3.0.0", - "cliui": "^3.2.0", - "decamelize": "^1.1.1", - "get-caller-file": "^1.0.1", - "os-locale": "^1.4.0", - "read-pkg-up": "^1.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^1.0.1", - "set-blocking": "^2.0.0", - "string-width": "^1.0.2", - "which-module": "^1.0.0", - "y18n": "^3.2.1", - "yargs-parser": "^5.0.0" - } - }, - "yargs-parser": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-5.0.0.tgz", - "integrity": "sha1-J17PDX/+Bcd+ZOfIbkzZS/DhIoo=", - "dev": true, - "requires": { - "camelcase": "^3.0.0" - } - }, - "yarn": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.12.3.tgz", - "integrity": "sha512-8f5rWNDvkhAmCxmn8C0LsNWMxTYVk4VGKiq0sIB6HGZjaZTHsGIH87SUmVDUEd2Wk54bqKoUlbVWgQFCQhRkVw==", - "dev": true - } - } -} From cdea507a299d880e06c98b4b9d0b34650e293c9d Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Fri, 21 Dec 2018 17:43:47 +1100 Subject: [PATCH 163/237] Fix improperly implemented `npm install` skip --- app/system/Bakery/Command/BuildAssets.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/system/Bakery/Command/BuildAssets.php index 3c3015b7b..612a939d8 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/system/Bakery/Command/BuildAssets.php @@ -75,20 +75,25 @@ protected function execute(InputInterface $input, OutputInterface $output) protected function npmInstall($force) { $this->io->section('Installing npm dependencies'); - - // Skip install if lockfile is newer - if (!$force || filemtime("package.json") > filemtime("package-lock.json") + 1000) { - $this->io->writeln('> Skipping npm install which has been previously run'); - return; - } - $this->io->writeln('> npm install'); // Temporarily change the working directory so we can install npm dependencies $wd = getcwd(); chdir($this->buildPath); + + // Skip if lockfile indicates previous run + if (!$force && file_exists('package-lock.json') && filemtime('package.json') < filemtime('package-lock.json') - 1) { + $this->io->writeln('> Skipping as package-lock.json age indicates dependencies are already installed'); + chdir($wd); + return; + } + $exitCode = 0; passthru('npm install', $exitCode); + + // Ensure lockfile last-modified date is updated + touch('package-lock.json'); + chdir($wd); if ($exitCode !== 0) { From 88f77bff8f06e6a06c4ae246ed4c5150452e748e Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Mon, 7 Jan 2019 22:04:49 +1100 Subject: [PATCH 164/237] Sidesteped flat dependencies requirement with browserify --- app/defines.php | 1 + app/sprinkles/core/package.json | 3 - app/system/ServicesProvider.php | 1 + build/gulpfile.js | 220 ++++++++++++++++---------------- build/package.json | 8 +- 5 files changed, 116 insertions(+), 117 deletions(-) diff --git a/app/defines.php b/app/defines.php index 5b4b14025..e9efd7059 100755 --- a/app/defines.php +++ b/app/defines.php @@ -69,4 +69,5 @@ // Full path to frontend vendor asset directories define('UserFrosting\ASSET_DIR', APP_DIR_NAME . DS . ASSET_DIR_NAME); define('UserFrosting\NPM_ASSET_DIR', ASSET_DIR . DS . 'node_modules'); +define('UserFrosting\BROWSERIFIED_ASSET_DIR', ASSET_DIR . DS . 'browser_modules'); define('UserFrosting\BOWER_ASSET_DIR', ASSET_DIR . DS . 'bower_components'); diff --git a/app/sprinkles/core/package.json b/app/sprinkles/core/package.json index 005adc50c..cb2526ebd 100644 --- a/app/sprinkles/core/package.json +++ b/app/sprinkles/core/package.json @@ -17,8 +17,5 @@ "fastclick": "^1.0.6", "ionicons": "^2.0.1", "urijs": "^1.18.4" - }, - "resolutions": { - "optimist": "0.6.1" } } diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index d0d043011..8f6ca92b0 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -55,6 +55,7 @@ public function register(ContainerInterface $container) $locator->registerStream('session', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); $locator->registerStream('assets', 'vendor', \UserFrosting\BOWER_ASSET_DIR, true); $locator->registerStream('assets', 'vendor', \UserFrosting\NPM_ASSET_DIR, true); + $locator->registerStream('assets', 'vendor', \UserFrosting\BROWSERIFIED_ASSET_DIR, true); // Register sprinkles streams $locator->registerStream('assets', '', \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME); diff --git a/build/gulpfile.js b/build/gulpfile.js index a1378c81b..7cbe73c1a 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -1,6 +1,7 @@ "use strict"; -const { bower: mergeBowerDeps, yarn: mergeYarnDeps, yarnIsFlat } = require("@userfrosting/merge-package-dependencies"); +const { bower: mergeBowerDeps, npm: mergeNpmDeps } = require("@userfrosting/merge-package-dependencies"); const { config: envConfig } = require("dotenv"); +const { default: browserifyDependencies } = require("@userfrosting/browserify-dependencies"); const { default: Bundler, ValidateRawConfig, MergeRawConfigs } = require("@userfrosting/gulp-bundle-assets"); const { default: minifyJs } = require("gulp-uglify-es"); const { execSync } = require("child_process"); @@ -26,7 +27,7 @@ const doILog = (process.env.UF_MODE === "dev"); * @param {any} message Message to log. */ function Logger(message, source) { - if (!doILog) { + if (doILog) { if (source) log.info(`${source}: ${message}`); else @@ -55,126 +56,124 @@ catch (error) { /** * Installs vendor assets. Mapped to npm script "uf-assets-install". - * @param {() => {}} done Used to mark task completion. */ -function assetsInstall(done) { - try { - // This script requires the npm environment, and therefore cannot be run directly with the gulp CLI. - if (!process.env.npm_lifecycle_event) throw new Error("Assets installation must be run via 'npm run uf-assets-install'"); - - // Clean up any legacy assets - if (deleteSync(legacyVendorAssetsGlob, { force: true })) - Logger("Legacy frontend vendor assets were deleted. Frontend vendor assets are now installed to 'app/assets'."); - - // See if there are any yarn packages - // TODO Would be better to read in file here then hand it off since we can avoid redundant `existsSync` calls - const yarnPaths = []; - for (const sprinkle of sprinkles) { - const path = sprinklesDir + sprinkle + "/package.json"; - if (existsSync(path)) yarnPaths.push(path); - } +async function assetsInstall() { + // Clean up any legacy assets + if (deleteSync(legacyVendorAssetsGlob, { force: true })) + Logger("Legacy frontend vendor assets were deleted. Frontend vendor assets are now installed to 'app/assets'."); + + // See if there are any npm packages + // TODO Would be better to read in file here then hand it off since we can avoid redundant `existsSync` calls + const npmPaths = []; + for (const sprinkle of sprinkles) { + const path = sprinklesDir + sprinkle + "/package.json"; + if (existsSync(path)) npmPaths.push(path); + } - if (yarnPaths.length > 0) { - // Install yarn dependencies - Logger("Installing vendor assets with Yarn...") - - // TODO I think we might be able to get away with removing this, since yarn.lock is synced with package.json - deleteSync([vendorAssetsDir + "package.json", vendorAssetsDir + "yarn.lock"], { force: true }); - - // Generate package.json - const yarnTemplate = { - // Private makes sure it isn't published, and cuts out a lot of unnecessary fields. - private: true - }; - Logger("Collating dependencies..."); - mergeYarnDeps(yarnTemplate, yarnPaths, vendorAssetsDir, doILog); - Logger("Dependency collation complete."); - - // Perform installation - // Yarn will automatically remove extraneous packages (barring algorithm failure) - // --flat switch cannot be used currently due to https://github.com/yarnpkg/yarn/issues/1658 however "resolutions" thankfully will still work - Logger("Running yarn install --non-interactive"); - execSync("yarn install --non-interactive", { + if (npmPaths.length > 0) { + // Install npm dependencies + Logger("Installing vendor assets with NPM...") + + // Remove package.json (package-lock.json can be left untouched as dates will invalidate it) + deleteSync(vendorAssetsDir + "package.json", { force: true }); + + // Generate package.json + const npmTemplate = { + // Private makes sure it isn't published, and cuts out a lot of unnecessary fields. + private: true + }; + Logger("Collating dependencies..."); + const pkg = mergeNpmDeps(npmTemplate, npmPaths, vendorAssetsDir, doILog); + Logger("Dependency collation complete."); + + // Perform installation + // NPM will automatically remove extraneous packages (barring algorithm failure) during install + Logger("Running npm install"); + execSync("npm install", { + cwd: vendorAssetsDir, + stdio: doILog ? "inherit" : "" + }); + + // Conduct audit + Logger("Running npm audit"); + try { + execSync("npm audit", { cwd: vendorAssetsDir, stdio: doILog ? "inherit" : "" }); - - // Ensure dependency tree is flat - Logger("Inspecting dependency tree..."); - if (!yarnIsFlat(vendorAssetsDir, doILog)) { - Logger(` -Dependency tree is not flat! Dependencies must be flat to prevent abnormal behavior of frontend dependencies. -Recommended solution is to adjust dependency versions until issue is resolved to ensure 100% compatibility. -Alternatively, resolutions can be used as an override, as documented at https://yarnpkg.com/en/docs/selective-version-resolutions -`); - throw new Error("Dependency tree is not flat."); - } - else Logger("Dependency tree is flat and therefore usable."); - } - else { - // Delete yarn artefacts - deleteSync([ - vendorAssetsDir + "package.json", - vendorAssetsDir + "node_modules/", - vendorAssetsDir + "yarn.lock" - ], { force: true }); } - - // See if there are any Bower packages - // TODO Would be better to read in file here then hand it off since we can avoid redundant `existsSync` calls - const bowerPaths = []; - for (const sprinkle of sprinkles) { - const path = sprinklesDir + sprinkle + "/bower.json"; - if (existsSync(path)) { - // TODO: We should really have a link to docs in the message - console.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`); - bowerPaths.push(path); - } + catch { + Logger("There appear to be some vulerabilities within your dependencies. Updating is recommended."); } - if (bowerPaths.length > 0) { - // Install yarn dependencies - Logger("Installing vendor assets with Bower...") - - // TODO I think we might be able to get away with removing this - deleteSync(vendorAssetsDir + "bower.json", { force: true }); - - // Generate package.json - const bowerTemplate = { - name: "uf-vendor-assets" - }; - Logger("Collating dependencies..."); - mergeBowerDeps(bowerTemplate, bowerPaths, vendorAssetsDir, doILog); - Logger("Dependency collation complete."); - - // Perform installation - Logger("Running bower install -q --allow-root"); - // --allow-root stops bower from complaining about being in 'sudo' in various situations - execSync("bower install -q --allow-root", { - cwd: vendorAssetsDir, - stdio: doILog ? "inherit" : "" - }); + // Browserify dependencies + Logger("Running browserify against npm dependencies with a main entrypoint"); + deleteSync(vendorAssetsDir + "browser_modules/", { force: true }); + await browserifyDependencies({ + dependencies: Object.keys(pkg.dependencies), + inputDir: vendorAssetsDir + "node_modules/", + outputDir: vendorAssetsDir + "browser_modules/" + }) + } + else { + // Delete npm artefacts + deleteSync([ + vendorAssetsDir + "package.json", + vendorAssetsDir + "node_modules/", + vendorAssetsDir + "package-lock.json", + vendorAssetsDir + "browser_modules/" + ], { force: true }); + } - // Prune any unnecessary dependencies - Logger("Running bower prune -q --allow-root"); - // --allow-root stops bower from complaining about being in 'sudo' in various situations - execSync("bower prune -q --allow-root", { - cwd: vendorAssetsDir, - stdio: doILog ? "inherit" : "" - }); - } - else { - // Remove bower artefacts - deleteSync([ - vendorAssetsDir + "bower.json", - vendorAssetsDir + "bower_components/" - ], { force: true }); + // See if there are any Bower packages + // TODO Would be better to read in file here then hand it off since we can avoid redundant `existsSync` calls + const bowerPaths = []; + for (const sprinkle of sprinkles) { + const path = sprinklesDir + sprinkle + "/bower.json"; + if (existsSync(path)) { + // TODO: We should really have a link to docs in the message + console.warn(`DEPRECATED: Detected bower.json in ${sprinkle} Sprinkle. Support for bower (bower.json) will be removed in the future, please use npm/yarn (package.json) instead.`); + bowerPaths.push(path); } + } - done(); + if (bowerPaths.length > 0) { + // Install bower dependencies + Logger("Installing vendor assets with Bower...") + + // TODO I think we might be able to get away with removing this + deleteSync(vendorAssetsDir + "bower.json", { force: true }); + + // Generate package.json + const bowerTemplate = { + name: "uf-vendor-assets" + }; + Logger("Collating dependencies..."); + mergeBowerDeps(bowerTemplate, bowerPaths, vendorAssetsDir, doILog); + Logger("Dependency collation complete."); + + // Perform installation + Logger("Running bower install -q --allow-root"); + // --allow-root stops bower from complaining about being in 'sudo' in various situations + execSync("bower install -q --allow-root", { + cwd: vendorAssetsDir, + stdio: doILog ? "inherit" : "" + }); + + // Prune any unnecessary dependencies + Logger("Running bower prune -q --allow-root"); + // --allow-root stops bower from complaining about being in 'sudo' in various situations + execSync("bower prune -q --allow-root", { + cwd: vendorAssetsDir, + stdio: doILog ? "inherit" : "" + }); } - catch (error) { - done(error); + else { + // Remove bower artefacts + deleteSync([ + vendorAssetsDir + "bower.json", + vendorAssetsDir + "bower_components/" + ], { force: true }); } }; @@ -188,6 +187,7 @@ function bundle() { sources.push(sprinklesDir + sprinkle + "/assets/**"); } sources.push(vendorAssetsDir + "node_modules/**"); + sources.push(vendorAssetsDir + "browser_modules/**"); sources.push(vendorAssetsDir + "bower_components/**"); // Create bundle stream factories object diff --git a/build/package.json b/build/package.json index 49b853496..c745d5e96 100755 --- a/build/package.json +++ b/build/package.json @@ -1,7 +1,8 @@ { "private": true, - "devDependencies": { - "@userfrosting/gulp-bundle-assets": "^3.0.0-alpha.6", + "dependencies": { + "@userfrosting/browserify-dependencies": "^1.0.0-alpha.3", + "@userfrosting/gulp-bundle-assets": "^3.0.0-beta.1", "@userfrosting/merge-package-dependencies": "^1.2.1", "bower": "^1.8.4", "del": "^3.0.0", @@ -13,8 +14,7 @@ "gulp-prune": "^0.2.0", "gulp-rev": "^9.0.0", "gulp-uglify-es": "^1.0.4", - "gulplog": "^1.0.0", - "yarn": "^1.12.3" + "gulplog": "^1.0.0" }, "scripts": { "uf-bundle": "gulp bundle", From bb4afecf7dc6b326c67367fb16afd9ddd59ab877 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Mon, 7 Jan 2019 22:11:24 +1100 Subject: [PATCH 165/237] Raised required node and npm versions --- build/package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build/package.json b/build/package.json index c745d5e96..b659e1bdd 100755 --- a/build/package.json +++ b/build/package.json @@ -23,7 +23,8 @@ "uf-clean": "gulp clean" }, "engines": { - "node": ">=8.0.0" + "node": ">=10.12.0", + "npm": ">=6.0.0" }, "engineStrict": true } From 5d8e03992373c82f9a9a133f8c9e57f9579ea235 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Mon, 7 Jan 2019 22:28:22 +1100 Subject: [PATCH 166/237] Update node version on travis --- .travis.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.travis.yml b/.travis.yml index 953401886..8a760b11b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,8 @@ before_install: - cp app/sprinkles.example.json app/sprinkles.json # set up db - bash build/before_install.sh $DB + # update node + - nvm install 10.12.0 before_script: # install deps and UF From 3d64bb1321e5e77cb422294e499fe57bb2ad60a2 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Mon, 7 Jan 2019 22:28:40 +1100 Subject: [PATCH 167/237] Updated changelog with assets rework changes --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f256fc298..fa4970b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Add cache facade (Ref [#838]) - Added `test:mail` Bakery Command - Add support for other config['mailer'] options ([#872]; Thanks @apple314159 !) +- Added support for npm dependencies on the frontend with auditting for known vulnerabilities ### Changed - Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle @@ -45,8 +46,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Changed deprecations to `warning`, and suppressed them in tests - Uncomment foreign keys in core migrations ([#833]) - Move default groups, roles & permissions creation to seeds +- Rewrote asset processing to minimise file sizes, drastically reduce IO, and improve maintainability +- Rewrote frontend dependency installation to prevent duplication and detect incompatibilities -### Fix +### Fixed - Sprinkle without a `template/` folder won't cause error anymore - Fixed routes not available in Tests [and Bakery] ([#854]) - redirect failing in UserController::pageInfo when user not found ([#888]) @@ -65,8 +68,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Removed Bakery `projectRoot` property. Use the `\UserFrosting\ROOT_DIR` constant instead - Removed `pretend` option from Bakery `migrate:refresh` and `migrate:reset` commands -### Fixed - ### Security From a95a495049b61e7540290b924e3cf2b0fc5a51de Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 7 Jan 2019 21:38:41 -0500 Subject: [PATCH 168/237] Updated Node and NPM version check for Bakery --- app/defines.php | 5 +++-- app/sprinkles/core/src/Bakery/DebugCommand.php | 8 ++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/defines.php b/app/defines.php index e9efd7059..2bbb622f4 100755 --- a/app/defines.php +++ b/app/defines.php @@ -9,11 +9,12 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.2.0-alpha.1'); +define('UserFrosting\VERSION', '4.2.0-alpha.2'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\PHP_RECOMMENDED_VERSION', '7.1'); -define('UserFrosting\DEBUG_CONFIG', false); +define('UserFrosting\NODE_MIN_VERSION', '10.12.0'); +define('UserFrosting\NPM_MIN_VERSION', '6.0.0'); // Directories and Paths diff --git a/app/sprinkles/core/src/Bakery/DebugCommand.php b/app/sprinkles/core/src/Bakery/DebugCommand.php index b4b30ba72..7d2583d9a 100644 --- a/app/sprinkles/core/src/Bakery/DebugCommand.php +++ b/app/sprinkles/core/src/Bakery/DebugCommand.php @@ -85,8 +85,8 @@ protected function checkNodeVersion() $npmVersion = trim(exec('node -v')); $this->io->writeln("Node Version : $npmVersion"); - if (version_compare($npmVersion, 'v4', '<')) { - $this->io->error('UserFrosting requires Node version 4.x or above. Check the documentation for more details.'); + if (version_compare($npmVersion, \UserFrosting\NODE_MIN_VERSION, '<')) { + $this->io->error('UserFrosting requires Node version ' . \UserFrosting\NODE_MIN_VERSION . ' or above. Check the documentation for more details.'); exit(1); } } @@ -99,8 +99,8 @@ protected function checkNpmVersion() $npmVersion = trim(exec('npm -v')); $this->io->writeln("NPM Version : $npmVersion"); - if (version_compare($npmVersion, '3', '<')) { - $this->io->error('UserFrosting requires npm version 3.x or above. Check the documentation for more details.'); + if (version_compare($npmVersion, \UserFrosting\NPM_MIN_VERSION, '<')) { + $this->io->error('UserFrosting requires npm version ' . \UserFrosting\NPM_MIN_VERSION . ' or above. Check the documentation for more details.'); exit(1); } } From aadadee63c566b9e2a86bb81b7639baaaa68a6fb Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 7 Jan 2019 21:53:27 -0500 Subject: [PATCH 169/237] Fix missing 'v' in previous commit. --- app/defines.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/defines.php b/app/defines.php index 2bbb622f4..06b03c25b 100755 --- a/app/defines.php +++ b/app/defines.php @@ -13,7 +13,7 @@ define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\PHP_RECOMMENDED_VERSION', '7.1'); -define('UserFrosting\NODE_MIN_VERSION', '10.12.0'); +define('UserFrosting\NODE_MIN_VERSION', 'v10.12.0'); define('UserFrosting\NPM_MIN_VERSION', '6.0.0'); // Directories and Paths From 0fc8c8e68235c8223388603a54690f6a84de0977 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 8 Jan 2019 20:57:29 -0500 Subject: [PATCH 170/237] Moved `build-assets` and `test` Bakery command to Core sprinkle + Moved `DatabaseTest` and `ConfirmableTrait` Traits to Core Sprinkle + added node & npm version check in `build-assets` --- CHANGELOG.md | 4 +- .../account/src/Bakery/CreateAdminUser.php | 4 +- .../core/src/Bakery}/BuildAssets.php | 11 +++- .../core/src/Bakery/DebugCommand.php | 32 ++---------- .../src/Bakery/Helper}/ConfirmableTrait.php | 2 +- .../core/src/Bakery/Helper}/DatabaseTest.php | 2 +- .../src/Bakery/Helper/NodeVersionCheck.php | 52 +++++++++++++++++++ .../core/src/Bakery/MigrateCommand.php | 2 +- app/sprinkles/core/src/Bakery/SeedCommand.php | 2 +- .../core/src/Bakery}/Test.php | 2 +- app/system/Bakery/Bakery.php | 10 ++-- 11 files changed, 80 insertions(+), 43 deletions(-) rename app/{system/Bakery/Command => sprinkles/core/src/Bakery}/BuildAssets.php (95%) rename app/{system/Bakery => sprinkles/core/src/Bakery/Helper}/ConfirmableTrait.php (97%) rename app/{system/Bakery => sprinkles/core/src/Bakery/Helper}/DatabaseTest.php (96%) create mode 100644 app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php rename app/{system/Bakery/Command => sprinkles/core/src/Bakery}/Test.php (97%) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa4970b4a..2ee81f07b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,7 +34,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added support for npm dependencies on the frontend with auditting for known vulnerabilities ### Changed -- Moved `migrate` Bakery command and sub-commands to the `Core` sprinkle +- Moved Bakery commands from `app/System/Bakery` to the `Core` sprinkle and `UserFrosting\Sprinkle\Core\Bakery` namespace. + - Moved `UserFrosting\System\Bakery\DatabaseTest` trait to `UserFrosting\Sprinkle\Core\Bakery\Helper\DatabaseTest`. + - Moved `UserFrosting\System\Bakery\ConfirmableTrait` trait to `UserFrosting\Sprinkle\Core\Bakery\Helper\ConfirmableTrait`. - Re-written the migrator. It is now detached from the console and Bakery and is now included in the Core Sprinkle ServicesProvider ([#795]) - Makes the `semantic versioning` part of a migration class optional. Migrations classes can now have the `UserFrosting\Sprinkle\{sprinkleName}\Database\Migrations` namespace, or any other sub-namespace - Move User registration out of the `AccountController` ([#793]) diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index 2a804b094..0a68f2895 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -11,10 +11,10 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use UserFrosting\System\Bakery\BaseCommand; -use UserFrosting\System\Bakery\DatabaseTest; +use UserFrosting\Sprinkle\Core\Bakery\Helper\DatabaseTest; use UserFrosting\Sprinkle\Account\Account\Registration; use UserFrosting\Sprinkle\Account\Database\Models\User; +use UserFrosting\System\Bakery\BaseCommand; /** * Create root user CLI command. diff --git a/app/system/Bakery/Command/BuildAssets.php b/app/sprinkles/core/src/Bakery/BuildAssets.php similarity index 95% rename from app/system/Bakery/Command/BuildAssets.php rename to app/sprinkles/core/src/Bakery/BuildAssets.php index 612a939d8..70f9a5416 100644 --- a/app/system/Bakery/Command/BuildAssets.php +++ b/app/sprinkles/core/src/Bakery/BuildAssets.php @@ -6,11 +6,12 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\System\Bakery\Command; +namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputOption; +use UserFrosting\Sprinkle\Core\Bakery\Helper\NodeVersionCheck; use UserFrosting\System\Bakery\BaseCommand; /** @@ -21,6 +22,8 @@ */ class BuildAssets extends BaseCommand { + use NodeVersionCheck; + /** * @var string Path to the build/ directory */ @@ -46,6 +49,10 @@ protected function execute(InputInterface $input, OutputInterface $output) // Display header, $this->io->title("UserFrosting's Assets Builder"); + // Validate Node and npm version + $this->checkNodeVersion(false); + $this->checkNpmVersion(false); + // Set $path $this->buildPath = \UserFrosting\ROOT_DIR . \UserFrosting\DS . \UserFrosting\BUILD_DIR_NAME; @@ -69,7 +76,7 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Install npm package - * + * * @param bool $force Force `npm install` to be run, ignoring evidence of a previous run. */ protected function npmInstall($force) diff --git a/app/sprinkles/core/src/Bakery/DebugCommand.php b/app/sprinkles/core/src/Bakery/DebugCommand.php index 7d2583d9a..8fea69c6e 100644 --- a/app/sprinkles/core/src/Bakery/DebugCommand.php +++ b/app/sprinkles/core/src/Bakery/DebugCommand.php @@ -10,8 +10,9 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use UserFrosting\Sprinkle\Core\Bakery\Helper\DatabaseTest; +use UserFrosting\Sprinkle\Core\Bakery\Helper\NodeVersionCheck; use UserFrosting\System\Bakery\BaseCommand; -use UserFrosting\System\Bakery\DatabaseTest; /** * Debug CLI tool. @@ -21,6 +22,7 @@ class DebugCommand extends BaseCommand { use DatabaseTest; + use NodeVersionCheck; /** * {@inheritdoc} @@ -77,34 +79,6 @@ protected function checkPhpVersion() } } - /** - * Check the minimum version requirement of Node installed - */ - protected function checkNodeVersion() - { - $npmVersion = trim(exec('node -v')); - $this->io->writeln("Node Version : $npmVersion"); - - if (version_compare($npmVersion, \UserFrosting\NODE_MIN_VERSION, '<')) { - $this->io->error('UserFrosting requires Node version ' . \UserFrosting\NODE_MIN_VERSION . ' or above. Check the documentation for more details.'); - exit(1); - } - } - - /** - * Check the minimum version requirement for Npm - */ - protected function checkNpmVersion() - { - $npmVersion = trim(exec('npm -v')); - $this->io->writeln("NPM Version : $npmVersion"); - - if (version_compare($npmVersion, \UserFrosting\NPM_MIN_VERSION, '<')) { - $this->io->error('UserFrosting requires npm version ' . \UserFrosting\NPM_MIN_VERSION . ' or above. Check the documentation for more details.'); - exit(1); - } - } - /** * List all sprinkles defined in the Sprinkles schema file, * making sure this file exist at the same time diff --git a/app/system/Bakery/ConfirmableTrait.php b/app/sprinkles/core/src/Bakery/Helper/ConfirmableTrait.php similarity index 97% rename from app/system/Bakery/ConfirmableTrait.php rename to app/sprinkles/core/src/Bakery/Helper/ConfirmableTrait.php index 638a3b3c1..2ac666129 100644 --- a/app/system/Bakery/ConfirmableTrait.php +++ b/app/sprinkles/core/src/Bakery/Helper/ConfirmableTrait.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\System\Bakery; +namespace UserFrosting\Sprinkle\Core\Bakery\Helper; /** * Confirmable Trait. Include method used to confirm action diff --git a/app/system/Bakery/DatabaseTest.php b/app/sprinkles/core/src/Bakery/Helper/DatabaseTest.php similarity index 96% rename from app/system/Bakery/DatabaseTest.php rename to app/sprinkles/core/src/Bakery/Helper/DatabaseTest.php index 6f7e7c7a4..0bf43ee5b 100644 --- a/app/system/Bakery/DatabaseTest.php +++ b/app/sprinkles/core/src/Bakery/Helper/DatabaseTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\System\Bakery; +namespace UserFrosting\Sprinkle\Core\Bakery\Helper; use Illuminate\Database\Capsule\Manager as Capsule; diff --git a/app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php b/app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php new file mode 100644 index 000000000..ed055b3f1 --- /dev/null +++ b/app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php @@ -0,0 +1,52 @@ +io->writeln("Node Version : $npmVersion"); + } + + if (version_compare($npmVersion, \UserFrosting\NODE_MIN_VERSION, '<')) { + $this->io->error('UserFrosting requires Node version ' . \UserFrosting\NODE_MIN_VERSION . ' or above. Check the documentation for more details.'); + exit(1); + } + } + + /** + * Check the minimum version requirement for Npm + * @param bool $displayVersion + */ + protected function checkNpmVersion($displayVersion = true) + { + $npmVersion = trim(exec('npm -v')); + + if ($displayVersion) { + $this->io->writeln("NPM Version : $npmVersion"); + } + + if (version_compare($npmVersion, \UserFrosting\NPM_MIN_VERSION, '<')) { + $this->io->error('UserFrosting requires npm version ' . \UserFrosting\NPM_MIN_VERSION . ' or above. Check the documentation for more details.'); + exit(1); + } + } +} diff --git a/app/sprinkles/core/src/Bakery/MigrateCommand.php b/app/sprinkles/core/src/Bakery/MigrateCommand.php index 3cdeee1a9..4816fbf95 100644 --- a/app/sprinkles/core/src/Bakery/MigrateCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateCommand.php @@ -11,8 +11,8 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputOption; +use UserFrosting\Sprinkle\Core\Bakery\Helper\ConfirmableTrait; use UserFrosting\System\Bakery\BaseCommand; -use UserFrosting\System\Bakery\ConfirmableTrait; /** * migrate Bakery Command diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index 6a38339e7..8e2e6fab9 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -13,8 +13,8 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use UserFrosting\Sprinkle\Core\Database\Seeder\Seeder; +use UserFrosting\Sprinkle\Core\Bakery\Helper\ConfirmableTrait; use UserFrosting\System\Bakery\BaseCommand; -use UserFrosting\System\Bakery\ConfirmableTrait; /** * seed Bakery Command diff --git a/app/system/Bakery/Command/Test.php b/app/sprinkles/core/src/Bakery/Test.php similarity index 97% rename from app/system/Bakery/Command/Test.php rename to app/sprinkles/core/src/Bakery/Test.php index 96eaa2075..3b4a32d4a 100644 --- a/app/system/Bakery/Command/Test.php +++ b/app/sprinkles/core/src/Bakery/Test.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\System\Bakery\Command; +namespace UserFrosting\Sprinkle\Core\Bakery; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; diff --git a/app/system/Bakery/Bakery.php b/app/system/Bakery/Bakery.php index 387e05d8b..f21dbb992 100644 --- a/app/system/Bakery/Bakery.php +++ b/app/system/Bakery/Bakery.php @@ -96,15 +96,17 @@ protected function loadCommands() // Add commands to the App foreach ($commandResources as $commandResource) { - // Translate the resource to a class - $command = $this->getResourceClass($commandResource); + // Translate the resource to a class. Skip if class not found + if (!$command = $this->getResourceClass($commandResource)) { + continue; + } // Get command instance $instance = new $command(); // Class must be an instance of symfony command if (!$instance instanceof Command) { - throw new \Exception("Bakery `$command` must be an instance of `" . Command::class . "`"); + continue; } // Add command to the Console app @@ -134,7 +136,7 @@ protected function getResourceClass(Resource $file) // Make sure class exist if (!class_exists($classPath)) { - throw new \Exception("Bakery command found in `{$file->getAbsolutePath()}`, but class `$classPath` doesn't exist. Make sure the class has the correct namespace."); + return false; } return $classPath; From 5c2ab8cc6b17eb54a627ab57e0fa323d44d79f03 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 8 Jan 2019 20:58:03 -0500 Subject: [PATCH 171/237] Make sure Vagrant uses the latest Node LTS version. --- CHANGELOG.md | 8 +++++--- vagrant/after.sh | 7 ++++++- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ee81f07b..86b9a455f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## [Unreleased] +## 4.2.0 + +### Changed Requirements +- Changed minimum Node.js version to **v10.12.0** +- Changed minimum NPM version to **6.0.0** ### Added - Use locale requested by browser when possible for guests ([#718]) @@ -70,8 +74,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Removed Bakery `projectRoot` property. Use the `\UserFrosting\ROOT_DIR` constant instead - Removed `pretend` option from Bakery `migrate:refresh` and `migrate:reset` commands -### Security - ## v4.1.22 - Updated Docker `README.md`. diff --git a/vagrant/after.sh b/vagrant/after.sh index b5d0ace42..c23242070 100644 --- a/vagrant/after.sh +++ b/vagrant/after.sh @@ -2,6 +2,11 @@ BASE_PATH="/home/vagrant/userfrosting" +# Update nodejs +sudo npm cache clean -f +sudo npm install -g n +sudo n -q lts + # Ensure composer deps are installed cd ${BASE_PATH} composer install @@ -27,4 +32,4 @@ php bakery migrate php bakery create-admin --username="admin" --email="admin@userfrosting.test" --password="adminadmin12" --firstName="Admin" --lastName="istrator" php bakery build-assets -echo "\n\nUserFrosting is ready at http://192.168.10.10/" \ No newline at end of file +echo "\n\nUserFrosting is ready at http://192.168.10.10/" From 6c212231293afd0ab1bd99773bf06885c9539d37 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 8 Jan 2019 22:25:43 -0500 Subject: [PATCH 172/237] Lock Homestead version because master is unpredictable --- vagrant/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vagrant/README.md b/vagrant/README.md index fb4f6ec75..883333b0b 100644 --- a/vagrant/README.md +++ b/vagrant/README.md @@ -12,7 +12,7 @@ UserFrosting uses the [Laravel/Homestead](https://laravel.com/docs/5.6/homestead * Clone Homestead from the root of your cloned fork of the UserFrosting Git repository ```sh -git clone https://github.com/laravel/homestead.git vagrant/Homestead +git clone -b v7.20.0 https://github.com/laravel/homestead.git vagrant/Homestead ``` * Run `vagrant up` from the root of your cloned fork of the UserFrosting Git repository @@ -127,4 +127,4 @@ $ mysql -uhomestead -psecret UserFrosting < /home/vagrant/userfrosting/userfrost - Username: homestead - Password: secret - Database: UserFrosting -- Port: 5432 \ No newline at end of file +- Port: 5432 From 2b9714196d71c64ee6fc53edeb778a66cec4fed6 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Thu, 10 Jan 2019 07:38:56 +1100 Subject: [PATCH 173/237] Support for running directly with gulp for assets install task --- build/gulpfile.js | 11 ++++++----- build/package.json | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/build/gulpfile.js b/build/gulpfile.js index 7cbe73c1a..2ee31eb16 100755 --- a/build/gulpfile.js +++ b/build/gulpfile.js @@ -6,7 +6,7 @@ const { default: Bundler, ValidateRawConfig, MergeRawConfigs } = require("@userf const { default: minifyJs } = require("gulp-uglify-es"); const { execSync } = require("child_process"); const { readFileSync, existsSync, writeFileSync } = require("fs"); -const { resolve: resolvePath } = require("path"); +const { resolve: resolvePath, normalize: normalisePath } = require("path"); const { src, dest, series } = require("gulp"); const { sync: deleteSync } = require("del"); const concatCss = require("gulp-concat-css"); @@ -43,6 +43,7 @@ const publicAssetsDir = rootDir + "public/assets/"; const legacyVendorAssetsGlob = rootDir + "sprinkles/*/assets/vendor/**"; const sprinkleBundleFile = "asset-bundles.json"; const vendorAssetsDir = rootDir + "app/assets/"; +const buildDirFromVendorAssetsDir = "../../build/"; // Load sprinkles let sprinkles; @@ -88,14 +89,14 @@ async function assetsInstall() { // Perform installation // NPM will automatically remove extraneous packages (barring algorithm failure) during install - Logger("Running npm install"); + Logger("Running npm install (using npm from PATH)"); execSync("npm install", { cwd: vendorAssetsDir, stdio: doILog ? "inherit" : "" }); // Conduct audit - Logger("Running npm audit"); + Logger("Running npm audit (using npm from PATH)"); try { execSync("npm audit", { cwd: vendorAssetsDir, @@ -107,7 +108,7 @@ async function assetsInstall() { } // Browserify dependencies - Logger("Running browserify against npm dependencies with a main entrypoint"); + Logger("Running browserify against npm dependencies with a compatible main entrypoint"); deleteSync(vendorAssetsDir + "browser_modules/", { force: true }); await browserifyDependencies({ dependencies: Object.keys(pkg.dependencies), @@ -155,7 +156,7 @@ async function assetsInstall() { // Perform installation Logger("Running bower install -q --allow-root"); // --allow-root stops bower from complaining about being in 'sudo' in various situations - execSync("bower install -q --allow-root", { + execSync(normalisePath(buildDirFromVendorAssetsDir + "node_modules/.bin/bower") + " install -q --allow-root", { cwd: vendorAssetsDir, stdio: doILog ? "inherit" : "" }); diff --git a/build/package.json b/build/package.json index b659e1bdd..3c8641521 100755 --- a/build/package.json +++ b/build/package.json @@ -1,8 +1,8 @@ { "private": true, "dependencies": { - "@userfrosting/browserify-dependencies": "^1.0.0-alpha.3", - "@userfrosting/gulp-bundle-assets": "^3.0.0-beta.1", + "@userfrosting/browserify-dependencies": "^1.0.0-beta.1", + "@userfrosting/gulp-bundle-assets": "^3.0.0-rc.1", "@userfrosting/merge-package-dependencies": "^1.2.1", "bower": "^1.8.4", "del": "^3.0.0", From 5d644e4eedba2f9a374b94a1777bf07c8b070fe9 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Thu, 10 Jan 2019 07:59:21 +1100 Subject: [PATCH 174/237] Use es modules in gulpfile --- build/{gulpfile.js => gulpfile.esm.js} | 61 ++++++++++++-------------- build/package.json | 1 + 2 files changed, 28 insertions(+), 34 deletions(-) rename build/{gulpfile.js => gulpfile.esm.js} (88%) mode change 100755 => 100644 diff --git a/build/gulpfile.js b/build/gulpfile.esm.js old mode 100755 new mode 100644 similarity index 88% rename from build/gulpfile.js rename to build/gulpfile.esm.js index 2ee31eb16..540688911 --- a/build/gulpfile.js +++ b/build/gulpfile.esm.js @@ -1,20 +1,19 @@ -"use strict"; -const { bower: mergeBowerDeps, npm: mergeNpmDeps } = require("@userfrosting/merge-package-dependencies"); -const { config: envConfig } = require("dotenv"); -const { default: browserifyDependencies } = require("@userfrosting/browserify-dependencies"); -const { default: Bundler, ValidateRawConfig, MergeRawConfigs } = require("@userfrosting/gulp-bundle-assets"); -const { default: minifyJs } = require("gulp-uglify-es"); -const { execSync } = require("child_process"); -const { readFileSync, existsSync, writeFileSync } = require("fs"); -const { resolve: resolvePath, normalize: normalisePath } = require("path"); -const { src, dest, series } = require("gulp"); -const { sync: deleteSync } = require("del"); -const concatCss = require("gulp-concat-css"); -const concatJs = require("gulp-concat"); -const log = require("gulplog"); -const minifyCss = require("gulp-clean-css"); -const prune = require("gulp-prune"); -const rev = require("gulp-rev"); +import browserifyDependencies from "@userfrosting/browserify-dependencies"; +import Bundler, { MergeRawConfigs, ValidateRawConfig } from "@userfrosting/gulp-bundle-assets"; +import { bower as mergeBowerDeps, npm as mergeNpmDeps } from "@userfrosting/merge-package-dependencies"; +import { execSync } from "child_process"; +import { sync as deleteSync } from "del"; +import { config as envConfig } from "dotenv"; +import { existsSync, readFileSync, writeFileSync } from "fs"; +import gulp from "gulp"; +import minifyCss from "gulp-clean-css"; +import concatJs from "gulp-concat"; +import concatCss from "gulp-concat-css"; +import prune from "gulp-prune"; +import rev from "gulp-rev"; +import minifyJs from "gulp-uglify-es"; +import { info } from "gulplog"; +import { normalize as normalisePath, resolve as resolvePath } from "path"; // Load environment variables envConfig({ path: "../app/.env" }); @@ -29,9 +28,9 @@ const doILog = (process.env.UF_MODE === "dev"); function Logger(message, source) { if (doILog) { if (source) - log.info(`${source}: ${message}`); + info(`${source}: ${message}`); else - log.info(message); + info(message); } } @@ -58,7 +57,7 @@ catch (error) { /** * Installs vendor assets. Mapped to npm script "uf-assets-install". */ -async function assetsInstall() { +export async function assetsInstall() { // Clean up any legacy assets if (deleteSync(legacyVendorAssetsGlob, { force: true })) Logger("Legacy frontend vendor assets were deleted. Frontend vendor assets are now installed to 'app/assets'."); @@ -181,7 +180,7 @@ async function assetsInstall() { /** * Compiles frontend assets. Mapped to npm script "uf-bundle". */ -function bundle() { +export function bundle() { // Build sources list const sources = []; for (const sprinkle of sprinkles) { @@ -308,7 +307,7 @@ function bundle() { // Write file Logger("Writing results file..."); writeFileSync("./bundle.result.json", JSON.stringify(resultsObject)); - Logger("Done.") + Logger("Finished writing results file.") }; // Logger adapter @@ -322,30 +321,30 @@ function bundle() { // Open stream Logger("Starting bundle process proper..."); - return src(sources, { sourcemaps: true }) + return gulp.src(sources, { sourcemaps: true }) .pipe(new Bundler(rawConfig, bundleBuilder, bundleResults)) .pipe(prune(publicAssetsDir)) - .pipe(dest(publicAssetsDir, { sourcemaps: "." })); + .pipe(gulp.dest(publicAssetsDir, { sourcemaps: "." })); }; /** * Run all frontend tasks. */ -const frontend = series(assetsInstall, bundle); +export const frontend = gulp.series(assetsInstall, bundle); /** * Clean vendor and public asset folders. * @param {() => {}} done Used to mark task completion. */ -function clean(done) { +export function clean(done) { try { Logger("Cleaning vendor assets..."); deleteSync(vendorAssetsDir, { force: true }); - Logger("Done."); + Logger("Finished cleaning vendor assets."); Logger("Cleaning public assets..."); deleteSync(publicAssetsDir, { force: true }) - Logger("Done."); + Logger("Finsihed cleaning public assets."); done(); } @@ -353,9 +352,3 @@ function clean(done) { done(error); } }; - -// Export public tasks -exports.frontend = frontend; -exports.assetsInstall = assetsInstall; -exports.bundle = bundle; -exports.clean = clean; diff --git a/build/package.json b/build/package.json index 3c8641521..be8c8340f 100755 --- a/build/package.json +++ b/build/package.json @@ -5,6 +5,7 @@ "@userfrosting/gulp-bundle-assets": "^3.0.0-rc.1", "@userfrosting/merge-package-dependencies": "^1.2.1", "bower": "^1.8.4", + "esm": "^3.0.84", "del": "^3.0.0", "dotenv": "^6.2.0", "gulp": "^4.0.0", From ba280be044529664308abe6a3be2e6b8e19fc5a1 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 9 Jan 2019 20:27:41 -0500 Subject: [PATCH 175/237] Fix test with wrong namespace --- .../account/tests/Unit/HasherTest.php | 2 +- .../account/tests/Unit/PDOStorageTest.php | 2 +- .../account/tests/Unit/RegistrationTest.php | 2 +- .../tests/Integration/AdminControllerTest.php | 2 +- .../admin/tests/Integration/SprunjeTests.php | 2 +- .../Integration/BakeryMigrateCommandTest.php | 2 +- .../BakeryMigrateRefreshCommandTest.php | 2 +- .../BakeryMigrateResetCommandTest.php | 2 +- .../BakeryMigrateRollbackCommandTest.php | 2 +- .../BakeryMigrateStatusCommandTest.php | 2 +- .../Integration/CheckEnvironmentTest.php | 2 +- .../DatabaseMigratorIntegrationTest.php | 2 +- .../DatabaseMigratorServiceTest.php | 2 +- .../Integration/DatabaseMigratorTest.php | 2 +- .../core/tests/Integration/DatabaseTests.php | 44 +++++++++---------- .../MigrationDependencyAnalyserTest.php | 2 +- .../Integration/MigrationLocatorTest.php | 2 +- .../Integration/MigrationRepositoryTest.php | 2 +- .../tests/Unit/BelongsToManyThroughTest.php | 2 +- app/sprinkles/core/tests/Unit/RouterTest.php | 2 +- 20 files changed, 41 insertions(+), 41 deletions(-) diff --git a/app/sprinkles/account/tests/Unit/HasherTest.php b/app/sprinkles/account/tests/Unit/HasherTest.php index 57a444d93..cbd76dcf0 100644 --- a/app/sprinkles/account/tests/Unit/HasherTest.php +++ b/app/sprinkles/account/tests/Unit/HasherTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Unit; +namespace UserFrosting\Sprinkle\Account\Tests\Unit; use UserFrosting\Sprinkle\Account\Authenticate\Hasher; use UserFrosting\Tests\TestCase; diff --git a/app/sprinkles/account/tests/Unit/PDOStorageTest.php b/app/sprinkles/account/tests/Unit/PDOStorageTest.php index be65bfc3f..37f0a545c 100644 --- a/app/sprinkles/account/tests/Unit/PDOStorageTest.php +++ b/app/sprinkles/account/tests/Unit/PDOStorageTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Unit; +namespace UserFrosting\Sprinkle\Account\Tests\Unit; use Birke\Rememberme\Storage\StorageInterface; use Carbon\Carbon; diff --git a/app/sprinkles/account/tests/Unit/RegistrationTest.php b/app/sprinkles/account/tests/Unit/RegistrationTest.php index ff892a42a..571f73a81 100644 --- a/app/sprinkles/account/tests/Unit/RegistrationTest.php +++ b/app/sprinkles/account/tests/Unit/RegistrationTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Unit; +namespace UserFrosting\Sprinkle\Account\Tests\Unit; use Mockery as m; use UserFrosting\Tests\TestCase; diff --git a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php index 493c713c2..dd4429fb3 100644 --- a/app/sprinkles/admin/tests/Integration/AdminControllerTest.php +++ b/app/sprinkles/admin/tests/Integration/AdminControllerTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Sprinkle\Admin\Tests; +namespace UserFrosting\Sprinkle\Admin\Tests\Integration; use UserFrosting\Sprinkle\Account\Tests\withTestUser; use UserFrosting\Sprinkle\Admin\Controller\AdminController; diff --git a/app/sprinkles/admin/tests/Integration/SprunjeTests.php b/app/sprinkles/admin/tests/Integration/SprunjeTests.php index 9be401045..4b14ea8f4 100644 --- a/app/sprinkles/admin/tests/Integration/SprunjeTests.php +++ b/app/sprinkles/admin/tests/Integration/SprunjeTests.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Admin\Tests\Integration; use UserFrosting\Sprinkle\Admin\Sprunje\UserPermissionSprunje; use UserFrosting\Sprinkle\Core\Util\ClassMapper; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php index f86aa1d42..1ead982fa 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use Mockery as m; use Symfony\Component\Console\Application; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php index da8145b0b..27cbbcc3e 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use Mockery as m; use Symfony\Component\Console\Application; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php index c0e482ce5..a6cd43a74 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use Mockery as m; use Symfony\Component\Console\Application; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php index 23b509c4b..3cda59e2b 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use Mockery as m; use Symfony\Component\Console\Application; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php index 65b385d81..50e986fe4 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use Mockery as m; use Symfony\Component\Console\Application; diff --git a/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php b/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php index 8eee73458..cf8c67b72 100644 --- a/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php +++ b/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use UserFrosting\Sprinkle\Core\Util\CheckEnvironment; use UserFrosting\Tests\TestCase; diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php index 6a439a7c7..b87c2db16 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use UserFrosting\Sprinkle\Core\Database\Migrator\DatabaseMigrationRepository; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationLocator; diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php index 3ee710b29..41b739618 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use UserFrosting\Sprinkle\Core\Tests\TestDatabase; use UserFrosting\Tests\TestCase; diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php index ce2f14533..a0a9c4003 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use Mockery as m; use Illuminate\Database\Capsule\Manager as Capsule; diff --git a/app/sprinkles/core/tests/Integration/DatabaseTests.php b/app/sprinkles/core/tests/Integration/DatabaseTests.php index 6f4752cc8..496549628 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseTests.php +++ b/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use UserFrosting\Tests\TestCase; use Illuminate\Database\Eloquent\Relations\Relation; @@ -148,8 +148,8 @@ public function testOneToManyRelationship() $this->assertInstanceOf('Illuminate\Database\Eloquent\Collection', $emails); $this->assertEquals(2, $emails->count()); - $this->assertInstanceOf('UserFrosting\Tests\Integration\EloquentTestEmail', $emails[0]); - $this->assertInstanceOf('UserFrosting\Tests\Integration\EloquentTestEmail', $emails[1]); + $this->assertInstanceOf(EloquentTestEmail::class, $emails[0]); + $this->assertInstanceOf(EloquentTestEmail::class, $emails[1]); } /** @@ -236,14 +236,14 @@ public function testSyncMorphMany() [ 'id' => 1, 'phoneable_id' => 1, - 'phoneable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser', + 'phoneable_type' => EloquentTestUser::class, 'label' => 'primary', 'number' => '8883332222' ], [ 'id' => 3, 'phoneable_id' => 1, - 'phoneable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser', + 'phoneable_type' => EloquentTestUser::class, 'label' => 'fax', 'number' => '5550005555' ] @@ -1059,19 +1059,19 @@ protected function generateAssignments() 'task_id' => 2, 'location_id' => 1, 'assignable_id' => 1, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' + 'assignable_type' => EloquentTestUser::class ]), EloquentTestAssignment::create([ 'task_id' => 2, 'location_id' => 2, 'assignable_id' => 1, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' + 'assignable_type' => EloquentTestUser::class ]), EloquentTestAssignment::create([ 'task_id' => 3, 'location_id' => 2, 'assignable_id' => 1, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' + 'assignable_type' => EloquentTestUser::class ]), EloquentTestAssignment::create([ 'task_id' => 3, @@ -1083,7 +1083,7 @@ protected function generateAssignments() 'task_id' => 3, 'location_id' => 1, 'assignable_id' => 2, - 'assignable_type' => 'UserFrosting\Tests\Integration\EloquentTestUser' + 'assignable_type' => EloquentTestUser::class ]) ]; } @@ -1206,12 +1206,12 @@ class EloquentTestUser extends EloquentTestModel public function emails() { - return $this->hasMany('UserFrosting\Tests\Integration\EloquentTestEmail', 'user_id'); + return $this->hasMany(EloquentTestEmail::class, 'user_id'); } public function phones() { - return $this->morphMany('UserFrosting\Tests\Integration\EloquentTestPhone', 'phoneable'); + return $this->morphMany(EloquentTestPhone::class, 'phoneable'); } /** @@ -1221,7 +1221,7 @@ public function phones() */ public function roles() { - return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestRole', 'role_users', 'user_id', 'role_id'); + return $this->belongsToMany(EloquentTestRole::class, 'role_users', 'user_id', 'role_id'); } /** @@ -1232,8 +1232,8 @@ public function roles() public function permissions() { return $this->belongsToManyThrough( - 'UserFrosting\Tests\Integration\EloquentTestPermission', - 'UserFrosting\Tests\Integration\EloquentTestRole', + EloquentTestPermission::class, + EloquentTestRole::class, 'role_users', 'user_id', 'role_id', @@ -1249,7 +1249,7 @@ public function permissions() public function assignmentTasks() { $relation = $this->morphToManyUnique( - 'UserFrosting\Tests\Integration\EloquentTestTask', + EloquentTestTask::class, 'assignable', 'assignments', null, @@ -1265,7 +1265,7 @@ public function assignmentTasks() public function tasks() { $relation = $this->morphToManyUnique( - 'UserFrosting\Tests\Integration\EloquentTestTask', + EloquentTestTask::class, 'assignable', 'assignments', null, @@ -1281,7 +1281,7 @@ public function tasks() public function jobRoles() { $relation = $this->belongsToManyUnique( - 'UserFrosting\Tests\Integration\EloquentTestRole', + EloquentTestRole::class, 'jobs', 'user_id', 'role_id' @@ -1313,7 +1313,7 @@ class EloquentTestEmail extends EloquentTestModel public function user() { - return $this->belongsTo('UserFrosting\Tests\Integration\EloquentTestUser', 'user_id'); + return $this->belongsTo(EloquentTestUser::class, 'user_id'); } } @@ -1338,7 +1338,7 @@ class EloquentTestRole extends EloquentTestModel */ public function permissions() { - return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestPermission', 'permission_roles', 'role_id', 'permission_id'); + return $this->belongsToMany(EloquentTestPermission::class, 'permission_roles', 'role_id', 'permission_id'); } } @@ -1352,7 +1352,7 @@ class EloquentTestPermission extends EloquentTestModel */ public function roles() { - return $this->belongsToMany('UserFrosting\Tests\Integration\EloquentTestRole', 'permission_roles', 'permission_id', 'role_id'); + return $this->belongsToMany(EloquentTestRole::class, 'permission_roles', 'permission_id', 'role_id'); } } @@ -1388,7 +1388,7 @@ class EloquentTestAssignment extends EloquentTestModel */ public function users() { - return $this->morphedByMany('UserFrosting\Tests\Integration\EloquentTestUser', 'assignable'); + return $this->morphedByMany(EloquentTestUser::class, 'assignable'); } } @@ -1402,6 +1402,6 @@ class EloquentTestJob extends EloquentTestModel */ public function role() { - return $this->belongsTo('UserFrosting\Tests\Integration\EloquentTestRole', 'role_id'); + return $this->belongsTo(EloquentTestRole::class, 'role_id'); } } diff --git a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php index 51c3e7e82..ca2ed2904 100644 --- a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use UserFrosting\Sprinkle\Core\Database\Migrator\MigrationDependencyAnalyser; use UserFrosting\Sprinkle\Core\Util\BadClassNameException; diff --git a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php index dfaeefb57..2cfa9ccaa 100644 --- a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use Mockery as m; use UserFrosting\Tests\TestCase; diff --git a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php index 5c5c1183f..576503b3d 100644 --- a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Integration; +namespace UserFrosting\Sprinkle\Core\Tests\Integration; use Mockery as m; use Illuminate\Support\Collection; diff --git a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php index 97bc6a80d..837cb2958 100644 --- a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php +++ b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Unit; +namespace UserFrosting\Sprinkle\Core\Tests\Unit; use Illuminate\Database\Eloquent\Builder as EloquentBuilder; use Illuminate\Database\Eloquent\Relations\BelongsToMany; diff --git a/app/sprinkles/core/tests/Unit/RouterTest.php b/app/sprinkles/core/tests/Unit/RouterTest.php index cd90c9fa9..a55c99a01 100644 --- a/app/sprinkles/core/tests/Unit/RouterTest.php +++ b/app/sprinkles/core/tests/Unit/RouterTest.php @@ -6,7 +6,7 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) */ -namespace UserFrosting\Tests\Unit; +namespace UserFrosting\Sprinkle\Core\Tests\Unit; use UserFrosting\Tests\TestCase; From 6e69897026e90c3dbcaee2ea81271477da6eebd6 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 9 Jan 2019 20:35:07 -0500 Subject: [PATCH 176/237] Sudo wasn't necessary here --- vagrant/after.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vagrant/after.sh b/vagrant/after.sh index c23242070..4be3d9800 100644 --- a/vagrant/after.sh +++ b/vagrant/after.sh @@ -3,9 +3,9 @@ BASE_PATH="/home/vagrant/userfrosting" # Update nodejs -sudo npm cache clean -f -sudo npm install -g n -sudo n -q lts +npm cache clean -f +npm install -g n +n -q lts # Ensure composer deps are installed cd ${BASE_PATH} From 9c7897bcd23a07742e4938d6f0ef60655161feb2 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 9 Jan 2019 20:57:43 -0500 Subject: [PATCH 177/237] Extended `bakery test` to add Test Scope and sprinkle selection argument (Thanks @ssnukala !) --- CHANGELOG.md | 1 + app/sprinkles/core/src/Bakery/Test.php | 20 ++++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86b9a455f..e0c73cb80 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `test:mail` Bakery Command - Add support for other config['mailer'] options ([#872]; Thanks @apple314159 !) - Added support for npm dependencies on the frontend with auditting for known vulnerabilities +- Extended `bakery test` to add Test Scope and sprinkle selection argument (Thanks @ssnukala !) ### Changed - Moved Bakery commands from `app/System/Bakery` to the `Core` sprinkle and `UserFrosting\Sprinkle\Core\Bakery` namespace. diff --git a/app/sprinkles/core/src/Bakery/Test.php b/app/sprinkles/core/src/Bakery/Test.php index 3b4a32d4a..b4163fd8e 100644 --- a/app/sprinkles/core/src/Bakery/Test.php +++ b/app/sprinkles/core/src/Bakery/Test.php @@ -8,9 +8,11 @@ namespace UserFrosting\Sprinkle\Core\Bakery; +use Illuminate\Support\Str; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Input\InputArgument; use UserFrosting\System\Bakery\BaseCommand; /** @@ -33,8 +35,9 @@ protected function configure() { $this->setName('test') ->addOption('coverage', 'c', InputOption::VALUE_NONE, 'Generate code coverage report in HTML format. Will be saved in _meta/coverage') - ->setDescription('Run tests') - ->setHelp('Run php unit tests'); + ->addArgument('testscope', InputArgument::OPTIONAL, "Test Scope can either be a sprinkle name or a class formated as 'SprinkleName\Tests\TestClass` or 'SprinkleName\Tests\TestClass::method` (Optional)") + ->setDescription('Runs automated tests') + ->setHelp("Run PHP unit tests. Tests from a specific sprinkle can optionally be run using the 'testscope' argument (`php bakery test SprinkleName`). A specific test class can also be be run using the testscope argument (`php bakery test 'SprinkleName\Tests\TestClass'`), as a specific test method (`php bakery test 'SprinkleName\Tests\TestClass::method'`)."); } /** @@ -50,6 +53,19 @@ protected function execute(InputInterface $input, OutputInterface $output) $command .= ' -v'; } + $testscope = $input->getArgument('testscope'); + if ($testscope) { + $slashes = '\\\\'; + if (strpos($testscope, '\\') !== false) { + $this->io->note("Executing Specified Test Scope : $testscope"); + $testscope = str_replace('\\', $slashes, $testscope); + $command .= " --filter='UserFrosting" . $slashes . 'Sprinkle' . $slashes . $testscope . "'"; + } else { + $this->io->note("Executing all tests in Sprinkle '".Str::studly($testscope)."'"); + $command .= " --filter='UserFrosting" . $slashes . 'Sprinkle' . $slashes . Str::studly($testscope) . $slashes . 'Tests' . $slashes . "' "; + } + } + // Add coverage report if ($input->getOption('coverage')) { $command .= ' --coverage-html _meta/coverage'; From d146289b84fb6ae2ea31801bd7592c87c6dbec23 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 9 Jan 2019 21:27:17 -0500 Subject: [PATCH 178/237] Adds php 7.3 test suite to Travis --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 8a760b11b..564011d4c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,6 +11,7 @@ php: - 7 - 7.1 - 7.2 + - 7.3 env: matrix: From 54c9cd2aa724c9e99a2c7e5a4726701acd8fe9c9 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 9 Jan 2019 22:35:27 -0500 Subject: [PATCH 179/237] Updated dependencies --- CHANGELOG.md | 3 ++- app/sprinkles/core/composer.json | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0c73cb80..713df9e44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,7 +36,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `test:mail` Bakery Command - Add support for other config['mailer'] options ([#872]; Thanks @apple314159 !) - Added support for npm dependencies on the frontend with auditting for known vulnerabilities -- Extended `bakery test` to add Test Scope and sprinkle selection argument (Thanks @ssnukala !) +- Extended `bakery test` to add Test Scope and sprinkle selection argument ([#919], Thanks @ssnukala !) ### Changed - Moved Bakery commands from `app/System/Bakery` to the `Core` sprinkle and `UserFrosting\Sprinkle\Core\Bakery` namespace. @@ -671,3 +671,4 @@ See [http://learn.userfrosting.com/upgrading/40-to-41](Upgrading 4.0.x to 4.1.x [#869]: https://github.com/userfrosting/UserFrosting/issues/869 [#872]: https://github.com/userfrosting/UserFrosting/issues/872 [#888]: https://github.com/userfrosting/UserFrosting/issues/888 +[#919]: https://github.com/userfrosting/UserFrosting/issues/919 diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index c6542f5d9..5421c9f37 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -45,12 +45,12 @@ "slim/twig-view": "^1.2", "symfony/http-foundation": "*", "twig/twig": "^1.18", - "userfrosting/assets": "dev-feature-locator", - "userfrosting/config": "dev-feature-locator", + "userfrosting/assets": "~4.2.0", + "userfrosting/config": "~4.2.0", "userfrosting/cache": "~4.1.0", "userfrosting/fortress": "~4.1.1", "userfrosting/i18n": "~4.1.0", - "userfrosting/uniformresourcelocator": "dev-develop", + "userfrosting/uniformresourcelocator": "~4.2.0", "userfrosting/session": "~4.1.0", "userfrosting/support": "~4.1.1", "vlucas/phpdotenv": "^2" From 9073989b213025cb66abb2363a6b631c45d948d0 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Wed, 9 Jan 2019 22:35:54 -0500 Subject: [PATCH 180/237] Prep 4.2.0-beta.1 release \o/ --- app/defines.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/defines.php b/app/defines.php index 06b03c25b..ef2a82f82 100755 --- a/app/defines.php +++ b/app/defines.php @@ -9,7 +9,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.2.0-alpha.2'); +define('UserFrosting\VERSION', '4.2.0-beta.1'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\PHP_RECOMMENDED_VERSION', '7.1'); From fa7621f37f60f1fc624b7d61750404599e485fce Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 10 Jan 2019 21:45:37 -0500 Subject: [PATCH 181/237] Added Codecoverage config --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 564011d4c..10e77e30d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,10 @@ before_script: script: # run unit tests - - app/vendor/bin/phpunit + - app/vendor/bin/phpunit --coverage-clover=coverage.xml + +after_success: + - bash <(curl -s https://codecov.io/bash) after_failure: - cat app/log/userfrosting.log From 7a71f071f9a5b0898b9580a41cb76d0aad3977ca Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Thu, 10 Jan 2019 21:49:21 -0500 Subject: [PATCH 182/237] Update Readme --- README.md | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 119783838..03e818dc3 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ -# UserFrosting 4.1 - -[https://www.userfrosting.com](https://www.userfrosting.com) +# UserFrosting 4.2 +[![Latest Version](https://img.shields.io/github/release/userfrosting/UserFrosting.svg)](https://github.com/userfrosting/UserFrosting/releases) +[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE.md) [![Build Status](https://travis-ci.org/userfrosting/UserFrosting.svg?branch=master)](https://travis-ci.org/userfrosting/UserFrosting) +[![codecov](https://codecov.io/gh/userfrosting/userfrosting/branch/master/graph/badge.svg)](https://codecov.io/gh/userfrosting/userfrosting) [![Join the chat at https://chat.userfrosting.com/channel/support](https://demo.rocket.chat/images/join-chat.svg)](https://chat.userfrosting.com/channel/support) -[![Backers on Open Collective](https://opencollective.com/userfrosting/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/userfrosting/sponsors/badge.svg)](#sponsors) +[![Backers on Open Collective](https://opencollective.com/userfrosting/backers/badge.svg)](#backers) +[![Sponsors on Open Collective](https://opencollective.com/userfrosting/sponsors/badge.svg)](#sponsors) +[![Donate](https://img.shields.io/badge/Open%20Collective-Donate-blue.svg)](https://opencollective.com/userfrosting#backer) - - - +[https://www.userfrosting.com](https://www.userfrosting.com) If you simply want to show that you like this project, or want to remember it for later, you should **star**, not **fork**, this repository. Forking is only for when you are ready to create your own copy of the code to work on. From 91dcf41735c88795002e9f0393003a4ccd69c7a1 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Fri, 11 Jan 2019 19:54:27 -0500 Subject: [PATCH 183/237] Update License & Copyright --- .php_cs | 3 ++- LICENSE.md | 2 +- README.md | 2 +- STYLE-GUIDE.md | 3 ++- app/defines.php | 3 ++- app/sprinkles/account/config/debug.php | 3 ++- app/sprinkles/account/config/default.php | 3 ++- app/sprinkles/account/config/production.php | 3 ++- app/sprinkles/account/factories/Permissions.php | 4 +++- app/sprinkles/account/factories/Roles.php | 4 +++- app/sprinkles/account/factories/Users.php | 4 +++- app/sprinkles/account/locale/ar/messages.php | 3 ++- app/sprinkles/account/locale/ar/validate.php | 3 ++- app/sprinkles/account/locale/de_DE/messages.php | 3 ++- app/sprinkles/account/locale/de_DE/validate.php | 3 ++- app/sprinkles/account/locale/en_US/messages.php | 3 ++- app/sprinkles/account/locale/en_US/validate.php | 3 ++- app/sprinkles/account/locale/es_ES/messages.php | 3 ++- app/sprinkles/account/locale/es_ES/validate.php | 3 ++- app/sprinkles/account/locale/fa/messages.php | 4 ++-- app/sprinkles/account/locale/fa/validate.php | 4 ++-- app/sprinkles/account/locale/fr_FR/messages.php | 3 ++- app/sprinkles/account/locale/fr_FR/validate.php | 3 ++- app/sprinkles/account/locale/it_IT/messages.php | 3 ++- app/sprinkles/account/locale/it_IT/validate.php | 3 ++- app/sprinkles/account/locale/pt_PT/messages.php | 3 ++- app/sprinkles/account/locale/pt_PT/validate.php | 3 ++- app/sprinkles/account/locale/ru_RU/messages.php | 3 ++- app/sprinkles/account/locale/ru_RU/validate.php | 3 ++- app/sprinkles/account/locale/th_TH/messages.php | 3 ++- app/sprinkles/account/locale/th_TH/validate.php | 3 ++- app/sprinkles/account/locale/tr/messages.php | 3 ++- app/sprinkles/account/locale/tr/validate.php | 3 ++- app/sprinkles/account/locale/zh_CN/messages.php | 3 ++- app/sprinkles/account/locale/zh_CN/validate.php | 3 ++- app/sprinkles/account/routes/routes.php | 4 +++- app/sprinkles/account/src/Account.php | 3 ++- app/sprinkles/account/src/Account/Registration.php | 3 ++- app/sprinkles/account/src/Authenticate/AuthGuard.php | 3 ++- app/sprinkles/account/src/Authenticate/Authenticator.php | 3 ++- .../src/Authenticate/Exception/AccountDisabledException.php | 3 ++- .../src/Authenticate/Exception/AccountInvalidException.php | 3 ++- .../Authenticate/Exception/AccountNotVerifiedException.php | 3 ++- .../src/Authenticate/Exception/AuthCompromisedException.php | 3 ++- .../src/Authenticate/Exception/AuthExpiredException.php | 3 ++- .../Authenticate/Exception/InvalidCredentialsException.php | 3 ++- app/sprinkles/account/src/Authenticate/Hasher.php | 3 ++- .../account/src/Authorize/AccessConditionExpression.php | 3 ++- .../account/src/Authorize/AuthorizationException.php | 3 ++- app/sprinkles/account/src/Authorize/AuthorizationManager.php | 3 ++- .../account/src/Authorize/ParserNodeFunctionEvaluator.php | 3 ++- app/sprinkles/account/src/Bakery/CreateAdminUser.php | 3 ++- app/sprinkles/account/src/Controller/AccountController.php | 3 ++- .../src/Controller/Exception/SpammyRequestException.php | 3 ++- .../account/src/Database/Migrations/v400/ActivitiesTable.php | 3 ++- .../account/src/Database/Migrations/v400/GroupsTable.php | 3 ++- .../src/Database/Migrations/v400/PasswordResetsTable.php | 3 ++- .../src/Database/Migrations/v400/PermissionRolesTable.php | 3 ++- .../src/Database/Migrations/v400/PermissionsTable.php | 3 ++- .../src/Database/Migrations/v400/PersistencesTable.php | 3 ++- .../account/src/Database/Migrations/v400/RoleUsersTable.php | 3 ++- .../account/src/Database/Migrations/v400/RolesTable.php | 3 ++- .../account/src/Database/Migrations/v400/UsersTable.php | 3 ++- .../src/Database/Migrations/v400/VerificationsTable.php | 3 ++- .../src/Database/Migrations/v420/AddingForeignKeys.php | 3 ++- app/sprinkles/account/src/Database/Models/Activity.php | 3 ++- .../src/Database/Models/Events/DeleteUserCacheEvent.php | 3 ++- app/sprinkles/account/src/Database/Models/Group.php | 3 ++- .../account/src/Database/Models/Interfaces/UserInterface.php | 3 ++- app/sprinkles/account/src/Database/Models/PasswordReset.php | 3 ++- app/sprinkles/account/src/Database/Models/Permission.php | 3 ++- app/sprinkles/account/src/Database/Models/Persistence.php | 3 ++- app/sprinkles/account/src/Database/Models/Role.php | 3 ++- app/sprinkles/account/src/Database/Models/User.php | 3 ++- app/sprinkles/account/src/Database/Models/Verification.php | 3 ++- app/sprinkles/account/src/Database/Seeds/DefaultGroups.php | 3 ++- .../account/src/Database/Seeds/DefaultPermissions.php | 3 ++- app/sprinkles/account/src/Database/Seeds/DefaultRoles.php | 3 ++- .../src/Error/Handler/AuthCompromisedExceptionHandler.php | 3 ++- .../src/Error/Handler/AuthExpiredExceptionHandler.php | 3 ++- .../account/src/Error/Handler/ForbiddenExceptionHandler.php | 3 ++- app/sprinkles/account/src/Facades/Password.php | 3 ++- .../account/src/Log/UserActivityDatabaseHandler.php | 3 ++- app/sprinkles/account/src/Log/UserActivityProcessor.php | 3 ++- app/sprinkles/account/src/Rememberme/PDOStorage.php | 3 ++- .../account/src/Repository/PasswordResetRepository.php | 3 ++- app/sprinkles/account/src/Repository/TokenRepository.php | 3 ++- .../account/src/Repository/VerificationRepository.php | 3 ++- .../account/src/ServicesProvider/ServicesProvider.php | 3 ++- app/sprinkles/account/src/Twig/AccountExtension.php | 3 ++- app/sprinkles/account/src/Util/HashFailedException.php | 3 ++- app/sprinkles/account/src/Util/Util.php | 3 ++- .../account/tests/Integration/AuthenticatorTest.php | 3 ++- .../account/tests/Integration/AuthorizationManagerTest.php | 3 ++- app/sprinkles/account/tests/Unit/FactoriesTest.php | 3 ++- app/sprinkles/account/tests/Unit/HasherTest.php | 3 ++- app/sprinkles/account/tests/Unit/PDOStorageTest.php | 3 ++- app/sprinkles/account/tests/Unit/RegistrationTest.php | 3 ++- app/sprinkles/account/tests/withTestUser.php | 3 ++- app/sprinkles/admin/locale/ar/messages.php | 3 ++- app/sprinkles/admin/locale/de_DE/messages.php | 3 ++- app/sprinkles/admin/locale/en_US/messages.php | 3 ++- app/sprinkles/admin/locale/es_ES/messages.php | 3 ++- app/sprinkles/admin/locale/fa/messages.php | 4 ++-- app/sprinkles/admin/locale/fr_FR/messages.php | 3 ++- app/sprinkles/admin/locale/it_IT/messages.php | 3 ++- app/sprinkles/admin/locale/pt_PT/messages.php | 3 ++- app/sprinkles/admin/locale/ru_RU/messages.php | 3 ++- app/sprinkles/admin/locale/th_TH/messages.php | 3 ++- app/sprinkles/admin/locale/tr/messages.php | 3 ++- app/sprinkles/admin/locale/zh_CN/messages.php | 3 ++- app/sprinkles/admin/routes/activities.php | 3 ++- app/sprinkles/admin/routes/admin.php | 3 ++- app/sprinkles/admin/routes/groups.php | 3 ++- app/sprinkles/admin/routes/permissions.php | 3 ++- app/sprinkles/admin/routes/roles.php | 3 ++- app/sprinkles/admin/routes/users.php | 3 ++- app/sprinkles/admin/src/Admin.php | 3 ++- app/sprinkles/admin/src/Controller/ActivityController.php | 3 ++- app/sprinkles/admin/src/Controller/AdminController.php | 3 ++- app/sprinkles/admin/src/Controller/GroupController.php | 3 ++- app/sprinkles/admin/src/Controller/PermissionController.php | 3 ++- app/sprinkles/admin/src/Controller/RoleController.php | 3 ++- app/sprinkles/admin/src/Controller/UserController.php | 3 ++- .../admin/src/ServicesProvider/ServicesProvider.php | 3 ++- app/sprinkles/admin/src/Sprunje/ActivitySprunje.php | 3 ++- app/sprinkles/admin/src/Sprunje/GroupSprunje.php | 3 ++- app/sprinkles/admin/src/Sprunje/PermissionSprunje.php | 3 ++- app/sprinkles/admin/src/Sprunje/PermissionUserSprunje.php | 3 ++- app/sprinkles/admin/src/Sprunje/RoleSprunje.php | 3 ++- app/sprinkles/admin/src/Sprunje/UserPermissionSprunje.php | 3 ++- app/sprinkles/admin/src/Sprunje/UserSprunje.php | 3 ++- .../admin/tests/Integration/AdminControllerTest.php | 3 ++- app/sprinkles/admin/tests/Integration/SprunjeTests.php | 3 ++- app/sprinkles/core/config/debug.php | 3 ++- app/sprinkles/core/config/default.php | 3 ++- app/sprinkles/core/config/production.php | 3 ++- app/sprinkles/core/config/testing.php | 3 ++- app/sprinkles/core/defines.php | 3 ++- app/sprinkles/core/extra/adjectives.php | 3 ++- app/sprinkles/core/extra/nouns.php | 3 ++- app/sprinkles/core/locale/ar/errors.php | 3 ++- app/sprinkles/core/locale/ar/messages.php | 3 ++- app/sprinkles/core/locale/ar/validate.php | 3 ++- app/sprinkles/core/locale/de_DE/errors.php | 3 ++- app/sprinkles/core/locale/de_DE/messages.php | 3 ++- app/sprinkles/core/locale/de_DE/validate.php | 3 ++- app/sprinkles/core/locale/en_US/errors.php | 3 ++- app/sprinkles/core/locale/en_US/messages.php | 3 ++- app/sprinkles/core/locale/en_US/validate.php | 3 ++- app/sprinkles/core/locale/es_ES/errors.php | 3 ++- app/sprinkles/core/locale/es_ES/messages.php | 3 ++- app/sprinkles/core/locale/es_ES/validate.php | 3 ++- app/sprinkles/core/locale/fa/errors.php | 4 ++-- app/sprinkles/core/locale/fa/messages.php | 4 ++-- app/sprinkles/core/locale/fa/validate.php | 4 ++-- app/sprinkles/core/locale/fr_FR/errors.php | 3 ++- app/sprinkles/core/locale/fr_FR/messages.php | 3 ++- app/sprinkles/core/locale/fr_FR/validate.php | 3 ++- app/sprinkles/core/locale/it_IT/errors.php | 3 ++- app/sprinkles/core/locale/it_IT/messages.php | 3 ++- app/sprinkles/core/locale/it_IT/validate.php | 3 ++- app/sprinkles/core/locale/pt_PT/errors.php | 3 ++- app/sprinkles/core/locale/pt_PT/messages.php | 3 ++- app/sprinkles/core/locale/pt_PT/validate.php | 3 ++- app/sprinkles/core/locale/ru_RU/errors.php | 3 ++- app/sprinkles/core/locale/ru_RU/messages.php | 3 ++- app/sprinkles/core/locale/ru_RU/validate.php | 3 ++- app/sprinkles/core/locale/th_TH/errors.php | 3 ++- app/sprinkles/core/locale/th_TH/messages.php | 3 ++- app/sprinkles/core/locale/th_TH/validate.php | 3 ++- app/sprinkles/core/locale/valitron/ar.php | 3 ++- app/sprinkles/core/locale/valitron/de.php | 3 ++- app/sprinkles/core/locale/valitron/el.php | 3 ++- app/sprinkles/core/locale/valitron/en.php | 3 ++- app/sprinkles/core/locale/valitron/es.php | 3 ++- app/sprinkles/core/locale/valitron/fr.php | 3 ++- app/sprinkles/core/locale/valitron/id.php | 3 ++- app/sprinkles/core/locale/valitron/it.php | 3 ++- app/sprinkles/core/locale/valitron/ja.php | 3 ++- app/sprinkles/core/locale/valitron/lv.php | 3 ++- app/sprinkles/core/locale/valitron/pt-br.php | 3 ++- app/sprinkles/core/locale/valitron/ro.php | 3 ++- app/sprinkles/core/locale/valitron/ru.php | 3 ++- app/sprinkles/core/locale/valitron/th.php | 3 ++- app/sprinkles/core/locale/valitron/zh-cn.php | 3 ++- app/sprinkles/core/locale/valitron/zh-tw.php | 3 ++- app/sprinkles/core/locale/zh_CN/errors.php | 3 ++- app/sprinkles/core/locale/zh_CN/messages.php | 3 ++- app/sprinkles/core/locale/zh_CN/validate.php | 3 ++- app/sprinkles/core/routes/routes.php | 4 +++- app/sprinkles/core/src/Alert/AlertStream.php | 3 ++- app/sprinkles/core/src/Alert/CacheAlertStream.php | 3 ++- app/sprinkles/core/src/Alert/SessionAlertStream.php | 3 ++- app/sprinkles/core/src/Bakery/BakeCommand.php | 3 ++- app/sprinkles/core/src/Bakery/BuildAssets.php | 4 +++- app/sprinkles/core/src/Bakery/ClearCacheCommand.php | 3 ++- app/sprinkles/core/src/Bakery/DebugCommand.php | 3 ++- app/sprinkles/core/src/Bakery/Helper/ConfirmableTrait.php | 3 ++- app/sprinkles/core/src/Bakery/Helper/DatabaseTest.php | 3 ++- app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php | 3 ++- app/sprinkles/core/src/Bakery/MigrateCommand.php | 4 +++- app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php | 3 ++- app/sprinkles/core/src/Bakery/MigrateResetCommand.php | 3 ++- app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php | 5 +++-- app/sprinkles/core/src/Bakery/MigrateStatusCommand.php | 3 ++- app/sprinkles/core/src/Bakery/RouteListCommand.php | 3 ++- app/sprinkles/core/src/Bakery/SeedCommand.php | 3 ++- app/sprinkles/core/src/Bakery/SeedListCommand.php | 3 ++- app/sprinkles/core/src/Bakery/SetupCommand.php | 3 ++- app/sprinkles/core/src/Bakery/SetupDbCommand.php | 3 ++- app/sprinkles/core/src/Bakery/SetupEnvCommand.php | 3 ++- app/sprinkles/core/src/Bakery/SetupSmtpCommand.php | 3 ++- app/sprinkles/core/src/Bakery/Test.php | 3 ++- app/sprinkles/core/src/Bakery/TestMailCommand.php | 3 ++- app/sprinkles/core/src/Controller/CoreController.php | 3 ++- app/sprinkles/core/src/Controller/SimpleController.php | 3 ++- app/sprinkles/core/src/Core.php | 3 ++- app/sprinkles/core/src/Csrf/CsrfProviderInterface.php | 3 ++- app/sprinkles/core/src/Csrf/SlimCsrfProvider.php | 3 ++- app/sprinkles/core/src/Database/Builder.php | 3 ++- app/sprinkles/core/src/Database/DatabaseInvalidException.php | 3 ++- app/sprinkles/core/src/Database/EloquentBuilder.php | 3 ++- app/sprinkles/core/src/Database/Migration.php | 3 ++- app/sprinkles/core/src/Database/MigrationInterface.php | 3 ++- .../core/src/Database/Migrations/v400/SessionsTable.php | 3 ++- .../core/src/Database/Migrations/v400/ThrottlesTable.php | 3 ++- .../src/Database/Migrator/DatabaseMigrationRepository.php | 3 ++- .../src/Database/Migrator/MigrationDependencyAnalyser.php | 3 ++- .../core/src/Database/Migrator/MigrationLocator.php | 5 +++-- .../core/src/Database/Migrator/MigrationLocatorInterface.php | 3 ++- .../src/Database/Migrator/MigrationRepositoryInterface.php | 3 ++- .../Migrator/MigrationRollbackDependencyAnalyser.php | 3 ++- app/sprinkles/core/src/Database/Migrator/Migrator.php | 4 +++- .../core/src/Database/Models/Concerns/HasRelationships.php | 3 ++- app/sprinkles/core/src/Database/Models/Model.php | 3 ++- app/sprinkles/core/src/Database/Models/Throttle.php | 3 ++- .../core/src/Database/Relations/BelongsToManyConstrained.php | 3 ++- .../core/src/Database/Relations/BelongsToManyThrough.php | 3 ++- .../core/src/Database/Relations/BelongsToManyUnique.php | 3 ++- .../core/src/Database/Relations/Concerns/Syncable.php | 3 ++- .../core/src/Database/Relations/Concerns/Unique.php | 3 ++- .../core/src/Database/Relations/HasManySyncable.php | 3 ++- .../core/src/Database/Relations/MorphManySyncable.php | 3 ++- .../core/src/Database/Relations/MorphToManyUnique.php | 3 ++- app/sprinkles/core/src/Database/Seeder/BaseSeed.php | 3 ++- app/sprinkles/core/src/Database/Seeder/SeedInterface.php | 3 ++- app/sprinkles/core/src/Database/Seeder/Seeder.php | 5 +++-- app/sprinkles/core/src/Error/ExceptionHandlerManager.php | 3 ++- app/sprinkles/core/src/Error/Handler/ExceptionHandler.php | 3 ++- .../core/src/Error/Handler/ExceptionHandlerInterface.php | 3 ++- .../core/src/Error/Handler/HttpExceptionHandler.php | 3 ++- .../core/src/Error/Handler/NotFoundExceptionHandler.php | 3 ++- .../core/src/Error/Handler/PhpMailerExceptionHandler.php | 3 ++- app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php | 3 ++- .../core/src/Error/Renderer/ErrorRendererInterface.php | 3 ++- app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php | 3 ++- app/sprinkles/core/src/Error/Renderer/JsonRenderer.php | 3 ++- app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php | 3 ++- app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php | 3 ++- app/sprinkles/core/src/Error/Renderer/XmlRenderer.php | 3 ++- app/sprinkles/core/src/Facades/Cache.php | 3 ++- app/sprinkles/core/src/Facades/Config.php | 3 ++- app/sprinkles/core/src/Facades/Debug.php | 3 ++- app/sprinkles/core/src/Facades/Seeder.php | 3 ++- app/sprinkles/core/src/Facades/Storage.php | 3 ++- app/sprinkles/core/src/Facades/Translator.php | 3 ++- app/sprinkles/core/src/Filesystem/FilesystemManager.php | 3 ++- .../core/src/Http/Concerns/DeterminesContentType.php | 3 ++- app/sprinkles/core/src/Log/DatabaseHandler.php | 3 ++- app/sprinkles/core/src/Log/MixedFormatter.php | 3 ++- app/sprinkles/core/src/Mail/EmailRecipient.php | 3 ++- app/sprinkles/core/src/Mail/MailMessage.php | 3 ++- app/sprinkles/core/src/Mail/Mailer.php | 3 ++- app/sprinkles/core/src/Mail/StaticMailMessage.php | 3 ++- app/sprinkles/core/src/Mail/TwigMailMessage.php | 3 ++- app/sprinkles/core/src/Model/UFModel.php | 3 ++- app/sprinkles/core/src/Router.php | 3 ++- app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 3 ++- app/sprinkles/core/src/Session/NullSessionHandler.php | 3 ++- app/sprinkles/core/src/Sprunje/Sprunje.php | 3 ++- app/sprinkles/core/src/Throttle/ThrottleRule.php | 3 ++- app/sprinkles/core/src/Throttle/Throttler.php | 3 ++- app/sprinkles/core/src/Throttle/ThrottlerException.php | 3 ++- app/sprinkles/core/src/Twig/CacheHelper.php | 3 ++- app/sprinkles/core/src/Twig/CoreExtension.php | 3 ++- app/sprinkles/core/src/Util/BadClassNameException.php | 3 ++- app/sprinkles/core/src/Util/Captcha.php | 3 ++- app/sprinkles/core/src/Util/CheckEnvironment.php | 3 ++- app/sprinkles/core/src/Util/ClassMapper.php | 3 ++- app/sprinkles/core/src/Util/EnvironmentInfo.php | 3 ++- app/sprinkles/core/src/Util/RawAssetBundles.php | 3 ++- app/sprinkles/core/src/Util/ShutdownHandler.php | 3 ++- app/sprinkles/core/src/Util/Util.php | 3 ++- app/sprinkles/core/tests/ControllerTestCase.php | 3 ++- app/sprinkles/core/tests/DatabaseTransactions.php | 3 ++- .../core/tests/Integration/BakeryMigrateCommandTest.php | 3 ++- .../tests/Integration/BakeryMigrateRefreshCommandTest.php | 3 ++- .../core/tests/Integration/BakeryMigrateResetCommandTest.php | 3 ++- .../tests/Integration/BakeryMigrateRollbackCommandTest.php | 3 ++- .../tests/Integration/BakeryMigrateStatusCommandTest.php | 3 ++- .../core/tests/Integration/CheckEnvironmentTest.php | 3 ++- .../tests/Integration/Controllers/CoreControllerTest.php | 3 ++- .../tests/Integration/DatabaseMigratorIntegrationTest.php | 3 ++- .../core/tests/Integration/DatabaseMigratorServiceTest.php | 3 ++- .../core/tests/Integration/DatabaseMigratorTest.php | 3 ++- app/sprinkles/core/tests/Integration/DatabaseTests.php | 3 ++- .../tests/Integration/Error/Handler/ExceptionHandlerTest.php | 3 ++- .../tests/Integration/Error/Renderer/WhoopsRendererTest.php | 3 ++- .../tests/Integration/MigrationDependencyAnalyserTest.php | 3 ++- .../core/tests/Integration/MigrationLocatorTest.php | 3 ++- .../core/tests/Integration/MigrationRepositoryTest.php | 3 ++- .../tests/Integration/Migrations/DeprecatedClassTable.php | 3 ++- .../core/tests/Integration/Migrations/UnfulfillableTable.php | 3 ++- .../Integration/Migrations/one/CreatePasswordResetsTable.php | 3 ++- .../tests/Integration/Migrations/one/CreateUsersTable.php | 3 ++- .../tests/Integration/Migrations/two/CreateFlightsTable.php | 3 ++- app/sprinkles/core/tests/Integration/Seeder/SeederTests.php | 3 ++- app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php | 3 ++- app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed2.php | 3 ++- .../core/tests/Integration/Seeder/Seeds/Test/Seed.php | 3 ++- app/sprinkles/core/tests/RefreshDatabase.php | 3 ++- app/sprinkles/core/tests/TestDatabase.php | 3 ++- app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php | 3 ++- app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php | 3 ++- app/sprinkles/core/tests/Unit/FilesystemTest.php | 3 ++- app/sprinkles/core/tests/Unit/RouterTest.php | 3 ++- app/sprinkles/core/tests/Unit/SprunjeTest.php | 3 ++- app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php | 3 ++- app/system/Bakery/Bakery.php | 3 ++- app/system/Bakery/BaseCommand.php | 3 ++- app/system/Bakery/Migration.php | 3 ++- app/system/Facade.php | 3 ++- app/system/ServicesProvider.php | 3 ++- app/system/SlimAppEvent.php | 3 ++- app/system/Sprinkle/Sprinkle.php | 3 ++- app/system/Sprinkle/SprinkleManager.php | 3 ++- app/system/UserFrosting.php | 3 ++- app/tests/DatabaseTransactions.php | 3 ++- app/tests/TestCase.php | 3 ++- app/tests/Unit/ExampleTest.php | 3 ++- bakery | 5 +++-- public/index.php | 4 ++-- 343 files changed, 696 insertions(+), 354 deletions(-) diff --git a/.php_cs b/.php_cs index e8df3e4ea..1dc05a1a2 100755 --- a/.php_cs +++ b/.php_cs @@ -3,7 +3,8 @@ $header = 'UserFrosting (http://www.userfrosting.com) @link https://github.com/userfrosting/UserFrosting -@license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License)'; +@copyright Copyright (c) 2019 Alexander Weissman +@license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License)'; $rules = [ '@PSR2' => true, diff --git a/LICENSE.md b/LICENSE.md index cf1bc8ed6..8df8d0f52 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,4 +1,4 @@ -Copyright (c) 2018 by Alexander Weissman (https://alexanderweissman.com) +Copyright (c) 2019 by Alexander Weissman (https://alexanderweissman.com) UserFrosting is 100% free and open-source. diff --git a/README.md b/README.md index 03e818dc3..5721acb77 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ If you simply want to show that you like this project, or want to remember it fo ## By [Alex Weissman](https://alexanderweissman.com) -Copyright (c) 2018, free to use in personal and commercial software as per the [license](LICENSE.md). +Copyright (c) 2019, free to use in personal and commercial software as per the [license](LICENSE.md). UserFrosting is a secure, modern user management system written in PHP and built on top of the [Slim Microframework](http://www.slimframework.com/), [Twig](http://twig.sensiolabs.org/) templating engine, and [Eloquent](https://laravel.com/docs/5.4/eloquent#introduction) ORM. diff --git a/STYLE-GUIDE.md b/STYLE-GUIDE.md index 73dcc77fc..ecec2b29a 100644 --- a/STYLE-GUIDE.md +++ b/STYLE-GUIDE.md @@ -16,7 +16,8 @@ In addition: * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ ``` diff --git a/app/defines.php b/app/defines.php index ef2a82f82..350de007b 100755 --- a/app/defines.php +++ b/app/defines.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting; diff --git a/app/sprinkles/account/config/debug.php b/app/sprinkles/account/config/debug.php index 9fae6c047..4b5681902 100644 --- a/app/sprinkles/account/config/debug.php +++ b/app/sprinkles/account/config/debug.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /* diff --git a/app/sprinkles/account/config/default.php b/app/sprinkles/account/config/default.php index 24cc64644..c38b50006 100644 --- a/app/sprinkles/account/config/default.php +++ b/app/sprinkles/account/config/default.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /* diff --git a/app/sprinkles/account/config/production.php b/app/sprinkles/account/config/production.php index d2281feee..b7ce4111f 100644 --- a/app/sprinkles/account/config/production.php +++ b/app/sprinkles/account/config/production.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /* diff --git a/app/sprinkles/account/factories/Permissions.php b/app/sprinkles/account/factories/Permissions.php index 17b666237..be7b9fcf5 100644 --- a/app/sprinkles/account/factories/Permissions.php +++ b/app/sprinkles/account/factories/Permissions.php @@ -3,8 +3,10 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ + use League\FactoryMuffin\Faker\Facade as Faker; /* diff --git a/app/sprinkles/account/factories/Roles.php b/app/sprinkles/account/factories/Roles.php index 84782bf73..34704f3f2 100644 --- a/app/sprinkles/account/factories/Roles.php +++ b/app/sprinkles/account/factories/Roles.php @@ -3,8 +3,10 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ + use League\FactoryMuffin\Faker\Facade as Faker; /* diff --git a/app/sprinkles/account/factories/Users.php b/app/sprinkles/account/factories/Users.php index 652303816..abd34c4fd 100644 --- a/app/sprinkles/account/factories/Users.php +++ b/app/sprinkles/account/factories/Users.php @@ -3,8 +3,10 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ + use League\FactoryMuffin\Faker\Facade as Faker; /* diff --git a/app/sprinkles/account/locale/ar/messages.php b/app/sprinkles/account/locale/ar/messages.php index 5433b488c..5cec36485 100644 --- a/app/sprinkles/account/locale/ar/messages.php +++ b/app/sprinkles/account/locale/ar/messages.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/account/locale/ar/validate.php b/app/sprinkles/account/locale/ar/validate.php index 7b8edc253..5bdb39469 100644 --- a/app/sprinkles/account/locale/ar/validate.php +++ b/app/sprinkles/account/locale/ar/validate.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/account/locale/de_DE/messages.php b/app/sprinkles/account/locale/de_DE/messages.php index 26a23a725..0b2a7b436 100644 --- a/app/sprinkles/account/locale/de_DE/messages.php +++ b/app/sprinkles/account/locale/de_DE/messages.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/account/locale/de_DE/validate.php b/app/sprinkles/account/locale/de_DE/validate.php index 4529f3f1b..c81a7334d 100644 --- a/app/sprinkles/account/locale/de_DE/validate.php +++ b/app/sprinkles/account/locale/de_DE/validate.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/account/locale/en_US/messages.php b/app/sprinkles/account/locale/en_US/messages.php index 501407de3..998856f32 100644 --- a/app/sprinkles/account/locale/en_US/messages.php +++ b/app/sprinkles/account/locale/en_US/messages.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/account/locale/en_US/validate.php b/app/sprinkles/account/locale/en_US/validate.php index 40f8df6aa..d91ef2a9f 100644 --- a/app/sprinkles/account/locale/en_US/validate.php +++ b/app/sprinkles/account/locale/en_US/validate.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/account/locale/es_ES/messages.php b/app/sprinkles/account/locale/es_ES/messages.php index 567c202ca..01503acc8 100755 --- a/app/sprinkles/account/locale/es_ES/messages.php +++ b/app/sprinkles/account/locale/es_ES/messages.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/account/locale/es_ES/validate.php b/app/sprinkles/account/locale/es_ES/validate.php index 11276e212..246034eff 100755 --- a/app/sprinkles/account/locale/es_ES/validate.php +++ b/app/sprinkles/account/locale/es_ES/validate.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/account/locale/fa/messages.php b/app/sprinkles/account/locale/fa/messages.php index adfed759d..0c2d8c789 100644 --- a/app/sprinkles/account/locale/fa/messages.php +++ b/app/sprinkles/account/locale/fa/messages.php @@ -1,10 +1,10 @@ group('/account', function () { $this->get('/captcha', 'UserFrosting\Sprinkle\Account\Controller\AccountController:imageCaptcha'); diff --git a/app/sprinkles/account/src/Account.php b/app/sprinkles/account/src/Account.php index 237790a4e..cfdbd2d38 100644 --- a/app/sprinkles/account/src/Account.php +++ b/app/sprinkles/account/src/Account.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account; diff --git a/app/sprinkles/account/src/Account/Registration.php b/app/sprinkles/account/src/Account/Registration.php index f66e7097e..10cf01102 100644 --- a/app/sprinkles/account/src/Account/Registration.php +++ b/app/sprinkles/account/src/Account/Registration.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Account; diff --git a/app/sprinkles/account/src/Authenticate/AuthGuard.php b/app/sprinkles/account/src/Authenticate/AuthGuard.php index 00921611f..7f6ce786b 100644 --- a/app/sprinkles/account/src/Authenticate/AuthGuard.php +++ b/app/sprinkles/account/src/Authenticate/AuthGuard.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate; diff --git a/app/sprinkles/account/src/Authenticate/Authenticator.php b/app/sprinkles/account/src/Authenticate/Authenticator.php index c00c91f2f..c298770c6 100644 --- a/app/sprinkles/account/src/Authenticate/Authenticator.php +++ b/app/sprinkles/account/src/Authenticate/Authenticator.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php b/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php index 3ad4c5999..7bf831797 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AccountDisabledException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php b/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php index fb06fae41..8d2e5d9e5 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AccountInvalidException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php b/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php index 2a721bb17..e2324af1b 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AccountNotVerifiedException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php b/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php index 52fd5287a..179a82626 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AuthCompromisedException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; diff --git a/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php b/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php index ab7cbdb90..3f8764825 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/AuthExpiredException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; diff --git a/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php b/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php index 78ea3de03..3cc6b2320 100644 --- a/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php +++ b/app/sprinkles/account/src/Authenticate/Exception/InvalidCredentialsException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate\Exception; diff --git a/app/sprinkles/account/src/Authenticate/Hasher.php b/app/sprinkles/account/src/Authenticate/Hasher.php index d03747e22..3da32527a 100644 --- a/app/sprinkles/account/src/Authenticate/Hasher.php +++ b/app/sprinkles/account/src/Authenticate/Hasher.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authenticate; diff --git a/app/sprinkles/account/src/Authorize/AccessConditionExpression.php b/app/sprinkles/account/src/Authorize/AccessConditionExpression.php index 55b6090a6..301153e85 100644 --- a/app/sprinkles/account/src/Authorize/AccessConditionExpression.php +++ b/app/sprinkles/account/src/Authorize/AccessConditionExpression.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authorize; diff --git a/app/sprinkles/account/src/Authorize/AuthorizationException.php b/app/sprinkles/account/src/Authorize/AuthorizationException.php index a3341febc..06b613a6f 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationException.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authorize; diff --git a/app/sprinkles/account/src/Authorize/AuthorizationManager.php b/app/sprinkles/account/src/Authorize/AuthorizationManager.php index 9d5b8bd37..b30413914 100644 --- a/app/sprinkles/account/src/Authorize/AuthorizationManager.php +++ b/app/sprinkles/account/src/Authorize/AuthorizationManager.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authorize; diff --git a/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php b/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php index 76c79a99f..936dc2f1c 100644 --- a/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php +++ b/app/sprinkles/account/src/Authorize/ParserNodeFunctionEvaluator.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Authorize; diff --git a/app/sprinkles/account/src/Bakery/CreateAdminUser.php b/app/sprinkles/account/src/Bakery/CreateAdminUser.php index 0a68f2895..ea28a6a78 100644 --- a/app/sprinkles/account/src/Bakery/CreateAdminUser.php +++ b/app/sprinkles/account/src/Bakery/CreateAdminUser.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Bakery; diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 94aae8abd..15982e0f9 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Controller; diff --git a/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php b/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php index b9afe650c..4bc90b894 100644 --- a/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php +++ b/app/sprinkles/account/src/Controller/Exception/SpammyRequestException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Controller\Exception; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php index 492754c54..aa40649c8 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/ActivitiesTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php index 95f8c330c..937aa67c8 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/GroupsTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php index 5639d4fed..dcbc42b9f 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PasswordResetsTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php index 1b02d9176..a3596ae71 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionRolesTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php index 0c65ccd15..119ec1d6f 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PermissionsTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php index e476ece76..2b1ffb861 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/PersistencesTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php index 34c06efbc..c6aa8cddb 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RoleUsersTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php index cbc3132f7..0f65f937a 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/RolesTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php b/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php index e077f49d7..958a3a8c8 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/UsersTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php b/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php index 9742c9621..49d1825b4 100644 --- a/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php +++ b/app/sprinkles/account/src/Database/Migrations/v400/VerificationsTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v400; diff --git a/app/sprinkles/account/src/Database/Migrations/v420/AddingForeignKeys.php b/app/sprinkles/account/src/Database/Migrations/v420/AddingForeignKeys.php index 72c6df473..0ed908868 100644 --- a/app/sprinkles/account/src/Database/Migrations/v420/AddingForeignKeys.php +++ b/app/sprinkles/account/src/Database/Migrations/v420/AddingForeignKeys.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Migrations\v420; diff --git a/app/sprinkles/account/src/Database/Models/Activity.php b/app/sprinkles/account/src/Database/Models/Activity.php index 8ee605f2f..a2202b9b8 100644 --- a/app/sprinkles/account/src/Database/Models/Activity.php +++ b/app/sprinkles/account/src/Database/Models/Activity.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models; diff --git a/app/sprinkles/account/src/Database/Models/Events/DeleteUserCacheEvent.php b/app/sprinkles/account/src/Database/Models/Events/DeleteUserCacheEvent.php index 4e397f019..375f9a3b9 100644 --- a/app/sprinkles/account/src/Database/Models/Events/DeleteUserCacheEvent.php +++ b/app/sprinkles/account/src/Database/Models/Events/DeleteUserCacheEvent.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models\Events; diff --git a/app/sprinkles/account/src/Database/Models/Group.php b/app/sprinkles/account/src/Database/Models/Group.php index cc5690b96..d5925fbad 100644 --- a/app/sprinkles/account/src/Database/Models/Group.php +++ b/app/sprinkles/account/src/Database/Models/Group.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models; diff --git a/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php b/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php index 3870afc96..5c8e5f1b0 100644 --- a/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php +++ b/app/sprinkles/account/src/Database/Models/Interfaces/UserInterface.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models\Interfaces; diff --git a/app/sprinkles/account/src/Database/Models/PasswordReset.php b/app/sprinkles/account/src/Database/Models/PasswordReset.php index bf79826fa..3f7c2b646 100644 --- a/app/sprinkles/account/src/Database/Models/PasswordReset.php +++ b/app/sprinkles/account/src/Database/Models/PasswordReset.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models; diff --git a/app/sprinkles/account/src/Database/Models/Permission.php b/app/sprinkles/account/src/Database/Models/Permission.php index 0d72d0dd0..ff372e616 100644 --- a/app/sprinkles/account/src/Database/Models/Permission.php +++ b/app/sprinkles/account/src/Database/Models/Permission.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models; diff --git a/app/sprinkles/account/src/Database/Models/Persistence.php b/app/sprinkles/account/src/Database/Models/Persistence.php index c8a6ad4be..8137aa511 100644 --- a/app/sprinkles/account/src/Database/Models/Persistence.php +++ b/app/sprinkles/account/src/Database/Models/Persistence.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models; diff --git a/app/sprinkles/account/src/Database/Models/Role.php b/app/sprinkles/account/src/Database/Models/Role.php index 630420d27..81e8b585a 100644 --- a/app/sprinkles/account/src/Database/Models/Role.php +++ b/app/sprinkles/account/src/Database/Models/Role.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models; diff --git a/app/sprinkles/account/src/Database/Models/User.php b/app/sprinkles/account/src/Database/Models/User.php index 5afd7d7e8..3f3981eda 100644 --- a/app/sprinkles/account/src/Database/Models/User.php +++ b/app/sprinkles/account/src/Database/Models/User.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models; diff --git a/app/sprinkles/account/src/Database/Models/Verification.php b/app/sprinkles/account/src/Database/Models/Verification.php index 319d4d4bc..441890d37 100644 --- a/app/sprinkles/account/src/Database/Models/Verification.php +++ b/app/sprinkles/account/src/Database/Models/Verification.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Models; diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php b/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php index d538e7faa..7d6c5a4d6 100644 --- a/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php +++ b/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Seeds; diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php b/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php index ac6c81308..8df28e0a8 100644 --- a/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php +++ b/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Seeds; diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php b/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php index 9762be974..b6dcd4447 100644 --- a/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php +++ b/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Database\Seeds; diff --git a/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php b/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php index b2e3f9096..066ceebb8 100644 --- a/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php +++ b/app/sprinkles/account/src/Error/Handler/AuthCompromisedExceptionHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Error\Handler; diff --git a/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php b/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php index f796b0ec5..5f00fb1fb 100644 --- a/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php +++ b/app/sprinkles/account/src/Error/Handler/AuthExpiredExceptionHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Error\Handler; diff --git a/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php b/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php index 9b536e531..9a55efa9b 100644 --- a/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php +++ b/app/sprinkles/account/src/Error/Handler/ForbiddenExceptionHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Error\Handler; diff --git a/app/sprinkles/account/src/Facades/Password.php b/app/sprinkles/account/src/Facades/Password.php index 1f1e29278..c8bf4f44d 100644 --- a/app/sprinkles/account/src/Facades/Password.php +++ b/app/sprinkles/account/src/Facades/Password.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Facades; diff --git a/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php b/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php index e6a62f80c..3833094b8 100644 --- a/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php +++ b/app/sprinkles/account/src/Log/UserActivityDatabaseHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Log; diff --git a/app/sprinkles/account/src/Log/UserActivityProcessor.php b/app/sprinkles/account/src/Log/UserActivityProcessor.php index 9bed6b30a..3d251ff2a 100644 --- a/app/sprinkles/account/src/Log/UserActivityProcessor.php +++ b/app/sprinkles/account/src/Log/UserActivityProcessor.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Log; diff --git a/app/sprinkles/account/src/Rememberme/PDOStorage.php b/app/sprinkles/account/src/Rememberme/PDOStorage.php index 1eebc7cf4..ce67e0499 100644 --- a/app/sprinkles/account/src/Rememberme/PDOStorage.php +++ b/app/sprinkles/account/src/Rememberme/PDOStorage.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Rememberme; diff --git a/app/sprinkles/account/src/Repository/PasswordResetRepository.php b/app/sprinkles/account/src/Repository/PasswordResetRepository.php index 5a4832695..389f8bb6c 100644 --- a/app/sprinkles/account/src/Repository/PasswordResetRepository.php +++ b/app/sprinkles/account/src/Repository/PasswordResetRepository.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Repository; diff --git a/app/sprinkles/account/src/Repository/TokenRepository.php b/app/sprinkles/account/src/Repository/TokenRepository.php index ebe9134ab..8b1560660 100644 --- a/app/sprinkles/account/src/Repository/TokenRepository.php +++ b/app/sprinkles/account/src/Repository/TokenRepository.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Repository; diff --git a/app/sprinkles/account/src/Repository/VerificationRepository.php b/app/sprinkles/account/src/Repository/VerificationRepository.php index 26f447f46..d421185f2 100644 --- a/app/sprinkles/account/src/Repository/VerificationRepository.php +++ b/app/sprinkles/account/src/Repository/VerificationRepository.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Repository; diff --git a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php index 408a4b816..2f1692229 100644 --- a/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/account/src/ServicesProvider/ServicesProvider.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\ServicesProvider; diff --git a/app/sprinkles/account/src/Twig/AccountExtension.php b/app/sprinkles/account/src/Twig/AccountExtension.php index 1c9dbd003..69625a953 100644 --- a/app/sprinkles/account/src/Twig/AccountExtension.php +++ b/app/sprinkles/account/src/Twig/AccountExtension.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Twig; diff --git a/app/sprinkles/account/src/Util/HashFailedException.php b/app/sprinkles/account/src/Util/HashFailedException.php index 765096b8b..d394166c5 100644 --- a/app/sprinkles/account/src/Util/HashFailedException.php +++ b/app/sprinkles/account/src/Util/HashFailedException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Util; diff --git a/app/sprinkles/account/src/Util/Util.php b/app/sprinkles/account/src/Util/Util.php index da1abfd26..db3257cab 100644 --- a/app/sprinkles/account/src/Util/Util.php +++ b/app/sprinkles/account/src/Util/Util.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Util; diff --git a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php index c0d3b23db..38ddde710 100644 --- a/app/sprinkles/account/tests/Integration/AuthenticatorTest.php +++ b/app/sprinkles/account/tests/Integration/AuthenticatorTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Tests\Integration; diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index f9c46a6a5..b520fd4da 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Tests\Integration; diff --git a/app/sprinkles/account/tests/Unit/FactoriesTest.php b/app/sprinkles/account/tests/Unit/FactoriesTest.php index c771058d9..841772d54 100644 --- a/app/sprinkles/account/tests/Unit/FactoriesTest.php +++ b/app/sprinkles/account/tests/Unit/FactoriesTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Tests\Unit; diff --git a/app/sprinkles/account/tests/Unit/HasherTest.php b/app/sprinkles/account/tests/Unit/HasherTest.php index cbd76dcf0..4bc6c11f6 100644 --- a/app/sprinkles/account/tests/Unit/HasherTest.php +++ b/app/sprinkles/account/tests/Unit/HasherTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Tests\Unit; diff --git a/app/sprinkles/account/tests/Unit/PDOStorageTest.php b/app/sprinkles/account/tests/Unit/PDOStorageTest.php index 37f0a545c..faa5819b5 100644 --- a/app/sprinkles/account/tests/Unit/PDOStorageTest.php +++ b/app/sprinkles/account/tests/Unit/PDOStorageTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Tests\Unit; diff --git a/app/sprinkles/account/tests/Unit/RegistrationTest.php b/app/sprinkles/account/tests/Unit/RegistrationTest.php index 571f73a81..dead5af3f 100644 --- a/app/sprinkles/account/tests/Unit/RegistrationTest.php +++ b/app/sprinkles/account/tests/Unit/RegistrationTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Tests\Unit; diff --git a/app/sprinkles/account/tests/withTestUser.php b/app/sprinkles/account/tests/withTestUser.php index 53a19d00a..a2727fa66 100644 --- a/app/sprinkles/account/tests/withTestUser.php +++ b/app/sprinkles/account/tests/withTestUser.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Account\Tests; diff --git a/app/sprinkles/admin/locale/ar/messages.php b/app/sprinkles/admin/locale/ar/messages.php index 0ec2e401a..8c57858df 100644 --- a/app/sprinkles/admin/locale/ar/messages.php +++ b/app/sprinkles/admin/locale/ar/messages.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/admin/locale/de_DE/messages.php b/app/sprinkles/admin/locale/de_DE/messages.php index 710eb00e3..575a73a18 100644 --- a/app/sprinkles/admin/locale/de_DE/messages.php +++ b/app/sprinkles/admin/locale/de_DE/messages.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/admin/locale/en_US/messages.php b/app/sprinkles/admin/locale/en_US/messages.php index ce3de1c34..b36fa3fac 100644 --- a/app/sprinkles/admin/locale/en_US/messages.php +++ b/app/sprinkles/admin/locale/en_US/messages.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/admin/locale/es_ES/messages.php b/app/sprinkles/admin/locale/es_ES/messages.php index 96dd3ec41..c62c408e8 100755 --- a/app/sprinkles/admin/locale/es_ES/messages.php +++ b/app/sprinkles/admin/locale/es_ES/messages.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/app/sprinkles/admin/locale/fa/messages.php b/app/sprinkles/admin/locale/fa/messages.php index d6915c1cd..5a38ad65c 100644 --- a/app/sprinkles/admin/locale/fa/messages.php +++ b/app/sprinkles/admin/locale/fa/messages.php @@ -1,10 +1,10 @@ getContainer()->get('config'); diff --git a/app/sprinkles/core/src/Alert/AlertStream.php b/app/sprinkles/core/src/Alert/AlertStream.php index 1d01075cd..bae135115 100644 --- a/app/sprinkles/core/src/Alert/AlertStream.php +++ b/app/sprinkles/core/src/Alert/AlertStream.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Alert; diff --git a/app/sprinkles/core/src/Alert/CacheAlertStream.php b/app/sprinkles/core/src/Alert/CacheAlertStream.php index 76c8f010c..0dc048029 100644 --- a/app/sprinkles/core/src/Alert/CacheAlertStream.php +++ b/app/sprinkles/core/src/Alert/CacheAlertStream.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Alert; diff --git a/app/sprinkles/core/src/Alert/SessionAlertStream.php b/app/sprinkles/core/src/Alert/SessionAlertStream.php index 7b5ae746d..5a63d0a6c 100644 --- a/app/sprinkles/core/src/Alert/SessionAlertStream.php +++ b/app/sprinkles/core/src/Alert/SessionAlertStream.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Alert; diff --git a/app/sprinkles/core/src/Bakery/BakeCommand.php b/app/sprinkles/core/src/Bakery/BakeCommand.php index 115a3eadb..4edcab6e4 100644 --- a/app/sprinkles/core/src/Bakery/BakeCommand.php +++ b/app/sprinkles/core/src/Bakery/BakeCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/BuildAssets.php b/app/sprinkles/core/src/Bakery/BuildAssets.php index 70f9a5416..cc5cfccb2 100644 --- a/app/sprinkles/core/src/Bakery/BuildAssets.php +++ b/app/sprinkles/core/src/Bakery/BuildAssets.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; @@ -92,6 +93,7 @@ protected function npmInstall($force) if (!$force && file_exists('package-lock.json') && filemtime('package.json') < filemtime('package-lock.json') - 1) { $this->io->writeln('> Skipping as package-lock.json age indicates dependencies are already installed'); chdir($wd); + return; } diff --git a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php index 210cbc0af..36a9577f8 100644 --- a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php +++ b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/DebugCommand.php b/app/sprinkles/core/src/Bakery/DebugCommand.php index 8fea69c6e..45ba42e76 100644 --- a/app/sprinkles/core/src/Bakery/DebugCommand.php +++ b/app/sprinkles/core/src/Bakery/DebugCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/Helper/ConfirmableTrait.php b/app/sprinkles/core/src/Bakery/Helper/ConfirmableTrait.php index 2ac666129..8cc73fccb 100644 --- a/app/sprinkles/core/src/Bakery/Helper/ConfirmableTrait.php +++ b/app/sprinkles/core/src/Bakery/Helper/ConfirmableTrait.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery\Helper; diff --git a/app/sprinkles/core/src/Bakery/Helper/DatabaseTest.php b/app/sprinkles/core/src/Bakery/Helper/DatabaseTest.php index 0bf43ee5b..b64d6c9c4 100644 --- a/app/sprinkles/core/src/Bakery/Helper/DatabaseTest.php +++ b/app/sprinkles/core/src/Bakery/Helper/DatabaseTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery\Helper; diff --git a/app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php b/app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php index ed055b3f1..29989340f 100644 --- a/app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php +++ b/app/sprinkles/core/src/Bakery/Helper/NodeVersionCheck.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery\Helper; diff --git a/app/sprinkles/core/src/Bakery/MigrateCommand.php b/app/sprinkles/core/src/Bakery/MigrateCommand.php index 4816fbf95..5a987470e 100644 --- a/app/sprinkles/core/src/Bakery/MigrateCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; @@ -58,6 +59,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // Don't go further if no migration is pending if (empty($pending)) { $this->io->success('Nothing to migrate'); + return; } diff --git a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php index b14c70672..bf0247cb6 100644 --- a/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateRefreshCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php index b2d9af1e0..da2ae338d 100644 --- a/app/sprinkles/core/src/Bakery/MigrateResetCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateResetCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php index 8d201ace4..9d6dab3bd 100644 --- a/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateRollbackCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; @@ -50,7 +51,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $migrator = $this->setupMigrator($input); // Get pending migrations - $ran = $migration ? [$migration]: $migrator->getRanMigrations($steps); + $ran = $migration ? [$migration] : $migrator->getRanMigrations($steps); // Don't go further if no migration is ran if (empty($ran)) { diff --git a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php index bfda24f1b..0469b03a5 100644 --- a/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php +++ b/app/sprinkles/core/src/Bakery/MigrateStatusCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/RouteListCommand.php b/app/sprinkles/core/src/Bakery/RouteListCommand.php index 0a0f63f44..5e03e34cc 100644 --- a/app/sprinkles/core/src/Bakery/RouteListCommand.php +++ b/app/sprinkles/core/src/Bakery/RouteListCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/SeedCommand.php b/app/sprinkles/core/src/Bakery/SeedCommand.php index 8e2e6fab9..cb52b7935 100644 --- a/app/sprinkles/core/src/Bakery/SeedCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/SeedListCommand.php b/app/sprinkles/core/src/Bakery/SeedListCommand.php index 28aa9119c..83595685b 100644 --- a/app/sprinkles/core/src/Bakery/SeedListCommand.php +++ b/app/sprinkles/core/src/Bakery/SeedListCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/SetupCommand.php b/app/sprinkles/core/src/Bakery/SetupCommand.php index 26dd546a1..4f0ff5f45 100644 --- a/app/sprinkles/core/src/Bakery/SetupCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/SetupDbCommand.php b/app/sprinkles/core/src/Bakery/SetupDbCommand.php index 58278512c..c46ef8e4f 100644 --- a/app/sprinkles/core/src/Bakery/SetupDbCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupDbCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php index 38f738759..42bfc5e07 100644 --- a/app/sprinkles/core/src/Bakery/SetupEnvCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupEnvCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php index 090f16049..7c6a81fea 100644 --- a/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php +++ b/app/sprinkles/core/src/Bakery/SetupSmtpCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/Test.php b/app/sprinkles/core/src/Bakery/Test.php index b4163fd8e..f8f112072 100644 --- a/app/sprinkles/core/src/Bakery/Test.php +++ b/app/sprinkles/core/src/Bakery/Test.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Bakery/TestMailCommand.php b/app/sprinkles/core/src/Bakery/TestMailCommand.php index f261ebb2f..d302165b1 100644 --- a/app/sprinkles/core/src/Bakery/TestMailCommand.php +++ b/app/sprinkles/core/src/Bakery/TestMailCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Bakery; diff --git a/app/sprinkles/core/src/Controller/CoreController.php b/app/sprinkles/core/src/Controller/CoreController.php index 6026f6e59..c0c7f2a5f 100644 --- a/app/sprinkles/core/src/Controller/CoreController.php +++ b/app/sprinkles/core/src/Controller/CoreController.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Controller; diff --git a/app/sprinkles/core/src/Controller/SimpleController.php b/app/sprinkles/core/src/Controller/SimpleController.php index 31eb35990..e0e3d0f75 100644 --- a/app/sprinkles/core/src/Controller/SimpleController.php +++ b/app/sprinkles/core/src/Controller/SimpleController.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Controller; diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index 1e8ec85f6..19e992794 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core; diff --git a/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php b/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php index d34627d87..de7adc450 100644 --- a/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php +++ b/app/sprinkles/core/src/Csrf/CsrfProviderInterface.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Csrf; diff --git a/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php b/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php index 226a7ae56..56c2139f9 100644 --- a/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php +++ b/app/sprinkles/core/src/Csrf/SlimCsrfProvider.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Csrf; diff --git a/app/sprinkles/core/src/Database/Builder.php b/app/sprinkles/core/src/Database/Builder.php index 23ad12fb1..12ec3b1c9 100644 --- a/app/sprinkles/core/src/Database/Builder.php +++ b/app/sprinkles/core/src/Database/Builder.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database; diff --git a/app/sprinkles/core/src/Database/DatabaseInvalidException.php b/app/sprinkles/core/src/Database/DatabaseInvalidException.php index 0eba67b0d..c1f8d664c 100644 --- a/app/sprinkles/core/src/Database/DatabaseInvalidException.php +++ b/app/sprinkles/core/src/Database/DatabaseInvalidException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database; diff --git a/app/sprinkles/core/src/Database/EloquentBuilder.php b/app/sprinkles/core/src/Database/EloquentBuilder.php index 09c8c6378..bfeb265c0 100644 --- a/app/sprinkles/core/src/Database/EloquentBuilder.php +++ b/app/sprinkles/core/src/Database/EloquentBuilder.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database; diff --git a/app/sprinkles/core/src/Database/Migration.php b/app/sprinkles/core/src/Database/Migration.php index 8b76eb041..a9d805add 100644 --- a/app/sprinkles/core/src/Database/Migration.php +++ b/app/sprinkles/core/src/Database/Migration.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database; diff --git a/app/sprinkles/core/src/Database/MigrationInterface.php b/app/sprinkles/core/src/Database/MigrationInterface.php index 802441832..e04e0e3a6 100644 --- a/app/sprinkles/core/src/Database/MigrationInterface.php +++ b/app/sprinkles/core/src/Database/MigrationInterface.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database; diff --git a/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php b/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php index b634577b5..637383688 100644 --- a/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php +++ b/app/sprinkles/core/src/Database/Migrations/v400/SessionsTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrations\v400; diff --git a/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php b/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php index 6ae7df00d..7b2d8f8aa 100644 --- a/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php +++ b/app/sprinkles/core/src/Database/Migrations/v400/ThrottlesTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrations\v400; diff --git a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php index 8fea97d1a..6a8a6f9f0 100644 --- a/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php +++ b/app/sprinkles/core/src/Database/Migrator/DatabaseMigrationRepository.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrator; diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php index 693ae58b6..46a93aaaf 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationDependencyAnalyser.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrator; diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php index b64937916..899ae1070 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocator.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrator; @@ -62,7 +63,7 @@ public function getMigrations() * Return an array of migration details inclusing the classname and the sprinkle name * * @param ResourceInstance $file The migration file - * @return string The migration full class path + * @return string The migration full class path */ protected function getMigrationDetails(ResourceInstance $file) { diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php index fab0a435b..32f149af6 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationLocatorInterface.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrator; diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php b/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php index a8ee19042..5f0743263 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRepositoryInterface.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrator; diff --git a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php index 837238c50..4011e181a 100644 --- a/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php +++ b/app/sprinkles/core/src/Database/Migrator/MigrationRollbackDependencyAnalyser.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrator; diff --git a/app/sprinkles/core/src/Database/Migrator/Migrator.php b/app/sprinkles/core/src/Database/Migrator/Migrator.php index f5582ebb8..a0627087f 100644 --- a/app/sprinkles/core/src/Database/Migrator/Migrator.php +++ b/app/sprinkles/core/src/Database/Migrator/Migrator.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Migrator; @@ -482,6 +483,7 @@ public function getPendingMigrations() { $available = $this->getAvailableMigrations(); $ran = $this->getRanMigrations(); + return $this->pendingMigrations($available, $ran); } diff --git a/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php b/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php index 6b4b55896..948a88c76 100644 --- a/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php +++ b/app/sprinkles/core/src/Database/Models/Concerns/HasRelationships.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Models\Concerns; diff --git a/app/sprinkles/core/src/Database/Models/Model.php b/app/sprinkles/core/src/Database/Models/Model.php index abe9e9772..26ef167c1 100644 --- a/app/sprinkles/core/src/Database/Models/Model.php +++ b/app/sprinkles/core/src/Database/Models/Model.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Models; diff --git a/app/sprinkles/core/src/Database/Models/Throttle.php b/app/sprinkles/core/src/Database/Models/Throttle.php index d02c1bdb8..fb99c013b 100644 --- a/app/sprinkles/core/src/Database/Models/Throttle.php +++ b/app/sprinkles/core/src/Database/Models/Throttle.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Models; diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php index 8207fda30..e834523f8 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyConstrained.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Relations; diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php index 3fd2c7cb8..50f6dbc59 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyThrough.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Relations; diff --git a/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php b/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php index a0478d80e..60a98b799 100644 --- a/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php +++ b/app/sprinkles/core/src/Database/Relations/BelongsToManyUnique.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Relations; diff --git a/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php b/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php index 3093de0b6..730180be4 100644 --- a/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php +++ b/app/sprinkles/core/src/Database/Relations/Concerns/Syncable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Relations\Concerns; diff --git a/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php b/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php index c87668b0b..90aa8a6cf 100644 --- a/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php +++ b/app/sprinkles/core/src/Database/Relations/Concerns/Unique.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Relations\Concerns; diff --git a/app/sprinkles/core/src/Database/Relations/HasManySyncable.php b/app/sprinkles/core/src/Database/Relations/HasManySyncable.php index 3acaac712..ca35e93b6 100644 --- a/app/sprinkles/core/src/Database/Relations/HasManySyncable.php +++ b/app/sprinkles/core/src/Database/Relations/HasManySyncable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Relations; diff --git a/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php b/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php index 12d3e5fd8..8492ce028 100644 --- a/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php +++ b/app/sprinkles/core/src/Database/Relations/MorphManySyncable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Relations; diff --git a/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php b/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php index 26637bfa6..9d7a75611 100644 --- a/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php +++ b/app/sprinkles/core/src/Database/Relations/MorphToManyUnique.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Relations; diff --git a/app/sprinkles/core/src/Database/Seeder/BaseSeed.php b/app/sprinkles/core/src/Database/Seeder/BaseSeed.php index ef625d2c3..86f217c06 100644 --- a/app/sprinkles/core/src/Database/Seeder/BaseSeed.php +++ b/app/sprinkles/core/src/Database/Seeder/BaseSeed.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Seeder; diff --git a/app/sprinkles/core/src/Database/Seeder/SeedInterface.php b/app/sprinkles/core/src/Database/Seeder/SeedInterface.php index 7253d08df..8ae25ef98 100644 --- a/app/sprinkles/core/src/Database/Seeder/SeedInterface.php +++ b/app/sprinkles/core/src/Database/Seeder/SeedInterface.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Seeder; diff --git a/app/sprinkles/core/src/Database/Seeder/Seeder.php b/app/sprinkles/core/src/Database/Seeder/Seeder.php index e494e9e6c..1dbb12f5b 100644 --- a/app/sprinkles/core/src/Database/Seeder/Seeder.php +++ b/app/sprinkles/core/src/Database/Seeder/Seeder.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Seeder; @@ -142,7 +143,7 @@ protected function loadSeeders(array $seedFiles) * Return an array of seed details inclusing the classname and the sprinkle name * * @param ResourceInstance $file The seed file - * @return array The details about a seed file [name, class, sprinkle] + * @return array The details about a seed file [name, class, sprinkle] */ protected function getSeedDetails(ResourceInstance $file) { diff --git a/app/sprinkles/core/src/Error/ExceptionHandlerManager.php b/app/sprinkles/core/src/Error/ExceptionHandlerManager.php index 400a507c6..544b83b92 100755 --- a/app/sprinkles/core/src/Error/ExceptionHandlerManager.php +++ b/app/sprinkles/core/src/Error/ExceptionHandlerManager.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error; diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php index aa0f0f9b9..a46f20f9d 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Handler; diff --git a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php index 50b4e9f48..b6146e412 100644 --- a/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php +++ b/app/sprinkles/core/src/Error/Handler/ExceptionHandlerInterface.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Handler; diff --git a/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php index 24799433d..615c434d3 100644 --- a/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/HttpExceptionHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Handler; diff --git a/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php index 4f1f089d6..863d90922 100644 --- a/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/NotFoundExceptionHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Handler; diff --git a/app/sprinkles/core/src/Error/Handler/PhpMailerExceptionHandler.php b/app/sprinkles/core/src/Error/Handler/PhpMailerExceptionHandler.php index 18499dbf8..7bbe75e66 100644 --- a/app/sprinkles/core/src/Error/Handler/PhpMailerExceptionHandler.php +++ b/app/sprinkles/core/src/Error/Handler/PhpMailerExceptionHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Handler; diff --git a/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php b/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php index 50c1feffd..464034325 100644 --- a/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/ErrorRenderer.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; diff --git a/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php b/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php index 14567b180..c57869f1c 100755 --- a/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php +++ b/app/sprinkles/core/src/Error/Renderer/ErrorRendererInterface.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; diff --git a/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php b/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php index 1d0ef0559..e47465bb7 100644 --- a/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/HtmlRenderer.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; diff --git a/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php b/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php index ffaf917e8..0fd9a103e 100755 --- a/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/JsonRenderer.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; diff --git a/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php b/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php index d73b9bce5..f1e9cf7a9 100755 --- a/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/PlainTextRenderer.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; diff --git a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php index f731057ab..523b850ee 100644 --- a/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/WhoopsRenderer.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; diff --git a/app/sprinkles/core/src/Error/Renderer/XmlRenderer.php b/app/sprinkles/core/src/Error/Renderer/XmlRenderer.php index 36e7ed6ee..ac3c0e267 100755 --- a/app/sprinkles/core/src/Error/Renderer/XmlRenderer.php +++ b/app/sprinkles/core/src/Error/Renderer/XmlRenderer.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Error\Renderer; diff --git a/app/sprinkles/core/src/Facades/Cache.php b/app/sprinkles/core/src/Facades/Cache.php index 5f24d983b..719599de7 100644 --- a/app/sprinkles/core/src/Facades/Cache.php +++ b/app/sprinkles/core/src/Facades/Cache.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Facades; diff --git a/app/sprinkles/core/src/Facades/Config.php b/app/sprinkles/core/src/Facades/Config.php index 514f60011..ba32bd706 100644 --- a/app/sprinkles/core/src/Facades/Config.php +++ b/app/sprinkles/core/src/Facades/Config.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Facades; diff --git a/app/sprinkles/core/src/Facades/Debug.php b/app/sprinkles/core/src/Facades/Debug.php index 4dc0f93f8..570907e73 100644 --- a/app/sprinkles/core/src/Facades/Debug.php +++ b/app/sprinkles/core/src/Facades/Debug.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Facades; diff --git a/app/sprinkles/core/src/Facades/Seeder.php b/app/sprinkles/core/src/Facades/Seeder.php index 2c3031266..897c2efd0 100644 --- a/app/sprinkles/core/src/Facades/Seeder.php +++ b/app/sprinkles/core/src/Facades/Seeder.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Facades; diff --git a/app/sprinkles/core/src/Facades/Storage.php b/app/sprinkles/core/src/Facades/Storage.php index 32c296e49..573b87442 100644 --- a/app/sprinkles/core/src/Facades/Storage.php +++ b/app/sprinkles/core/src/Facades/Storage.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Facades; diff --git a/app/sprinkles/core/src/Facades/Translator.php b/app/sprinkles/core/src/Facades/Translator.php index 814f680b6..3111c7d99 100644 --- a/app/sprinkles/core/src/Facades/Translator.php +++ b/app/sprinkles/core/src/Facades/Translator.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Facades; diff --git a/app/sprinkles/core/src/Filesystem/FilesystemManager.php b/app/sprinkles/core/src/Filesystem/FilesystemManager.php index b993bc859..da43555fb 100644 --- a/app/sprinkles/core/src/Filesystem/FilesystemManager.php +++ b/app/sprinkles/core/src/Filesystem/FilesystemManager.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Filesystem; diff --git a/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php b/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php index 8ed008749..386d019ae 100644 --- a/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php +++ b/app/sprinkles/core/src/Http/Concerns/DeterminesContentType.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Http\Concerns; diff --git a/app/sprinkles/core/src/Log/DatabaseHandler.php b/app/sprinkles/core/src/Log/DatabaseHandler.php index 4ddfc5ee1..557e63299 100644 --- a/app/sprinkles/core/src/Log/DatabaseHandler.php +++ b/app/sprinkles/core/src/Log/DatabaseHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Log; diff --git a/app/sprinkles/core/src/Log/MixedFormatter.php b/app/sprinkles/core/src/Log/MixedFormatter.php index 4111256bb..8a3c228cb 100644 --- a/app/sprinkles/core/src/Log/MixedFormatter.php +++ b/app/sprinkles/core/src/Log/MixedFormatter.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Log; diff --git a/app/sprinkles/core/src/Mail/EmailRecipient.php b/app/sprinkles/core/src/Mail/EmailRecipient.php index fb2843a88..8ab1febd0 100755 --- a/app/sprinkles/core/src/Mail/EmailRecipient.php +++ b/app/sprinkles/core/src/Mail/EmailRecipient.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Mail; diff --git a/app/sprinkles/core/src/Mail/MailMessage.php b/app/sprinkles/core/src/Mail/MailMessage.php index 9fd18f33b..6f0542a26 100644 --- a/app/sprinkles/core/src/Mail/MailMessage.php +++ b/app/sprinkles/core/src/Mail/MailMessage.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Mail; diff --git a/app/sprinkles/core/src/Mail/Mailer.php b/app/sprinkles/core/src/Mail/Mailer.php index 7c43fbd85..1f957b729 100644 --- a/app/sprinkles/core/src/Mail/Mailer.php +++ b/app/sprinkles/core/src/Mail/Mailer.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Mail; diff --git a/app/sprinkles/core/src/Mail/StaticMailMessage.php b/app/sprinkles/core/src/Mail/StaticMailMessage.php index 22ec70533..2085a8a9d 100644 --- a/app/sprinkles/core/src/Mail/StaticMailMessage.php +++ b/app/sprinkles/core/src/Mail/StaticMailMessage.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Mail; diff --git a/app/sprinkles/core/src/Mail/TwigMailMessage.php b/app/sprinkles/core/src/Mail/TwigMailMessage.php index 6c979d7b3..dd5b28659 100644 --- a/app/sprinkles/core/src/Mail/TwigMailMessage.php +++ b/app/sprinkles/core/src/Mail/TwigMailMessage.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Mail; diff --git a/app/sprinkles/core/src/Model/UFModel.php b/app/sprinkles/core/src/Model/UFModel.php index 60635e035..df058ca03 100644 --- a/app/sprinkles/core/src/Model/UFModel.php +++ b/app/sprinkles/core/src/Model/UFModel.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Model; diff --git a/app/sprinkles/core/src/Router.php b/app/sprinkles/core/src/Router.php index 60ff05a91..b3f1bfac1 100644 --- a/app/sprinkles/core/src/Router.php +++ b/app/sprinkles/core/src/Router.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core; diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 188d41299..56ab8546c 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\ServicesProvider; diff --git a/app/sprinkles/core/src/Session/NullSessionHandler.php b/app/sprinkles/core/src/Session/NullSessionHandler.php index fc2b5c428..42e737348 100644 --- a/app/sprinkles/core/src/Session/NullSessionHandler.php +++ b/app/sprinkles/core/src/Session/NullSessionHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Session; diff --git a/app/sprinkles/core/src/Sprunje/Sprunje.php b/app/sprinkles/core/src/Sprunje/Sprunje.php index 605b90658..b09dc51b4 100644 --- a/app/sprinkles/core/src/Sprunje/Sprunje.php +++ b/app/sprinkles/core/src/Sprunje/Sprunje.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Sprunje; diff --git a/app/sprinkles/core/src/Throttle/ThrottleRule.php b/app/sprinkles/core/src/Throttle/ThrottleRule.php index 9829ebcee..0c39d596d 100644 --- a/app/sprinkles/core/src/Throttle/ThrottleRule.php +++ b/app/sprinkles/core/src/Throttle/ThrottleRule.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Throttle; diff --git a/app/sprinkles/core/src/Throttle/Throttler.php b/app/sprinkles/core/src/Throttle/Throttler.php index 19283ebf2..c5f24226f 100644 --- a/app/sprinkles/core/src/Throttle/Throttler.php +++ b/app/sprinkles/core/src/Throttle/Throttler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Throttle; diff --git a/app/sprinkles/core/src/Throttle/ThrottlerException.php b/app/sprinkles/core/src/Throttle/ThrottlerException.php index 0f231f372..3bfefd2ee 100644 --- a/app/sprinkles/core/src/Throttle/ThrottlerException.php +++ b/app/sprinkles/core/src/Throttle/ThrottlerException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Throttle; diff --git a/app/sprinkles/core/src/Twig/CacheHelper.php b/app/sprinkles/core/src/Twig/CacheHelper.php index dc654c517..e4e8be87d 100755 --- a/app/sprinkles/core/src/Twig/CacheHelper.php +++ b/app/sprinkles/core/src/Twig/CacheHelper.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Twig; diff --git a/app/sprinkles/core/src/Twig/CoreExtension.php b/app/sprinkles/core/src/Twig/CoreExtension.php index 83ac3123f..da858f504 100755 --- a/app/sprinkles/core/src/Twig/CoreExtension.php +++ b/app/sprinkles/core/src/Twig/CoreExtension.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Twig; diff --git a/app/sprinkles/core/src/Util/BadClassNameException.php b/app/sprinkles/core/src/Util/BadClassNameException.php index 1cd6f4e2a..7e3ce4c58 100644 --- a/app/sprinkles/core/src/Util/BadClassNameException.php +++ b/app/sprinkles/core/src/Util/BadClassNameException.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Util; diff --git a/app/sprinkles/core/src/Util/Captcha.php b/app/sprinkles/core/src/Util/Captcha.php index 8472d7be3..d0611d656 100644 --- a/app/sprinkles/core/src/Util/Captcha.php +++ b/app/sprinkles/core/src/Util/Captcha.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Util; diff --git a/app/sprinkles/core/src/Util/CheckEnvironment.php b/app/sprinkles/core/src/Util/CheckEnvironment.php index 9087423b0..fce19bfc7 100644 --- a/app/sprinkles/core/src/Util/CheckEnvironment.php +++ b/app/sprinkles/core/src/Util/CheckEnvironment.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Util; diff --git a/app/sprinkles/core/src/Util/ClassMapper.php b/app/sprinkles/core/src/Util/ClassMapper.php index 448c1f496..4c3edc3b7 100644 --- a/app/sprinkles/core/src/Util/ClassMapper.php +++ b/app/sprinkles/core/src/Util/ClassMapper.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Util; diff --git a/app/sprinkles/core/src/Util/EnvironmentInfo.php b/app/sprinkles/core/src/Util/EnvironmentInfo.php index 459c34757..f092a15fa 100644 --- a/app/sprinkles/core/src/Util/EnvironmentInfo.php +++ b/app/sprinkles/core/src/Util/EnvironmentInfo.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Util; diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index f8f33915c..d22795890 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Util; diff --git a/app/sprinkles/core/src/Util/ShutdownHandler.php b/app/sprinkles/core/src/Util/ShutdownHandler.php index e17928b76..df80dcf91 100755 --- a/app/sprinkles/core/src/Util/ShutdownHandler.php +++ b/app/sprinkles/core/src/Util/ShutdownHandler.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Util; diff --git a/app/sprinkles/core/src/Util/Util.php b/app/sprinkles/core/src/Util/Util.php index d601c0dbb..9cd14008a 100644 --- a/app/sprinkles/core/src/Util/Util.php +++ b/app/sprinkles/core/src/Util/Util.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Util; diff --git a/app/sprinkles/core/tests/ControllerTestCase.php b/app/sprinkles/core/tests/ControllerTestCase.php index aa8957598..da67cdda3 100644 --- a/app/sprinkles/core/tests/ControllerTestCase.php +++ b/app/sprinkles/core/tests/ControllerTestCase.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests; diff --git a/app/sprinkles/core/tests/DatabaseTransactions.php b/app/sprinkles/core/tests/DatabaseTransactions.php index 5fcfb8b93..668905e1c 100644 --- a/app/sprinkles/core/tests/DatabaseTransactions.php +++ b/app/sprinkles/core/tests/DatabaseTransactions.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php index 1ead982fa..79fb5d91b 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateCommandTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php index 27cbbcc3e..58e3cb8a0 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRefreshCommandTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php index a6cd43a74..7a995c319 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateResetCommandTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php index 3cda59e2b..6aba5a97d 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateRollbackCommandTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php index 50e986fe4..da0a83177 100644 --- a/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php +++ b/app/sprinkles/core/tests/Integration/BakeryMigrateStatusCommandTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php b/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php index cf8c67b72..2d283e7b9 100644 --- a/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php +++ b/app/sprinkles/core/tests/Integration/CheckEnvironmentTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php index 5e284f10d..f8dc0415c 100644 --- a/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php +++ b/app/sprinkles/core/tests/Integration/Controllers/CoreControllerTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests; diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php index b87c2db16..a68530d29 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorIntegrationTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php index 41b739618..494d12d90 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorServiceTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php index a0a9c4003..c0134ad7e 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php +++ b/app/sprinkles/core/tests/Integration/DatabaseMigratorTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/DatabaseTests.php b/app/sprinkles/core/tests/Integration/DatabaseTests.php index 496549628..f7a44e67a 100644 --- a/app/sprinkles/core/tests/Integration/DatabaseTests.php +++ b/app/sprinkles/core/tests/Integration/DatabaseTests.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php b/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php index e10ea5793..4d9ca9df5 100644 --- a/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php +++ b/app/sprinkles/core/tests/Integration/Error/Handler/ExceptionHandlerTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Integration\Error\Handler; diff --git a/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php b/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php index 1b9c886d6..4b819f345 100644 --- a/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php +++ b/app/sprinkles/core/tests/Integration/Error/Renderer/WhoopsRendererTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Integration\Error\Renderer; diff --git a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php index ca2ed2904..5a72ab04d 100644 --- a/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationDependencyAnalyserTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php index 2cfa9ccaa..1ccab2b06 100644 --- a/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationLocatorTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php index 576503b3d..a16a95cbc 100644 --- a/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php +++ b/app/sprinkles/core/tests/Integration/MigrationRepositoryTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Integration; diff --git a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php index 6ee07ef24..4aee13c71 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/DeprecatedClassTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Integration\Migrations; diff --git a/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php b/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php index 12c445793..a389f5187 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/UnfulfillableTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Integration\Migrations; diff --git a/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php b/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php index bcf2f7750..0e43db518 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/one/CreatePasswordResetsTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Integration\Migrations\one; diff --git a/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php b/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php index 327262e6a..688b5c8a1 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/one/CreateUsersTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Integration\Migrations\one; diff --git a/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php b/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php index 4f77eee8b..2c8fe5f31 100644 --- a/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php +++ b/app/sprinkles/core/tests/Integration/Migrations/two/CreateFlightsTable.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Integration\Migrations\two; diff --git a/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php b/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php index ae4ff5956..f565b8612 100644 --- a/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php +++ b/app/sprinkles/core/tests/Integration/Seeder/SeederTests.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Integration\Seeder; diff --git a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php index 419ae5d00..d6923599e 100644 --- a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php +++ b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed1.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Seeds; diff --git a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed2.php b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed2.php index 70d78dd55..1a1bd6b02 100644 --- a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed2.php +++ b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Seed2.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Seeds; diff --git a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Test/Seed.php b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Test/Seed.php index adb89e973..aea0f8477 100644 --- a/app/sprinkles/core/tests/Integration/Seeder/Seeds/Test/Seed.php +++ b/app/sprinkles/core/tests/Integration/Seeder/Seeds/Test/Seed.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Database\Seeds; diff --git a/app/sprinkles/core/tests/RefreshDatabase.php b/app/sprinkles/core/tests/RefreshDatabase.php index 6c03588a5..6504e9cd9 100644 --- a/app/sprinkles/core/tests/RefreshDatabase.php +++ b/app/sprinkles/core/tests/RefreshDatabase.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests; diff --git a/app/sprinkles/core/tests/TestDatabase.php b/app/sprinkles/core/tests/TestDatabase.php index 772d9f737..0029f519a 100644 --- a/app/sprinkles/core/tests/TestDatabase.php +++ b/app/sprinkles/core/tests/TestDatabase.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests; diff --git a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php index 837cb2958..22e2ad203 100644 --- a/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php +++ b/app/sprinkles/core/tests/Unit/BelongsToManyThroughTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Unit; diff --git a/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php b/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php index 404f3a7de..cf363f876 100644 --- a/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php +++ b/app/sprinkles/core/tests/Unit/DatabaseSyncableTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Unit; diff --git a/app/sprinkles/core/tests/Unit/FilesystemTest.php b/app/sprinkles/core/tests/Unit/FilesystemTest.php index f0a0fa3b8..8e6212466 100644 --- a/app/sprinkles/core/tests/Unit/FilesystemTest.php +++ b/app/sprinkles/core/tests/Unit/FilesystemTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Unit; diff --git a/app/sprinkles/core/tests/Unit/RouterTest.php b/app/sprinkles/core/tests/Unit/RouterTest.php index a55c99a01..534e5dfb1 100644 --- a/app/sprinkles/core/tests/Unit/RouterTest.php +++ b/app/sprinkles/core/tests/Unit/RouterTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Unit; diff --git a/app/sprinkles/core/tests/Unit/SprunjeTest.php b/app/sprinkles/core/tests/Unit/SprunjeTest.php index 3938f854b..7346f1eee 100644 --- a/app/sprinkles/core/tests/Unit/SprunjeTest.php +++ b/app/sprinkles/core/tests/Unit/SprunjeTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Unit; diff --git a/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php b/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php index 85f1e4196..0b6f69fbe 100644 --- a/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php +++ b/app/sprinkles/core/tests/Unit/TestDatabaseTraitTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Sprinkle\Core\Tests\Unit; diff --git a/app/system/Bakery/Bakery.php b/app/system/Bakery/Bakery.php index f21dbb992..7e5990ccf 100644 --- a/app/system/Bakery/Bakery.php +++ b/app/system/Bakery/Bakery.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System\Bakery; diff --git a/app/system/Bakery/BaseCommand.php b/app/system/Bakery/BaseCommand.php index 99ec1b554..f150d47fc 100644 --- a/app/system/Bakery/BaseCommand.php +++ b/app/system/Bakery/BaseCommand.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System\Bakery; diff --git a/app/system/Bakery/Migration.php b/app/system/Bakery/Migration.php index cd7d2dfe2..bc73c3c91 100644 --- a/app/system/Bakery/Migration.php +++ b/app/system/Bakery/Migration.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System\Bakery; diff --git a/app/system/Facade.php b/app/system/Facade.php index 98294fef4..4fd04d2e8 100644 --- a/app/system/Facade.php +++ b/app/system/Facade.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System; diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 8f6ca92b0..4e7af7034 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System; diff --git a/app/system/SlimAppEvent.php b/app/system/SlimAppEvent.php index 77f0aa901..65ca965f2 100644 --- a/app/system/SlimAppEvent.php +++ b/app/system/SlimAppEvent.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System; diff --git a/app/system/Sprinkle/Sprinkle.php b/app/system/Sprinkle/Sprinkle.php index b66e48862..5f2b3e264 100644 --- a/app/system/Sprinkle/Sprinkle.php +++ b/app/system/Sprinkle/Sprinkle.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System\Sprinkle; diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index 387ddde86..bc47e2dfb 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System\Sprinkle; diff --git a/app/system/UserFrosting.php b/app/system/UserFrosting.php index 3aca2d4c2..2c29cbb09 100644 --- a/app/system/UserFrosting.php +++ b/app/system/UserFrosting.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\System; diff --git a/app/tests/DatabaseTransactions.php b/app/tests/DatabaseTransactions.php index 7ac961dc0..74844837b 100644 --- a/app/tests/DatabaseTransactions.php +++ b/app/tests/DatabaseTransactions.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests; diff --git a/app/tests/TestCase.php b/app/tests/TestCase.php index 87d210a32..2ff5ca74b 100644 --- a/app/tests/TestCase.php +++ b/app/tests/TestCase.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests; diff --git a/app/tests/Unit/ExampleTest.php b/app/tests/Unit/ExampleTest.php index d0bae826a..69d4c75fc 100644 --- a/app/tests/Unit/ExampleTest.php +++ b/app/tests/Unit/ExampleTest.php @@ -3,7 +3,8 @@ * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ namespace UserFrosting\Tests\Unit; diff --git a/bakery b/bakery index 4d0348d12..9098d244c 100644 --- a/bakery +++ b/bakery @@ -10,10 +10,11 @@ * \___/|___/\___|_| \_| |_| \___/|___/\__|_|_| |_|\__, | * __/ | * |___/ - * http://www.userfrosting.com + * UserFrosting (http://www.userfrosting.com) * * @link https://github.com/userfrosting/UserFrosting - * @license https://github.com/userfrosting/UserFrosting/blob/master/licenses/UserFrosting.md (MIT License) + * @copyright Copyright (c) 2019 Alexander Weissman + * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ /** diff --git a/public/index.php b/public/index.php index 5cbc048a9..95b6f339b 100755 --- a/public/index.php +++ b/public/index.php @@ -1,10 +1,10 @@ Date: Sat, 12 Jan 2019 15:41:22 +1100 Subject: [PATCH 184/237] Update usefrosting/assets to v5 (semver alignment) and fixed #860 --- app/sprinkles/core/composer.json | 2 +- .../core/src/Util/RawAssetBundles.php | 137 +++++++++--------- 2 files changed, 66 insertions(+), 73 deletions(-) diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index 5421c9f37..158afeaa7 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -45,7 +45,7 @@ "slim/twig-view": "^1.2", "symfony/http-foundation": "*", "twig/twig": "^1.18", - "userfrosting/assets": "~4.2.0", + "userfrosting/assets": "^5.0.0", "userfrosting/config": "~4.2.0", "userfrosting/cache": "~4.1.0", "userfrosting/fortress": "~4.1.1", diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index f8f33915c..cba3b4d87 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -36,85 +36,78 @@ public function extend($filePath) } // Read file - $bundlesFile = $this->readSchema($filePath); + $schema = $this->readSchema($filePath, true); + + // Abort if no bundle is specified + if ($schema['bundle'] === null) { + return; + } // Process bundles - if (isset($bundlesFile->bundle)) { - foreach ($bundlesFile->bundle as $bundleName => $bundle) { - // Get collision setting. - $collisionRule = isset($bundle->options->sprinkle->onCollision) ? $bundle->options->sprinkle->onCollision : 'replace'; + foreach ($schema['bundle'] as $bundleName => $_) { + + // Get collision setting. + $collisionRule = $schema["bundle.$bundleName.options.sprinkle.onCollision"] ?: 'replace'; - // Handle CSS bundle if specified. - if (isset($bundle->styles)) { - // Attempt to add CSS bundle - try { - $standardisedBundle = $this->standardiseBundle($bundle->styles); - if (!array_key_exists($bundleName, $this->cssBundles)) { - $this->cssBundles[$bundleName] = $standardisedBundle; - } else { - switch ($collisionRule) { - case 'replace': - // Replaces the existing bundle. - $this->cssBundles[$bundleName] = $standardisedBundle; - break; - case 'merge': - // Merge with existing bundle. - foreach ($standardisedBundle as $assetPath) { - if (!in_array($assetPath, $this->cssBundles[$bundleName])) { - $this->cssBundles[$bundleName][] = $assetPath; - } - } - break; - case 'ignore': - break; - case 'error': - throw new \ErrorException("The bundle '$bundleName' is already defined."); - break; - default: - throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); - break; - } - } - } catch (\Exception $e) { - throw new InvalidBundlesFileException("Encountered issue processing styles property for '$bundleName' for file '$filePath'", 0, $e); - } + // Handle CSS bundle + $styles = $schema["bundle.$bundleName.styles"]; + if ($styles !== null) { + // Attempt to add CSS bundle + try { + $this->addWithCollisionRule($styles, $bundleName, $collisionRule, $this->cssBundles); + } catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing styles property for '$bundleName' for file '$filePath'", 0, $e); } + } - // Handle JS bundle if specified. - if (isset($bundle->scripts)) { - // Attempt to add JS bundle - try { - $standardisedBundle = $this->standardiseBundle($bundle->scripts); - if (!array_key_exists($bundleName, $this->jsBundles)) { - $this->jsBundles[$bundleName] = $standardisedBundle; - } else { - switch ($collisionRule) { - case 'replace': - // Replaces the existing bundle. - $this->jsBundles[$bundleName] = $standardisedBundle; - break; - case 'merge': - // Merge with existing bundle. - foreach ($standardisedBundle as $assetPath) { - if (!in_array($assetPath, $this->jsBundles[$bundleName])) { - $this->jsBundles[$bundleName][] = $assetPath; - } - } - break; - case 'ignore': - break; - case 'error': - throw new \ErrorException("The bundle '$bundleName' is already defined."); - break; - default: - throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); - break; - } + // Handle JS bundle + $scripts = $schema["bundle.$bundleName.scripts"]; + if ($scripts !== null) { + // Attempt to add JS bundle + try { + $this->addWithCollisionRule($scripts, $bundleName, $collisionRule, $this->jsBundles); + } catch (\Exception $e) { + throw new InvalidBundlesFileException("Encountered issue processing scripts property for '$bundleName' for file '$filePath'", 0, $e); + } + } + } + } + + /** + * Adds provided bundle to provided bundle store with collision rule respected. + * @param string|string[] $bundle Bundle to add. + * @param string $name Name of bundle provided. + * @param string $collisionRule Rule to apply if collision is detected. + * @param string[string][] $bundleStore Place to add bundles (CSS or JS depending on provided store). + * @throws \ErrorException if collision rule is 'error' and bundle is already defined. + * @throws \OutOfBoundsException if an invalid collision rule is provided. + */ + protected function addWithCollisionRule(&$bundle, $bundleName, $collisionRule, &$bundleStore) { + $standardisedBundle = $this->standardiseBundle($bundle); + if (!array_key_exists($bundleName, $bundleStore)) { + $bundleStore[$bundleName] = $standardisedBundle; + } else { + switch ($collisionRule) { + case 'replace': + // Replaces the existing bundle. + $bundleStore[$bundleName] = $standardisedBundle; + break; + case 'merge': + // Merge with existing bundle. + foreach ($standardisedBundle as $assetPath) { + if (!in_array($assetPath, $bundleStore[$bundleName])) { + $bundleStore[$bundleName][] = $assetPath; } - } catch (\Exception $e) { - throw new InvalidBundlesFileException("Encountered issue processing scripts property for '$bundleName' for file '$filePath'", 0, $e); } - } + break; + case 'ignore': + break; + case 'error': + throw new \ErrorException("The bundle '$bundleName' is already defined."); + break; + default: + throw new \OutOfBoundsException("Invalid value '$collisionRule' provided for 'onCollision' key in bundle '$bundleName'."); + break; } } } From 4822f1440f4ea1b42bd19871206a27c9e135a512 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 12 Jan 2019 16:28:05 +1100 Subject: [PATCH 185/237] Fix for #920 and potentially dodgy node dependencies lockfile --- .gitignore | 1 + app/sprinkles/core/src/Bakery/BuildAssets.php | 23 +++++++++++++++---- build/.npmrc | 1 + build/gulpfile.esm.js | 11 +++++++-- 4 files changed, 29 insertions(+), 7 deletions(-) create mode 100644 build/.npmrc diff --git a/.gitignore b/.gitignore index 329be784a..6a6137dbc 100644 --- a/.gitignore +++ b/.gitignore @@ -74,3 +74,4 @@ vagrant/Homestead/ # Igore npm lockfile build/package-lock.json +build/package.lock diff --git a/app/sprinkles/core/src/Bakery/BuildAssets.php b/app/sprinkles/core/src/Bakery/BuildAssets.php index cc5cfccb2..474157275 100644 --- a/app/sprinkles/core/src/Bakery/BuildAssets.php +++ b/app/sprinkles/core/src/Bakery/BuildAssets.php @@ -89,26 +89,39 @@ protected function npmInstall($force) $wd = getcwd(); chdir($this->buildPath); + // Delete troublesome package-lock.json + if (file_exists('package-lock.json')) unlink('package-lock.json'); + // Skip if lockfile indicates previous run - if (!$force && file_exists('package-lock.json') && filemtime('package.json') < filemtime('package-lock.json') - 1) { + if (!$force && file_exists('package.lock') && filemtime('package.json') < filemtime('package.lock') - 1) { $this->io->writeln('> Skipping as package-lock.json age indicates dependencies are already installed'); chdir($wd); return; } + // Ensure extraneous dependencies are cleared out $exitCode = 0; - passthru('npm install', $exitCode); + passthru('npm prune'); - // Ensure lockfile last-modified date is updated - touch('package-lock.json'); + if ($exitCode !== 0) { + $this->io->error('npm dependency installation has failed'); + exit(1); + } - chdir($wd); + // Install the new dependencies + $exitCode = 0; + passthru('npm install', $exitCode); if ($exitCode !== 0) { $this->io->error('npm dependency installation has failed'); exit(1); } + + // Update lockfile date (for skip logic) + touch('package.lock'); + + chdir($wd); } /** diff --git a/build/.npmrc b/build/.npmrc new file mode 100644 index 000000000..43c97e719 --- /dev/null +++ b/build/.npmrc @@ -0,0 +1 @@ +package-lock=false diff --git a/build/gulpfile.esm.js b/build/gulpfile.esm.js index 540688911..85b947097 100644 --- a/build/gulpfile.esm.js +++ b/build/gulpfile.esm.js @@ -74,8 +74,9 @@ export async function assetsInstall() { // Install npm dependencies Logger("Installing vendor assets with NPM...") - // Remove package.json (package-lock.json can be left untouched as dates will invalidate it) + // Remove package.json and package-lock.json (if it happens to exist) deleteSync(vendorAssetsDir + "package.json", { force: true }); + deleteSync(vendorAssetsDir + "package-lock.json", { force: true }); // Generate package.json const npmTemplate = { @@ -86,8 +87,14 @@ export async function assetsInstall() { const pkg = mergeNpmDeps(npmTemplate, npmPaths, vendorAssetsDir, doILog); Logger("Dependency collation complete."); + // Remove any existing unneeded dependencies + Logger("Running npm prune (using npm from PATH)"); + execSync("npm prune", { + cwd: vendorAssetsDir, + stdio: doILog ? "inherit" : "" + }); + // Perform installation - // NPM will automatically remove extraneous packages (barring algorithm failure) during install Logger("Running npm install (using npm from PATH)"); execSync("npm install", { cwd: vendorAssetsDir, From 221ac19d404a81ff95ad658d094fb5ec542a2d9d Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sun, 13 Jan 2019 18:30:53 -0500 Subject: [PATCH 186/237] Updated Dependencies --- app/sprinkles/core/composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/sprinkles/core/composer.json b/app/sprinkles/core/composer.json index 158afeaa7..72346e742 100644 --- a/app/sprinkles/core/composer.json +++ b/app/sprinkles/core/composer.json @@ -47,12 +47,12 @@ "twig/twig": "^1.18", "userfrosting/assets": "^5.0.0", "userfrosting/config": "~4.2.0", - "userfrosting/cache": "~4.1.0", - "userfrosting/fortress": "~4.1.1", - "userfrosting/i18n": "~4.1.0", + "userfrosting/cache": "~4.2.0", + "userfrosting/fortress": "~4.2.0", + "userfrosting/i18n": "~4.2.0", "userfrosting/uniformresourcelocator": "~4.2.0", - "userfrosting/session": "~4.1.0", - "userfrosting/support": "~4.1.1", + "userfrosting/session": "~4.2.0", + "userfrosting/support": "~4.2.0", "vlucas/phpdotenv": "^2" }, "autoload": { From 82b7be1849ce58524588e8997fb0315bb56b3d2c Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Tue, 15 Jan 2019 07:15:20 +1100 Subject: [PATCH 187/237] docs: update `README.md` with statuses of master and develop --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5721acb77..db79301c1 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,16 @@ [![Latest Version](https://img.shields.io/github/release/userfrosting/UserFrosting.svg)](https://github.com/userfrosting/UserFrosting/releases) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE.md) -[![Build Status](https://travis-ci.org/userfrosting/UserFrosting.svg?branch=master)](https://travis-ci.org/userfrosting/UserFrosting) -[![codecov](https://codecov.io/gh/userfrosting/userfrosting/branch/master/graph/badge.svg)](https://codecov.io/gh/userfrosting/userfrosting) [![Join the chat at https://chat.userfrosting.com/channel/support](https://demo.rocket.chat/images/join-chat.svg)](https://chat.userfrosting.com/channel/support) [![Backers on Open Collective](https://opencollective.com/userfrosting/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/userfrosting/sponsors/badge.svg)](#sponsors) [![Donate](https://img.shields.io/badge/Open%20Collective-Donate-blue.svg)](https://opencollective.com/userfrosting#backer) +| Branch | Status | +| ------ | ------ | +| master | [![Build Status](https://travis-ci.org/userfrosting/UserFrosting.svg?branch=master)](https://travis-ci.org/userfrosting/UserFrosting) [![codecov](https://codecov.io/gh/userfrosting/userfrosting/branch/master/graph/badge.svg)](https://codecov.io/gh/userfrosting/userfrosting/branch/master) | +| develop | [![Build Status](https://travis-ci.org/userfrosting/UserFrosting.svg?branch=develop)](https://travis-ci.org/userfrosting/UserFrosting) [![codecov](https://codecov.io/gh/userfrosting/userfrosting/branch/develop/graph/badge.svg)](https://codecov.io/gh/userfrosting/userfrosting/branch/develop) | + [https://www.userfrosting.com](https://www.userfrosting.com) If you simply want to show that you like this project, or want to remember it for later, you should **star**, not **fork**, this repository. Forking is only for when you are ready to create your own copy of the code to work on. From 145dd4b22e26fca613dda8e26db5ae41436102d1 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Tue, 15 Jan 2019 07:16:22 +1100 Subject: [PATCH 188/237] docs: updated Jordan's bio in `README.md` --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db79301c1..8c14f009a 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Louis's a civil engineer in Montréal, Québec who also has a passion for coding ### Jordan Mele -Jordan's a former developer of Mayvin Training and a student studying Computer Science at the University of Wollongong, Australia. His passion is creating software-based solutions to overcomplicated problems, while keeping the user in control. +Jordan's an Australian PHP Developer at [4mation](https://www.4mation.com.au) in Surry Hills, NSW. His passion is creating simple yet intuitive software-based solutions for problems that would otherwise be tedious and overcomplicated to address, while keeping the user in control. ### Sarah Baghdadi From fddecb46635c36c90ee636af82fd31d5af259475 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 15 Jan 2019 20:26:16 -0500 Subject: [PATCH 189/237] Ignore untestable files in code coverage (#924) --- phpunit.xml | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/phpunit.xml b/phpunit.xml index 192eb2cd3..044b4fe72 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -23,13 +23,8 @@ - app/ - public/index.php - - app/vendor/ - app/tests/ - app/sprinkles/*/tests/ - + app/sprinkles/*/src/ + app/system/ From 91c0c683ad4d1732957e9c3c9cdff0c1aca7ad80 Mon Sep 17 00:00:00 2001 From: Srinivas Date: Tue, 15 Jan 2019 21:11:35 -0600 Subject: [PATCH 190/237] Docker Changes 1. Upgraded docker-compose.yml to v 3.2 2. Added sample docker-compose.yml file for a 2nd test database 3. Added PHP configuration file (custom.ini) and added Zip module to PHP 4. Added client_max_body_size option to Nginx config. --- docker-compose-testdb.yml | 91 +++++++++++++++++++++++++++++++++++++++ docker-compose.yml | 55 ++++++++++++++--------- docker/nginx/Dockerfile | 3 +- docker/nginx/default.conf | 1 + docker/php/Dockerfile | 13 +++--- docker/php/custom.ini | 6 +++ 6 files changed, 142 insertions(+), 27 deletions(-) create mode 100644 docker-compose-testdb.yml create mode 100644 docker/php/custom.ini diff --git a/docker-compose-testdb.yml b/docker-compose-testdb.yml new file mode 100644 index 000000000..b40530c95 --- /dev/null +++ b/docker-compose-testdb.yml @@ -0,0 +1,91 @@ +version: "3.2" +services: + php: + restart: unless-stopped + tty: true + build: + context: ./docker/php + environment: + - DB_DRIVER=mysql + - DB_HOST=ufmysql + - DB_PORT=3306 + - DB_NAME=userfrosting + - DB_USER=docker + - DB_PASSWORD=secret + - DB_TEST_DRIVER=mysql + - DB_TEST_HOST=mysqltest + - DB_TEST_PORT=3306 + - DB_TEST_NAME=userfrosting_test + - DB_TEST_USER=docker + - DB_TEST_PASSWORD=secret + - TEST_DB=test_ufdb + volumes: + - .:/app + - ./docker/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini + networks: + - backend + nginx: + restart: unless-stopped + tty: true + ports: + - "8591:80" + - "8592:443" + build: + context: ./docker/nginx + volumes: + - .:/app + depends_on: + - php + - ufmysql + - ufmysqltest + networks: + - frontend + - backend + ufmysql: + image: mysql:5.7 + networks: + - backend + environment: + - MYSQL_DATABASE=userfrosting + - MYSQL_ROOT_PASSWORD=secret + - MYSQL_USER=docker + - MYSQL_PASSWORD=secret + ports: + - 8593:3306 + volumes: + - userfrosting-db:/var/lib/mysql + ufmysqltest: + image: mysql:5.7 + networks: + - backend + environment: + - MYSQL_DATABASE=userfrosting_test + - MYSQL_ROOT_PASSWORD=secret + - MYSQL_USER=docker + - MYSQL_PASSWORD=secret + ports: + - 8594:3306 + volumes: + - userfrosting-test-db:/var/lib/mysql + composer: + image: "composer" + volumes: + - .:/app + working_dir: /app + command: -V + node: + image: node:alpine + build: + context: ./docker/node + volumes: + - .:/app + working_dir: /app/build + command: npm run uf-assets-install +volumes: + userfrosting-db: + driver: local + userfrosting-test-db: + driver: local +networks: + frontend: + backend: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 932a1c0f6..b5dc75645 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,44 +1,55 @@ -version: '2' +version: "3.2" services: php: + restart: unless-stopped + tty: true build: context: ./docker/php environment: - DB_DRIVER=mysql - - DB_HOST=mysql + - DB_HOST=ufmysql - DB_PORT=3306 - DB_NAME=userfrosting - - DB_USER=userfrosting - - DB_PASSWORD=password + - DB_USER=docker + - DB_PASSWORD=secret volumes: - .:/app - links: - - mysql + - ./docker/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini + networks: + - backend nginx: + restart: unless-stopped + tty: true + ports: + - "8591:80" + - "8592:443" build: context: ./docker/nginx - ports: - - 8570:80 volumes: - .:/app - links: + depends_on: - php - mysql: + - ufmysql + networks: + - frontend + - backend + ufmysql: image: mysql:5.7 + networks: + - backend environment: - MYSQL_DATABASE=userfrosting - - MYSQL_ROOT_PASSWORD=root - - MYSQL_USER=userfrosting - - MYSQL_PASSWORD=password + - MYSQL_ROOT_PASSWORD=secret + - MYSQL_USER=docker + - MYSQL_PASSWORD=secret ports: - - 8571:3306 + - 8593:3306 volumes: - userfrosting-db:/var/lib/mysql - composer: - image: composer/composer - volumes_from: - - php + image: "composer" + volumes: + - .:/app working_dir: /app command: -V @@ -46,11 +57,15 @@ services: image: node:alpine build: context: ./docker/node - volumes_from: - - php + volumes: + - .:/app working_dir: /app/build command: npm run uf-assets-install volumes: userfrosting-db: + driver: local +networks: + frontend: + backend: diff --git a/docker/nginx/Dockerfile b/docker/nginx/Dockerfile index 7d2fbc3cc..be54539ba 100644 --- a/docker/nginx/Dockerfile +++ b/docker/nginx/Dockerfile @@ -1,2 +1,3 @@ FROM nginx:alpine -COPY default.conf /etc/nginx/conf.d/default.conf +RUN rm /etc/nginx/conf.d/default.conf +COPY default.conf /etc/nginx/conf.d/default.conf \ No newline at end of file diff --git a/docker/nginx/default.conf b/docker/nginx/default.conf index 8ae7bb820..5241476a0 100644 --- a/docker/nginx/default.conf +++ b/docker/nginx/default.conf @@ -25,4 +25,5 @@ server { index index.php; try_files $uri /index.php?$query_string; } + client_max_body_size 100M; } diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index c5b8a9eb2..c85e87089 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -1,11 +1,12 @@ FROM php:7.2-fpm RUN apt-get update && apt-get install -y \ - libfreetype6-dev \ - libjpeg62-turbo-dev \ - libpng-dev \ + libfreetype6-dev \ + libjpeg62-turbo-dev \ + libpng-dev \ + zip \ && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-install -j$(nproc) gd \ - && docker-php-ext-install -j$(nproc) pdo pdo_mysql + && docker-php-ext-install -j$(nproc) pdo pdo_mysql \ + && docker-php-ext-install -j$(nproc) zip RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer - -WORKDIR /app +WORKDIR /app \ No newline at end of file diff --git a/docker/php/custom.ini b/docker/php/custom.ini new file mode 100644 index 000000000..9de5b8415 --- /dev/null +++ b/docker/php/custom.ini @@ -0,0 +1,6 @@ +file_uploads = On +memory_limit = 64M +upload_max_filesize = 64M +post_max_size = 64M +max_execution_time = 600 +memory_limit=512M \ No newline at end of file From 3795c1e29eea8a311ab63aac9d035fe2727fcc94 Mon Sep 17 00:00:00 2001 From: Jordan Date: Mon, 21 Jan 2019 15:48:04 +1100 Subject: [PATCH 191/237] Prevent caching of API routes with dynamic content (#922) Prevent caching of routes with dynamic content --- app/sprinkles/account/routes/routes.php | 4 ++- app/sprinkles/admin/routes/activities.php | 6 ++-- app/sprinkles/admin/routes/admin.php | 8 +++-- app/sprinkles/admin/routes/groups.php | 8 +++-- app/sprinkles/admin/routes/permissions.php | 6 ++-- app/sprinkles/admin/routes/roles.php | 8 +++-- app/sprinkles/admin/routes/users.php | 8 +++-- .../src/Controller/PermissionController.php | 4 +-- .../admin/src/Controller/UserController.php | 4 +-- app/sprinkles/core/routes/routes.php | 5 ++- app/sprinkles/core/src/Bakery/BuildAssets.php | 4 ++- app/sprinkles/core/src/Util/NoCache.php | 36 +++++++++++++++++++ .../core/src/Util/RawAssetBundles.php | 15 ++++---- 13 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 app/sprinkles/core/src/Util/NoCache.php diff --git a/app/sprinkles/account/routes/routes.php b/app/sprinkles/account/routes/routes.php index 1fa5c3b5d..bb89382b7 100644 --- a/app/sprinkles/account/routes/routes.php +++ b/app/sprinkles/account/routes/routes.php @@ -7,6 +7,8 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ +use UserFrosting\Sprinkle\Core\Util\NoCache; + $app->group('/account', function () { $this->get('/captcha', 'UserFrosting\Sprinkle\Account\Controller\AccountController:imageCaptcha'); @@ -55,6 +57,6 @@ $this->post('/settings/profile', 'UserFrosting\Sprinkle\Account\Controller\AccountController:profile') ->add('authGuard'); -}); +})->add(new NoCache()); $app->get('/modals/account/tos', 'UserFrosting\Sprinkle\Account\Controller\AccountController:getModalAccountTos'); diff --git a/app/sprinkles/admin/routes/activities.php b/app/sprinkles/admin/routes/activities.php index 2e59c21c5..a68646556 100644 --- a/app/sprinkles/admin/routes/activities.php +++ b/app/sprinkles/admin/routes/activities.php @@ -7,14 +7,16 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ +use UserFrosting\Sprinkle\Core\Util\NoCache; + /** * Routes for administrative activity monitoring. */ $app->group('/activities', function () { $this->get('', 'UserFrosting\Sprinkle\Admin\Controller\ActivityController:pageList') ->setName('uri_activities'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/api/activities', function () { $this->get('', 'UserFrosting\Sprinkle\Admin\Controller\ActivityController:getList'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); diff --git a/app/sprinkles/admin/routes/admin.php b/app/sprinkles/admin/routes/admin.php index 1cac8c32f..dd5baee99 100644 --- a/app/sprinkles/admin/routes/admin.php +++ b/app/sprinkles/admin/routes/admin.php @@ -7,18 +7,20 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ +use UserFrosting\Sprinkle\Core\Util\NoCache; + /** * Routes for administrative panel management. */ $app->group('/dashboard', function () { $this->get('', 'UserFrosting\Sprinkle\Admin\Controller\AdminController:pageDashboard') ->setName('dashboard'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/api/dashboard', function () { $this->post('/clear-cache', 'UserFrosting\Sprinkle\Admin\Controller\AdminController:clearCache'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/modals/dashboard', function () { $this->get('/clear-cache', 'UserFrosting\Sprinkle\Admin\Controller\AdminController:getModalConfirmClearCache'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); diff --git a/app/sprinkles/admin/routes/groups.php b/app/sprinkles/admin/routes/groups.php index 40e1d0357..a4841a467 100644 --- a/app/sprinkles/admin/routes/groups.php +++ b/app/sprinkles/admin/routes/groups.php @@ -7,6 +7,8 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ +use UserFrosting\Sprinkle\Core\Util\NoCache; + /** * Routes for administrative group management. */ @@ -15,7 +17,7 @@ ->setName('uri_groups'); $this->get('/g/{slug}', 'UserFrosting\Sprinkle\Admin\Controller\GroupController:pageInfo'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/api/groups', function () { $this->delete('/g/{slug}', 'UserFrosting\Sprinkle\Admin\Controller\GroupController:delete'); @@ -29,7 +31,7 @@ $this->post('', 'UserFrosting\Sprinkle\Admin\Controller\GroupController:create'); $this->put('/g/{slug}', 'UserFrosting\Sprinkle\Admin\Controller\GroupController:updateInfo'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/modals/groups', function () { $this->get('/confirm-delete', 'UserFrosting\Sprinkle\Admin\Controller\GroupController:getModalConfirmDelete'); @@ -37,4 +39,4 @@ $this->get('/create', 'UserFrosting\Sprinkle\Admin\Controller\GroupController:getModalCreate'); $this->get('/edit', 'UserFrosting\Sprinkle\Admin\Controller\GroupController:getModalEdit'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); diff --git a/app/sprinkles/admin/routes/permissions.php b/app/sprinkles/admin/routes/permissions.php index a543a3a76..9f6871beb 100644 --- a/app/sprinkles/admin/routes/permissions.php +++ b/app/sprinkles/admin/routes/permissions.php @@ -7,6 +7,8 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ +use UserFrosting\Sprinkle\Core\Util\NoCache; + /** * Routes for administrative permission management. */ @@ -15,7 +17,7 @@ ->setName('uri_permissions'); $this->get('/p/{id}', 'UserFrosting\Sprinkle\Admin\Controller\PermissionController:pageInfo'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/api/permissions', function () { $this->get('', 'UserFrosting\Sprinkle\Admin\Controller\PermissionController:getList'); @@ -23,4 +25,4 @@ $this->get('/p/{id}', 'UserFrosting\Sprinkle\Admin\Controller\PermissionController:getInfo'); $this->get('/p/{id}/users', 'UserFrosting\Sprinkle\Admin\Controller\PermissionController:getUsers'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); diff --git a/app/sprinkles/admin/routes/roles.php b/app/sprinkles/admin/routes/roles.php index b1a1400b8..efcd21704 100644 --- a/app/sprinkles/admin/routes/roles.php +++ b/app/sprinkles/admin/routes/roles.php @@ -7,6 +7,8 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ +use UserFrosting\Sprinkle\Core\Util\NoCache; + /** * Routes for administrative role management. */ @@ -15,7 +17,7 @@ ->setName('uri_roles'); $this->get('/r/{slug}', 'UserFrosting\Sprinkle\Admin\Controller\RoleController:pageInfo'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/api/roles', function () { $this->delete('/r/{slug}', 'UserFrosting\Sprinkle\Admin\Controller\RoleController:delete'); @@ -33,7 +35,7 @@ $this->put('/r/{slug}', 'UserFrosting\Sprinkle\Admin\Controller\RoleController:updateInfo'); $this->put('/r/{slug}/{field}', 'UserFrosting\Sprinkle\Admin\Controller\RoleController:updateField'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/modals/roles', function () { $this->get('/confirm-delete', 'UserFrosting\Sprinkle\Admin\Controller\RoleController:getModalConfirmDelete'); @@ -43,4 +45,4 @@ $this->get('/edit', 'UserFrosting\Sprinkle\Admin\Controller\RoleController:getModalEdit'); $this->get('/permissions', 'UserFrosting\Sprinkle\Admin\Controller\RoleController:getModalEditPermissions'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); diff --git a/app/sprinkles/admin/routes/users.php b/app/sprinkles/admin/routes/users.php index 1f3e581b1..0bcdbabd6 100644 --- a/app/sprinkles/admin/routes/users.php +++ b/app/sprinkles/admin/routes/users.php @@ -7,6 +7,8 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ +use UserFrosting\Sprinkle\Core\Util\NoCache; + /** * Routes for administrative user management. */ @@ -15,7 +17,7 @@ ->setName('uri_users'); $this->get('/u/{user_name}', 'UserFrosting\Sprinkle\Admin\Controller\UserController:pageInfo'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/api/users', function () { $this->delete('/u/{user_name}', 'UserFrosting\Sprinkle\Admin\Controller\UserController:delete'); @@ -37,7 +39,7 @@ $this->put('/u/{user_name}', 'UserFrosting\Sprinkle\Admin\Controller\UserController:updateInfo'); $this->put('/u/{user_name}/{field}', 'UserFrosting\Sprinkle\Admin\Controller\UserController:updateField'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); $app->group('/modals/users', function () { $this->get('/confirm-delete', 'UserFrosting\Sprinkle\Admin\Controller\UserController:getModalConfirmDelete'); @@ -49,4 +51,4 @@ $this->get('/password', 'UserFrosting\Sprinkle\Admin\Controller\UserController:getModalEditPassword'); $this->get('/roles', 'UserFrosting\Sprinkle\Admin\Controller\UserController:getModalEditRoles'); -})->add('authGuard'); +})->add('authGuard')->add(new NoCache()); diff --git a/app/sprinkles/admin/src/Controller/PermissionController.php b/app/sprinkles/admin/src/Controller/PermissionController.php index cfbb9e3ea..fd92d0da5 100644 --- a/app/sprinkles/admin/src/Controller/PermissionController.php +++ b/app/sprinkles/admin/src/Controller/PermissionController.php @@ -140,11 +140,9 @@ public function getUsers(Request $request, Response $response, $args) $sprunje = $classMapper->createInstance('permission_user_sprunje', $classMapper, $params); - $response = $sprunje->toResponse($response); - // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content. // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating). - return $response; + return $sprunje->toResponse($response); } /** diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index aa7ec0b5e..0b12fac7e 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -834,11 +834,9 @@ public function getPermissions(Request $request, Response $response, $args) $params['user_id'] = $user->id; $sprunje = $classMapper->createInstance('user_permission_sprunje', $classMapper, $params); - $response = $sprunje->toResponse($response); - // Be careful how you consume this data - it has not been escaped and contains untrusted user-supplied content. // For example, if you plan to insert it into an HTML DOM, you must escape it on the client side (or use client-side templating). - return $response; + return $sprunje->toResponse($response); } /** diff --git a/app/sprinkles/core/routes/routes.php b/app/sprinkles/core/routes/routes.php index b29e0b3eb..9953af940 100755 --- a/app/sprinkles/core/routes/routes.php +++ b/app/sprinkles/core/routes/routes.php @@ -7,6 +7,8 @@ * @license https://github.com/userfrosting/UserFrosting/blob/master/LICENSE.md (MIT License) */ +use UserFrosting\Sprinkle\Core\Util\NoCache; + global $app; $config = $app->getContainer()->get('config'); @@ -16,7 +18,8 @@ $app->get('/about', 'UserFrosting\Sprinkle\Core\Controller\CoreController:pageAbout')->add('checkEnvironment'); -$app->get('/alerts', 'UserFrosting\Sprinkle\Core\Controller\CoreController:jsonAlerts'); +$app->get('/alerts', 'UserFrosting\Sprinkle\Core\Controller\CoreController:jsonAlerts') + ->add(new NoCache()); $app->get('/legal', 'UserFrosting\Sprinkle\Core\Controller\CoreController:pageLegal'); diff --git a/app/sprinkles/core/src/Bakery/BuildAssets.php b/app/sprinkles/core/src/Bakery/BuildAssets.php index 474157275..c3a2d66f5 100644 --- a/app/sprinkles/core/src/Bakery/BuildAssets.php +++ b/app/sprinkles/core/src/Bakery/BuildAssets.php @@ -90,7 +90,9 @@ protected function npmInstall($force) chdir($this->buildPath); // Delete troublesome package-lock.json - if (file_exists('package-lock.json')) unlink('package-lock.json'); + if (file_exists('package-lock.json')) { + unlink('package-lock.json'); + } // Skip if lockfile indicates previous run if (!$force && file_exists('package.lock') && filemtime('package.json') < filemtime('package.lock') - 1) { diff --git a/app/sprinkles/core/src/Util/NoCache.php b/app/sprinkles/core/src/Util/NoCache.php new file mode 100644 index 000000000..36c05f7a0 --- /dev/null +++ b/app/sprinkles/core/src/Util/NoCache.php @@ -0,0 +1,36 @@ +withHeader('Cache-Control', 'no-store'); + + return $next($request, $response); + } +} diff --git a/app/sprinkles/core/src/Util/RawAssetBundles.php b/app/sprinkles/core/src/Util/RawAssetBundles.php index d087acc67..9a303bc8f 100644 --- a/app/sprinkles/core/src/Util/RawAssetBundles.php +++ b/app/sprinkles/core/src/Util/RawAssetBundles.php @@ -46,7 +46,7 @@ public function extend($filePath) // Process bundles foreach ($schema['bundle'] as $bundleName => $_) { - + // Get collision setting. $collisionRule = $schema["bundle.$bundleName.options.sprinkle.onCollision"] ?: 'replace'; @@ -76,14 +76,15 @@ public function extend($filePath) /** * Adds provided bundle to provided bundle store with collision rule respected. - * @param string|string[] $bundle Bundle to add. - * @param string $name Name of bundle provided. - * @param string $collisionRule Rule to apply if collision is detected. - * @param string[string][] $bundleStore Place to add bundles (CSS or JS depending on provided store). - * @throws \ErrorException if collision rule is 'error' and bundle is already defined. + * @param string|string[] $bundle Bundle to add. + * @param string $name Name of bundle provided. + * @param string $collisionRule Rule to apply if collision is detected. + * @param string[string][] $bundleStore Place to add bundles (CSS or JS depending on provided store). + * @throws \ErrorException if collision rule is 'error' and bundle is already defined. * @throws \OutOfBoundsException if an invalid collision rule is provided. */ - protected function addWithCollisionRule(&$bundle, $bundleName, $collisionRule, &$bundleStore) { + protected function addWithCollisionRule(&$bundle, $bundleName, $collisionRule, &$bundleStore) + { $standardisedBundle = $this->standardiseBundle($bundle); if (!array_key_exists($bundleName, $bundleStore)) { $bundleStore[$bundleName] = $standardisedBundle; From f9bf15321b88ffe21cfa9189e30b900bc3a31278 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 21 Jan 2019 11:50:47 -0500 Subject: [PATCH 192/237] SprinkleManager & Bakery Test improvements. (#928) --- CHANGELOG.md | 23 +- .../core/src/Bakery/DebugCommand.php | 24 +- .../core/src/Bakery/RouteListCommand.php | 6 +- .../core/src/Bakery/SprinkleListCommand.php | 60 +++++ app/sprinkles/core/src/Bakery/Test.php | 98 ++++++- app/system/Sprinkle/SprinkleManager.php | 142 ++++++++-- app/tests/Unit/SprinkleManagerTest.php | 253 ++++++++++++++++++ app/tests/Unit/data/bar/.gitkeep | 0 app/tests/Unit/data/foo/.gitkeep | 0 app/tests/Unit/data/sprinkles-bad.json | 7 + app/tests/Unit/data/sprinkles-duplicate.json | 11 + app/tests/Unit/data/sprinkles.json | 10 + app/tests/Unit/data/sprinkles.txt | 10 + app/tests/Unit/data/test/.gitkeep | 0 14 files changed, 596 insertions(+), 48 deletions(-) create mode 100644 app/sprinkles/core/src/Bakery/SprinkleListCommand.php create mode 100644 app/tests/Unit/SprinkleManagerTest.php create mode 100644 app/tests/Unit/data/bar/.gitkeep create mode 100644 app/tests/Unit/data/foo/.gitkeep create mode 100644 app/tests/Unit/data/sprinkles-bad.json create mode 100644 app/tests/Unit/data/sprinkles-duplicate.json create mode 100644 app/tests/Unit/data/sprinkles.json create mode 100644 app/tests/Unit/data/sprinkles.txt create mode 100644 app/tests/Unit/data/test/.gitkeep diff --git a/CHANGELOG.md b/CHANGELOG.md index 713df9e44..56396bb51 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,28 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). -## 4.2.0 +## 4.2.0-beta.2 + +### Added +- Added `sprinkle:list` bakery command +- Changed the sprinkle list in the bakery `debug` command to use the new `sprinkle:list` table + +### Fix +- Fix for `Test` Bakery command + - Added `coverage-format` and `coverage-path` options to `test` Bakery command + - Sprinkle Testscope is now case insensitive + - **Class testscope now relative to `/` instead of `/UserFrosting/Sprinkle/` for more intuitive usage and to enable testing of non sprinkle tests** + - Detect and use the sprinkle `phpunit.xml` config when testing a specific sprinkle +- SprinkleManager Improvements : + - Added public `getSprinklePath` method to get path to the sprinkle directory + - Added public `getSprinkleClassNamespace` method to get sprinkle base namespace + - Added public `getSprinkle` method. Returns the sprinkle name as formatted in `sprinkles.json` file, independent of the case of the search argument. + - Public `isAvailable` method now case insensitive. + - Added public `getSprinklesPath` & `setSprinklesPath` to return or set the path to the sprinkle dir (`app/sprinkles/`) + - Added `JsonException` if `sprinkles.json` doesn't contain valid json. + - Added specific tests for sprinkleManager with 100% test coverage + +## 4.2.0-beta.1 ### Changed Requirements - Changed minimum Node.js version to **v10.12.0** diff --git a/app/sprinkles/core/src/Bakery/DebugCommand.php b/app/sprinkles/core/src/Bakery/DebugCommand.php index 45ba42e76..ba72a5b6b 100644 --- a/app/sprinkles/core/src/Bakery/DebugCommand.php +++ b/app/sprinkles/core/src/Bakery/DebugCommand.php @@ -54,7 +54,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->checkPhpVersion(); $this->checkNodeVersion(); $this->checkNpmVersion(); - $this->listSprinkles(); + $this->listSprinkles($input, $output); $this->showConfig(); $this->checkDatabase(); @@ -83,23 +83,27 @@ protected function checkPhpVersion() /** * List all sprinkles defined in the Sprinkles schema file, * making sure this file exist at the same time + * + * @param InputInterface $input + * @param OutputInterface $output */ - protected function listSprinkles() + protected function listSprinkles(InputInterface $input, OutputInterface $output) { // Check for Sprinkles schema file $path = \UserFrosting\SPRINKLES_SCHEMA_FILE; - $sprinklesFile = @file_get_contents($path); - if ($sprinklesFile === false) { + if (@file_exists($path) === false) { $this->io->error("The file `$path` not found."); } // List installed sprinkles - $sprinkles = json_decode($sprinklesFile)->base; - $this->io->section('Loaded sprinkles'); - $this->io->listing($sprinkles); + $command = $this->getApplication()->find('sprinkle:list'); + $command->run($input, $output); + + /** @var \UserFrosting\System\Sprinkle\SprinkleManager $sprinkleManager */ + $sprinkleManager = $this->ci->sprinkleManager; // Throw fatal error if the `core` sprinkle is missing - if (!in_array('core', $sprinkles)) { + if (!$sprinkleManager->isAvailable('core')) { $this->io->error("The `core` sprinkle is missing from the 'sprinkles.json' file."); exit(1); } @@ -111,7 +115,7 @@ protected function listSprinkles() */ protected function checkDatabase() { - $this->io->section('Testing database connection...'); + $this->io->title('Testing database connection...'); try { $this->testDB(); @@ -134,7 +138,7 @@ protected function showConfig() $config = $this->ci->config; // Display database info - $this->io->section('Database config'); + $this->io->title('Database config'); $this->io->writeln([ 'DRIVER : ' . $config['db.default.driver'], 'HOST : ' . $config['db.default.host'], diff --git a/app/sprinkles/core/src/Bakery/RouteListCommand.php b/app/sprinkles/core/src/Bakery/RouteListCommand.php index 5e03e34cc..6fc47410c 100644 --- a/app/sprinkles/core/src/Bakery/RouteListCommand.php +++ b/app/sprinkles/core/src/Bakery/RouteListCommand.php @@ -54,15 +54,15 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->io->title('Registered Routes'); // Get routes list - $this->routes = $this->ci->router->getRoutes(); + $routes = $this->ci->router->getRoutes(); // If not route, don't go further - if (count($this->routes) === 0) { + if (count($routes) === 0) { return $this->io->error("Your application doesn't have any routes."); } // Compile the routes into a displayable format - $routes = collect($this->routes)->map(function ($route) use ($input) { + $routes = collect($routes)->map(function ($route) use ($input) { return $this->getRouteInformation($route, $input); })->all(); diff --git a/app/sprinkles/core/src/Bakery/SprinkleListCommand.php b/app/sprinkles/core/src/Bakery/SprinkleListCommand.php new file mode 100644 index 000000000..1f902cbaa --- /dev/null +++ b/app/sprinkles/core/src/Bakery/SprinkleListCommand.php @@ -0,0 +1,60 @@ +setName('sprinkle:list') + ->setDescription('List all available sprinkles and their params'); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->io->title('Loaded Sprinkles'); + + /** @var \UserFrosting\System\Sprinkle\SprinkleManager $sprinkleManager */ + $sprinkleManager = $this->ci->sprinkleManager; + + // Get sprinkle list + $sprinkles = $sprinkleManager->getSprinkleNames(); + + // Compile the routes into a displayable format + $sprinklesTable = collect($sprinkles)->map(function ($sprinkle) use ($sprinkleManager) { + return [ + 'sprinkle' => $sprinkle, + 'namespace' => $sprinkleManager->getSprinkleClassNamespace($sprinkle), + 'path' => $sprinkleManager->getSprinklePath($sprinkle), + ]; + })->all(); + + // Display table + $this->io->table($this->headers, $sprinklesTable); + } +} diff --git a/app/sprinkles/core/src/Bakery/Test.php b/app/sprinkles/core/src/Bakery/Test.php index f8f112072..d5b2941e3 100644 --- a/app/sprinkles/core/src/Bakery/Test.php +++ b/app/sprinkles/core/src/Bakery/Test.php @@ -29,16 +29,23 @@ class Test extends BaseCommand */ protected $buildPath; + /** + * @var string + */ + protected $slashes = '\\'; + /** * {@inheritdoc} */ protected function configure() { $this->setName('test') - ->addOption('coverage', 'c', InputOption::VALUE_NONE, 'Generate code coverage report in HTML format. Will be saved in _meta/coverage') - ->addArgument('testscope', InputArgument::OPTIONAL, "Test Scope can either be a sprinkle name or a class formated as 'SprinkleName\Tests\TestClass` or 'SprinkleName\Tests\TestClass::method` (Optional)") + ->addOption('coverage', 'c', InputOption::VALUE_NONE, 'Enable code coverage report.') + ->addOption('coverage-format', null, InputOption::VALUE_REQUIRED, 'Select test coverage format. Choose from html, clover, crap4j, php, text, xml, etc. Default to HTML.') + ->addOption('coverage-path', null, InputOption::VALUE_REQUIRED, 'Code coverage report saving location. Default to `_meta/coverage`.') + ->addArgument('testscope', InputArgument::OPTIONAL, 'Test Scope can either be a sprinkle name or a test class (optional)') ->setDescription('Runs automated tests') - ->setHelp("Run PHP unit tests. Tests from a specific sprinkle can optionally be run using the 'testscope' argument (`php bakery test SprinkleName`). A specific test class can also be be run using the testscope argument (`php bakery test 'SprinkleName\Tests\TestClass'`), as a specific test method (`php bakery test 'SprinkleName\Tests\TestClass::method'`)."); + ->setHelp("Run PHP unit tests. Tests from a specific sprinkle can optionally be run using the 'testscope' argument (`php bakery test SprinkleName`). A specific test class can also be be run using the testscope argument (`php bakery test 'UserFrosting\Sprinkle\SprinkleName\Tests\TestClass'`), as a specific test method (`php bakery test 'UserFrosting\Sprinkle\SprinkleName\Tests\TestClass::method'`)."); } /** @@ -54,26 +61,93 @@ protected function execute(InputInterface $input, OutputInterface $output) $command .= ' -v'; } + // Process test scope $testscope = $input->getArgument('testscope'); if ($testscope) { - $slashes = '\\\\'; - if (strpos($testscope, '\\') !== false) { - $this->io->note("Executing Specified Test Scope : $testscope"); - $testscope = str_replace('\\', $slashes, $testscope); - $command .= " --filter='UserFrosting" . $slashes . 'Sprinkle' . $slashes . $testscope . "'"; + if (strpos($testscope, $this->slashes) !== false) { + $command .= $this->parseTestScope($testscope); } else { - $this->io->note("Executing all tests in Sprinkle '".Str::studly($testscope)."'"); - $command .= " --filter='UserFrosting" . $slashes . 'Sprinkle' . $slashes . Str::studly($testscope) . $slashes . 'Tests' . $slashes . "' "; + $command .= $this->parseSprinkleTestScope($testscope); } } // Add coverage report - if ($input->getOption('coverage')) { - $command .= ' --coverage-html _meta/coverage'; + if ($input->getOption('coverage') || $input->getOption('coverage-format') || $input->getOption('coverage-path')) { + $format = ($input->getOption('coverage-format')) ?: 'html'; + $path = ($input->getOption('coverage-path')) ?: '_meta/coverage'; + + switch ($format) { + case 'clover': + case 'xml': + case 'crap4j': + $path = $path . '/coverage.xml'; + break; + case 'php': + $path = $path . '/coverage.php'; + break; + case 'text': + $path = ''; + break; + case 'html': + default: + $file = ''; + break; + } + + $command .= " --coverage-$format $path"; } // Execute $this->io->writeln("> $command"); passthru($command); } + + /** + * Return the sprinkle test class + * + * @param string $testscope Testscope received from command line + * @return string + */ + protected function parseSprinkleTestScope($testscope) + { + /** @var \UserFrosting\System\Sprinkle\SprinkleManager $sprinkleManager */ + $sprinkleManager = $this->ci->sprinkleManager; + + // Get the Sprinkle name from the SprinkleManager, as we need the correct case + $sprinkle = $sprinkleManager->getSprinkle($testscope); + + // Make sure sprinkle exist + if (!$sprinkle) { + $this->io->error("Sprinkle $testscope not found"); + exit(1); + } + + $sprinkleName = Str::studly($sprinkle); + $this->io->note("Executing all tests for Sprinkle '$sprinkleName'"); + + // Check if sprinkle has phpunit.xml file + $phpunitConfig = $sprinkleManager->getSprinklePath($sprinkle) . \UserFrosting\DS . 'phpunit.xml'; + if (file_exists($phpunitConfig)) { + return " -c $phpunitConfig "; + } + + // Add command part + $testClass = $sprinkleManager->getSprinkleClassNamespace($sprinkleName) . "\Tests"; + $testClass = str_replace($this->slashes, $this->slashes . $this->slashes, $testClass); + + return " --filter='$testClass' "; + } + + /** + * Parse testscope for + * @param string $testscope + * @return string string to append to command + */ + protected function parseTestScope($testscope) + { + $this->io->note("Executing Specified Test Scope : $testscope"); + $testscope = str_replace($this->slashes, $this->slashes . $this->slashes, $testscope); + + return " --filter='$testscope'"; + } } diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index bc47e2dfb..c5d476ba6 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -12,6 +12,7 @@ use Illuminate\Support\Str; use Interop\Container\ContainerInterface; use UserFrosting\Support\Exception\FileNotFoundException; +use UserFrosting\Support\Exception\JsonException; /** * Sprinkle manager class. @@ -35,12 +36,7 @@ class SprinkleManager /** * @var string The full absolute base path to the sprinkles directory. */ - protected $sprinklesPath; - - /** - * @var string[] Keeps track of a mapping from resource stream names to relative paths. - */ - protected $resourcePaths; + protected $sprinklesPath = \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS; /** * Create a new SprinkleManager object. @@ -50,7 +46,6 @@ class SprinkleManager public function __construct(ContainerInterface $ci) { $this->ci = $ci; - $this->sprinklesPath = \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS; } /** @@ -72,7 +67,66 @@ public function addSprinkleResources($sprinkleName) { /** @var \UserFrosting\UniformResourceLocator\ResourceLocator $locator */ $locator = $this->ci->locator; - $locator->registerLocation($sprinkleName, $this->sprinklesPath . $sprinkleName); + $locator->registerLocation($sprinkleName, $this->getSprinklePath($sprinkleName)); + } + + /** + * Returns sprinkle base path from name + * + * @param string $sprinkleName + * @return string + */ + public function getSprinklePath($sprinkleName) + { + // Get Sprinkle and make sure it exist + $sprinkle = $this->getSprinkle($sprinkleName); + if (!$sprinkle) { + throw new FileNotFoundException("Sprinkle `$sprinkleName` doesn't exist."); + } + + // Get path and make sure it exist + $path = $this->getSprinklesPath() . $sprinkle; + if (!file_exists($path)) { + throw new FileNotFoundException("Sprinkle `$sprinkleName` should be found at `$path`, but that directory doesn't exist."); + } + + return $path; + } + + /** + * Returns the sprinkle class + * + * @param string $sprinkleName + * @return string + */ + protected function getSprinkleClass($sprinkleName) + { + $className = Str::studly($sprinkleName); + + return $this->getSprinkleClassNamespace($sprinkleName) . "\\$className"; + } + + /** + * Returns the claculated sprinkle namespace + * @param string $sprinkleName + * @return string The Sprinkle Namespace + */ + public function getSprinkleClassNamespace($sprinkleName) + { + $className = Str::studly($sprinkleName); + + return "UserFrosting\\Sprinkle\\$className"; + } + + /** + * Returns the sprinkle service provider class + * + * @param string $sprinkleName + * @return string + */ + protected function getSprinkleDefaultServiceProvider($sprinkleName) + { + return $this->getSprinkleClassNamespace($sprinkleName) . '\\ServicesProvider\\ServicesProvider'; } /** @@ -80,13 +134,12 @@ public function addSprinkleResources($sprinkleName) * * Creates an object of a subclass of UserFrosting\System\Sprinkle\Sprinkle if defined for the sprinkle (converting to StudlyCase). * Otherwise, returns null. - * @param string $name The name of the Sprinkle to initialize. + * @param string $sprinkleName The name of the Sprinkle to initialize. * @return mixed Sprinkle class instance or null if no such class exist */ - public function bootSprinkle($name) + public function bootSprinkle($sprinkleName) { - $className = Str::studly($name); - $fullClassName = "\\UserFrosting\\Sprinkle\\$className\\$className"; + $fullClassName = $this->getSprinkleClass($sprinkleName); // Check that class exists. If not, set to null if (class_exists($fullClassName)) { @@ -124,7 +177,7 @@ public function getSprinkles() * * @param string[] $sprinkleNames */ - public function init($sprinkleNames) + public function init(array $sprinkleNames) { foreach ($sprinkleNames as $sprinkleName) { $sprinkle = $this->bootSprinkle($sprinkleName); @@ -153,12 +206,29 @@ public function initFromSchema($schemaPath) * Return if a Sprinkle is available * Can be used by other Sprinkles to test if their dependencies are met * - * @param string $name The name of the Sprinkle + * @param string $sprinkleName The name of the Sprinkle * @return bool */ - public function isAvailable($name) + public function isAvailable($sprinkleName) + { + return (bool) $this->getSprinkle($sprinkleName); + } + + /** + * Find sprinkle value from the sprinkles.json + * + * @param string $sprinkleName + * @return string|false Return sprinkle name or false if sprinkle not found + */ + public function getSprinkle($sprinkleName) { - return in_array($name, $this->getSprinkleNames()); + $mathches = preg_grep("/^$sprinkleName$/i", $this->getSprinkleNames()); + + if (count($mathches) <= 0) { + return false; + } + + return array_values($mathches)[0]; } /** @@ -174,12 +244,11 @@ public function registerAllServices() /** * Register services for a specified Sprinkle. * - * @param string $name + * @param string $sprinkleName */ - public function registerServices($name) + public function registerServices($sprinkleName) { - $className = Str::studly($name); - $fullClassName = "\\UserFrosting\\Sprinkle\\$className\\ServicesProvider\\ServicesProvider"; + $fullClassName = $this->getSprinkleDefaultServiceProvider($sprinkleName); // Check that class exists, and register services if (class_exists($fullClassName)) { @@ -189,6 +258,29 @@ public function registerServices($name) } } + /** + * Returns sprinklePath parameter + * + * @return string + */ + public function getSprinklesPath() + { + return $this->sprinklesPath; + } + + /** + * Sets sprinklePath parameter + * + * @param string $sprinklesPath + * @return static + */ + public function setSprinklesPath($sprinklesPath) + { + $this->sprinklesPath = $sprinklesPath; + + return $this; + } + /** * Load list of Sprinkles from a JSON schema file (e.g. 'sprinkles.json'). * @@ -200,10 +292,16 @@ protected function loadSchema($schemaPath) $sprinklesFile = @file_get_contents($schemaPath); if ($sprinklesFile === false) { - $errorMessage = "Error: Unable to determine Sprinkle load order. File '$schemaPath' not found or unable to read. Please create a 'sprinkles.json' file and try again."; + $errorMessage = "Error: Unable to determine Sprinkle load order. File '$schemaPath' not found or unable to read. Please create a 'sprinkles.json' file and try again."; throw new FileNotFoundException($errorMessage); } - return json_decode($sprinklesFile); + // Make sure sprinkle contains valid json + if (!$data = json_decode($sprinklesFile)) { + $errorMessage = "Error: Unable to determine Sprinkle load order. File '$schemaPath' doesn't contain valid json : " . json_last_error_msg(); + throw new JsonException($errorMessage); + } + + return $data; } } diff --git a/app/tests/Unit/SprinkleManagerTest.php b/app/tests/Unit/SprinkleManagerTest.php new file mode 100644 index 000000000..c6ee90edc --- /dev/null +++ b/app/tests/Unit/SprinkleManagerTest.php @@ -0,0 +1,253 @@ +fakeCi = m::mock(ContainerInterface::class); + $this->fakeCi->eventDispatcher = new eventDispatcherStub(); + $this->fakeCi->locator = new ResourceLocatorStub(); + + // Setup test sprinkle mock class so it can be found by `class_exist` + m::mock('UserFrosting\Sprinkle\Test\Test'); + } + + public function tearDown() + { + parent::tearDown(); + m::close(); + } + + /** + * @return SprinkleManager + */ + public function testConstructor() + { + $sprinkleManager = new SprinkleManager($this->fakeCi); + $this->assertInstanceOf(SprinkleManager::class, $sprinkleManager); + + return $sprinkleManager; + } + + /** + * @depends testConstructor + * @param SprinkleManager $sprinkleManager + */ + public function testGetSetSprinklesPath(SprinkleManager $sprinkleManager) + { + $sprinkleManager->setSprinklesPath('/foo'); + $this->assertSame('/foo', $sprinkleManager->getSprinklesPath()); + } + + /** + * @depends testConstructor + * @param SprinkleManager $sprinkleManager + * @return SprinkleManager + */ + public function testInitFromSchema(SprinkleManager $sprinkleManager) + { + $sprinkleManager->initFromSchema(__DIR__ . '/data/sprinkles.json'); + + return $sprinkleManager; + } + + /** + * @depends testConstructor + * @expectedException \UserFrosting\Support\Exception\FileNotFoundException + */ + public function testLoadSprinkleWithNonExistingFile() + { + $sprinkleManager = new SprinkleManager($this->fakeCi); + $sprinkleManager->initFromSchema('foo.json'); + } + + /** + * @depends testInitFromSchema + * @param SprinkleManager $sprinkleManager + */ + public function testGetSprinkles(SprinkleManager $sprinkleManager) + { + $sprinkles = $sprinkleManager->getSprinkles(); + $this->assertEquals([ + 'foo' => null, + 'bar' => null, + 'test' => new \UserFrosting\Sprinkle\Test\Test() + ], $sprinkles); + } + + /** + * @depends testInitFromSchema + * @param SprinkleManager $sprinkleManager + */ + public function testGetSprinkleNames(SprinkleManager $sprinkleManager) + { + $sprinkles = $sprinkleManager->getSprinkleNames(); + $this->assertSame(['foo', 'bar', 'test'], $sprinkles); + } + + /** + * @depends testInitFromSchema + * @depends testGetSprinkleNames + * @param string $sprinkleName + * @param bool $isAvailable + * @param SprinkleManager $sprinkleManager + * @testWith ["bar", true] + * ["test", true] + * ["foo", true] + * ["fOo", true] + * ["foO", true] + * ["Foo", true] + * ["FOO", true] + * ["fo", false] + * ["o", false] + * ["oo", false] + * ["f0o", false] + * ["foofoo", false] + * ["1foo1", false] + * ["barfoo", false] + * ["blah", false] + */ + public function testIsAvailable($sprinkleName, $isAvailable, SprinkleManager $sprinkleManager) + { + $this->assertSame($isAvailable, $sprinkleManager->isAvailable($sprinkleName)); + } + + /** + * @depends testInitFromSchema + * @param string $sprinkleName + * @param bool $path + * @param SprinkleManager $sprinkleManager + * @testWith ["foo", "/data/foo"] + * ["bar", "/data/bar"] + * ["test", "/data/test"] + */ + public function testGetSprinklePath($sprinkleName, $path, SprinkleManager $sprinkleManager) + { + $sprinkleManager->setSprinklesPath(__DIR__ . '/data/'); + $this->assertSame(__DIR__ . $path, $sprinkleManager->getSprinklePath($sprinkleName)); + } + + /** + * @depends testInitFromSchema + * @depends testGetSprinklePath + * @expectedException \UserFrosting\Support\Exception\FileNotFoundException + * @param SprinkleManager $sprinkleManager + */ + public function testGetSprinklePathWherePathDoesntExist(SprinkleManager $sprinkleManager) + { + $sprinkleManager->setSprinklesPath(__DIR__ . '/foo/'); + $sprinkleManager->getSprinklePath('foo'); + } + + /** + * @depends testInitFromSchema + * @depends testGetSprinklePath + * @expectedException \UserFrosting\Support\Exception\FileNotFoundException + * @param SprinkleManager $sprinkleManager + */ + public function testGetSprinklePathWhereSprinkleDoesntExist(SprinkleManager $sprinkleManager) + { + $sprinkleManager->getSprinklePath('blah'); + } + + /** + * @depends testInitFromSchema + * @param SprinkleManager $sprinkleManager + */ + public function testRegisterAllServices(SprinkleManager $sprinkleManager) + { + // Set Expectations for test sprinkle ServiceProvider + // @see https://stackoverflow.com/a/13390001/445757 + $this->getMockBuilder('nonexistant') + ->setMockClassName('foo') + ->setMethods(['register']) + ->getMock(); + class_alias('foo', 'UserFrosting\Sprinkle\Test\ServicesProvider\ServicesProvider'); + + $sprinkleManager->registerAllServices(); + } + + /** + * @depends testInitFromSchema + * @depends testGetSprinklePath + * @param SprinkleManager $sprinkleManager + */ + public function testAddResources(SprinkleManager $sprinkleManager) + { + $sprinkleManager->setSprinklesPath(__DIR__ . '/data/'); + $sprinkleManager->addResources(); + } + + /** + * This will work, as long as it contains valid json + * + * @depends testConstructor + * @depends testGetSprinkles + */ + public function testLoadSprinkleWithTxtFile() + { + $sprinkleManager = new SprinkleManager($this->fakeCi); + $sprinkleManager->initFromSchema(__DIR__ . '/data/sprinkles.txt'); + $this->assertCount(3, $sprinkleManager->getSprinkles()); + } + + /** + * @depends testConstructor + * @expectedException \UserFrosting\Support\Exception\JsonException + */ + public function testLoadSprinkleWithBadJson() + { + $sprinkleManager = new SprinkleManager($this->fakeCi); + $sprinkleManager->initFromSchema(__DIR__ . '/data/sprinkles-bad.json'); + } + + /** + * @depends testConstructor + * @depends testIsAvailable + */ + public function testLoadSprinkleWithDuplicateSprinkles() + { + $sprinkleManager = new SprinkleManager($this->fakeCi); + $sprinkleManager->initFromSchema(__DIR__ . '/data/sprinkles-duplicate.json'); + $this->assertEquals([ + 'foo' => null, + 'FOO' => null, + 'bar' => null, + ], $sprinkleManager->getSprinkles()); + + $this->assertTrue($sprinkleManager->isAvailable('Foo')); + } +} + +class eventDispatcherStub +{ + public function addSubscriber() + { + } +} + +class ResourceLocatorStub +{ + public function registerLocation() + { + } +} diff --git a/app/tests/Unit/data/bar/.gitkeep b/app/tests/Unit/data/bar/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/app/tests/Unit/data/foo/.gitkeep b/app/tests/Unit/data/foo/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/app/tests/Unit/data/sprinkles-bad.json b/app/tests/Unit/data/sprinkles-bad.json new file mode 100644 index 000000000..adbc379bc --- /dev/null +++ b/app/tests/Unit/data/sprinkles-bad.json @@ -0,0 +1,7 @@ +{ + "base": [ + "foo" + "bar" + "test" + ] +} diff --git a/app/tests/Unit/data/sprinkles-duplicate.json b/app/tests/Unit/data/sprinkles-duplicate.json new file mode 100644 index 000000000..d8be11781 --- /dev/null +++ b/app/tests/Unit/data/sprinkles-duplicate.json @@ -0,0 +1,11 @@ +{ + "require": { + + }, + "base": [ + "foo", + "FOO", + "bar", + "bar" + ] +} diff --git a/app/tests/Unit/data/sprinkles.json b/app/tests/Unit/data/sprinkles.json new file mode 100644 index 000000000..8a1ffa64b --- /dev/null +++ b/app/tests/Unit/data/sprinkles.json @@ -0,0 +1,10 @@ +{ + "require": { + + }, + "base": [ + "foo", + "bar", + "test" + ] +} diff --git a/app/tests/Unit/data/sprinkles.txt b/app/tests/Unit/data/sprinkles.txt new file mode 100644 index 000000000..8a1ffa64b --- /dev/null +++ b/app/tests/Unit/data/sprinkles.txt @@ -0,0 +1,10 @@ +{ + "require": { + + }, + "base": [ + "foo", + "bar", + "test" + ] +} diff --git a/app/tests/Unit/data/test/.gitkeep b/app/tests/Unit/data/test/.gitkeep new file mode 100644 index 000000000..e69de29bb From d038793214d1d50419f8a50256f1202fd6f1b281 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 21 Jan 2019 20:54:52 -0500 Subject: [PATCH 193/237] [Travis] Cache composer data to speed up builds --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 10e77e30d..637fe2650 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,10 @@ env: - DB=sqlite - DB=pgsql +cache: + directories: + - $HOME/.composer/cache + before_install: # copy sprinkles.json - cp app/sprinkles.example.json app/sprinkles.json From 213e6973616cd87f69b9c6026ae28fd3f7bf053b Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Mon, 21 Jan 2019 21:34:39 -0500 Subject: [PATCH 194/237] Let's try to fix that false negative test --- .../account/tests/Integration/AuthorizationManagerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php index b520fd4da..01ae32d4c 100644 --- a/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php +++ b/app/sprinkles/account/tests/Integration/AuthorizationManagerTest.php @@ -131,7 +131,7 @@ public function testCheckAccess_withNormalUser() $authLogger->shouldReceive('debug')->once()->with('No matching permissions found. Access denied.'); $authLogger->shouldReceive('debug')->times(2); - $this->assertFalse($this->getManager()->checkAccess($user, 'foo')); + $this->assertFalse($this->getManager()->checkAccess($user, 'blah')); } /** From 8eb89de9fce8675f021a8c37a5e036caba6f5133 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Tue, 22 Jan 2019 17:59:42 +1100 Subject: [PATCH 195/237] Updated CHANGELOG.md --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56396bb51..25fa9a6ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## 4.2.0-beta.2 ### Added -- Added `sprinkle:list` bakery command -- Changed the sprinkle list in the bakery `debug` command to use the new `sprinkle:list` table +- `sprinkle:list` bakery command +- `NoCache` middleware to prevent caching of routes with dynamic content + +### Changed +- Sprinkle list in the bakery `debug` command to uses the new `sprinkle:list` table ### Fix - Fix for `Test` Bakery command From 66c012ebfd39fb7060698ea4cf2a37c3b73afcd1 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 26 Jan 2019 13:39:33 +1100 Subject: [PATCH 196/237] - Updated changelog regarding `npm i` dependency issue fix. - Noted area needing improvement in asset build script --- CHANGELOG.md | 1 + build/gulpfile.esm.js | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25fa9a6ab..7e2d7c6aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added public `getSprinklesPath` & `setSprinklesPath` to return or set the path to the sprinkle dir (`app/sprinkles/`) - Added `JsonException` if `sprinkles.json` doesn't contain valid json. - Added specific tests for sprinkleManager with 100% test coverage +- Ignore existing `package-lock.json` which caused incorrect dependencies to be installed when upgrading from older versions of UserFrosting. ## 4.2.0-beta.1 diff --git a/build/gulpfile.esm.js b/build/gulpfile.esm.js index 85b947097..1da2ca193 100644 --- a/build/gulpfile.esm.js +++ b/build/gulpfile.esm.js @@ -267,6 +267,7 @@ export function bundle() { * @param {string} path Absolute path to resolve. */ function resolveToAssetPath(path) { + // TODO There is a significant amount of duplicated code here. We can do better. if (path.startsWith(resolvePath(sprinklesDir))) { // Handle sprinkle path for (const sprinkle of sprinkles) { From 2e8fa2b0ef148321e7874d6395b977b6634f7021 Mon Sep 17 00:00:00 2001 From: Jordan Date: Sat, 26 Jan 2019 14:20:08 +1100 Subject: [PATCH 197/237] Develop jordan (#930) - Updated latest `CHANGELOG` entry to align with http://keepachangelog.com/en/1.0.0/ standards - Updated Jordan's (@Silic0nS0ldier) bio - Added fix for `npm` dependency installation issues to `CHANGELOG` - Added new `NoCache` middleware to `CHANGELOG` - Added branch status summary to `README` --- CHANGELOG.md | 8 ++++++-- README.md | 9 ++++++--- build/gulpfile.esm.js | 1 + 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56396bb51..7e2d7c6aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,8 +8,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## 4.2.0-beta.2 ### Added -- Added `sprinkle:list` bakery command -- Changed the sprinkle list in the bakery `debug` command to use the new `sprinkle:list` table +- `sprinkle:list` bakery command +- `NoCache` middleware to prevent caching of routes with dynamic content + +### Changed +- Sprinkle list in the bakery `debug` command to uses the new `sprinkle:list` table ### Fix - Fix for `Test` Bakery command @@ -25,6 +28,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added public `getSprinklesPath` & `setSprinklesPath` to return or set the path to the sprinkle dir (`app/sprinkles/`) - Added `JsonException` if `sprinkles.json` doesn't contain valid json. - Added specific tests for sprinkleManager with 100% test coverage +- Ignore existing `package-lock.json` which caused incorrect dependencies to be installed when upgrading from older versions of UserFrosting. ## 4.2.0-beta.1 diff --git a/README.md b/README.md index 5721acb77..8c14f009a 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,16 @@ [![Latest Version](https://img.shields.io/github/release/userfrosting/UserFrosting.svg)](https://github.com/userfrosting/UserFrosting/releases) [![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE.md) -[![Build Status](https://travis-ci.org/userfrosting/UserFrosting.svg?branch=master)](https://travis-ci.org/userfrosting/UserFrosting) -[![codecov](https://codecov.io/gh/userfrosting/userfrosting/branch/master/graph/badge.svg)](https://codecov.io/gh/userfrosting/userfrosting) [![Join the chat at https://chat.userfrosting.com/channel/support](https://demo.rocket.chat/images/join-chat.svg)](https://chat.userfrosting.com/channel/support) [![Backers on Open Collective](https://opencollective.com/userfrosting/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/userfrosting/sponsors/badge.svg)](#sponsors) [![Donate](https://img.shields.io/badge/Open%20Collective-Donate-blue.svg)](https://opencollective.com/userfrosting#backer) +| Branch | Status | +| ------ | ------ | +| master | [![Build Status](https://travis-ci.org/userfrosting/UserFrosting.svg?branch=master)](https://travis-ci.org/userfrosting/UserFrosting) [![codecov](https://codecov.io/gh/userfrosting/userfrosting/branch/master/graph/badge.svg)](https://codecov.io/gh/userfrosting/userfrosting/branch/master) | +| develop | [![Build Status](https://travis-ci.org/userfrosting/UserFrosting.svg?branch=develop)](https://travis-ci.org/userfrosting/UserFrosting) [![codecov](https://codecov.io/gh/userfrosting/userfrosting/branch/develop/graph/badge.svg)](https://codecov.io/gh/userfrosting/userfrosting/branch/develop) | + [https://www.userfrosting.com](https://www.userfrosting.com) If you simply want to show that you like this project, or want to remember it for later, you should **star**, not **fork**, this repository. Forking is only for when you are ready to create your own copy of the code to work on. @@ -77,7 +80,7 @@ Louis's a civil engineer in Montréal, Québec who also has a passion for coding ### Jordan Mele -Jordan's a former developer of Mayvin Training and a student studying Computer Science at the University of Wollongong, Australia. His passion is creating software-based solutions to overcomplicated problems, while keeping the user in control. +Jordan's an Australian PHP Developer at [4mation](https://www.4mation.com.au) in Surry Hills, NSW. His passion is creating simple yet intuitive software-based solutions for problems that would otherwise be tedious and overcomplicated to address, while keeping the user in control. ### Sarah Baghdadi diff --git a/build/gulpfile.esm.js b/build/gulpfile.esm.js index 85b947097..1da2ca193 100644 --- a/build/gulpfile.esm.js +++ b/build/gulpfile.esm.js @@ -267,6 +267,7 @@ export function bundle() { * @param {string} path Absolute path to resolve. */ function resolveToAssetPath(path) { + // TODO There is a significant amount of duplicated code here. We can do better. if (path.startsWith(resolvePath(sprinklesDir))) { // Handle sprinkle path for (const sprinkle of sprinkles) { From f89b8a9b116e8385d3981f4eaa362818b841fa91 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 09:35:13 -0500 Subject: [PATCH 198/237] Fix issue with sprinkle path --- app/system/Sprinkle/SprinkleManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index c5d476ba6..670c2027a 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -36,7 +36,7 @@ class SprinkleManager /** * @var string The full absolute base path to the sprinkles directory. */ - protected $sprinklesPath = \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS; + protected $sprinklesPath = \UserFrosting\SPRINKLES_DIR . \UserFrosting\DS; /** * Create a new SprinkleManager object. From c4c6432fefcf5d4405691fb0503f4e7bfcf2d3b4 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 11:46:37 -0500 Subject: [PATCH 199/237] Update beta version (before we forget) --- app/defines.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/defines.php b/app/defines.php index 350de007b..5cf40c12b 100755 --- a/app/defines.php +++ b/app/defines.php @@ -10,7 +10,7 @@ namespace UserFrosting; // Some standard defines -define('UserFrosting\VERSION', '4.2.0-beta.1'); +define('UserFrosting\VERSION', '4.2.0-beta.2'); define('UserFrosting\DS', '/'); define('UserFrosting\PHP_MIN_VERSION', '5.6'); define('UserFrosting\PHP_RECOMMENDED_VERSION', '7.1'); From 8987791e1c56502b4dda0fc679c9db91c58f7d59 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 17:48:48 -0500 Subject: [PATCH 200/237] Fix vendor assets not found in production mode --- CHANGELOG.md | 1 + .../src/ServicesProvider/ServicesProvider.php | 19 ++++++++++++------- app/system/ServicesProvider.php | 4 ---- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e2d7c6aa..8996962f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added `JsonException` if `sprinkles.json` doesn't contain valid json. - Added specific tests for sprinkleManager with 100% test coverage - Ignore existing `package-lock.json` which caused incorrect dependencies to be installed when upgrading from older versions of UserFrosting. +- Vendor assets not found in production mode ## 4.2.0-beta.1 diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 56ab8546c..9ef01d860 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -123,6 +123,13 @@ public function register(ContainerInterface $container) // Load asset schema if ($config['assets.use_raw']) { + + // Register sprinkle assets stream, plus vendor assets in shared streams + $locator->registerStream('assets', 'vendor', \UserFrosting\BOWER_ASSET_DIR, true); + $locator->registerStream('assets', 'vendor', \UserFrosting\NPM_ASSET_DIR, true); + $locator->registerStream('assets', 'vendor', \UserFrosting\BROWSERIFIED_ASSET_DIR, true); + $locator->registerStream('assets', '', \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME); + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; $assets = new Assets($locator, 'assets', $baseUrl); @@ -144,6 +151,11 @@ public function register(ContainerInterface $container) $assets->addAssetBundles($bundles); } } else { + + // Register compiled assets stream in public folder + alias for vendor ones + $c->locator->registerStream('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); + $c->locator->registerStream('assets', 'vendor', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); + $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; $assets = new Assets($locator, 'assets', $baseUrl); @@ -249,13 +261,6 @@ public function register(ContainerInterface $container) $config->set('csrf.blacklist', $csrfBlacklist); - // Reset 'assets' scheme in locator to use raw assets if specified in config. - // Must be done here to prevent circular dependency as config is not loaded in system and locator can't be extended here. - if (!$config['assets.use_raw']) { - $c->locator->removeStream('assets'); - $c->locator->registerStream('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); - } - return $config; }; diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 4e7af7034..5323ece06 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -54,12 +54,8 @@ public function register(ContainerInterface $container) $locator->registerStream('log', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\LOG_DIR_NAME, true); $locator->registerStream('cache', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\CACHE_DIR_NAME, true); $locator->registerStream('session', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); - $locator->registerStream('assets', 'vendor', \UserFrosting\BOWER_ASSET_DIR, true); - $locator->registerStream('assets', 'vendor', \UserFrosting\NPM_ASSET_DIR, true); - $locator->registerStream('assets', 'vendor', \UserFrosting\BROWSERIFIED_ASSET_DIR, true); // Register sprinkles streams - $locator->registerStream('assets', '', \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME); $locator->registerStream('config', '', \UserFrosting\DS . \UserFrosting\CONFIG_DIR_NAME); $locator->registerStream('extra', '', \UserFrosting\DS . \UserFrosting\EXTRA_DIR_NAME); $locator->registerStream('factories', '', \UserFrosting\DS . \UserFrosting\FACTORY_DIR_NAME); From 5e8f60c5e1394bb526a1012b75577b0e29485d01 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 19:59:30 -0500 Subject: [PATCH 201/237] Updated Bake Command description --- app/sprinkles/core/src/Bakery/BakeCommand.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/sprinkles/core/src/Bakery/BakeCommand.php b/app/sprinkles/core/src/Bakery/BakeCommand.php index 4edcab6e4..170405364 100644 --- a/app/sprinkles/core/src/Bakery/BakeCommand.php +++ b/app/sprinkles/core/src/Bakery/BakeCommand.php @@ -21,11 +21,6 @@ */ class BakeCommand extends BaseCommand { - /** - * @var string Path to the build/ directory - */ - protected $buildPath; - /** * @var string The UserFrosting ASCII art. */ @@ -46,7 +41,7 @@ protected function configure() { $this->setName('bake') ->setDescription('UserFrosting installation command') - ->setHelp('This command combine the debug, migrate and build-assets commands.'); + ->setHelp('This command combine the setup:db, setup:smtp, debug, migrate, create-admin and build-assets commands.'); } /** From 15f3c20b8dd9db65521697f34ff62f46b44e2363 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 20:10:01 -0500 Subject: [PATCH 202/237] Make io messages style consistent --- app/sprinkles/core/src/Bakery/BuildAssets.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/sprinkles/core/src/Bakery/BuildAssets.php b/app/sprinkles/core/src/Bakery/BuildAssets.php index c3a2d66f5..1301e7698 100644 --- a/app/sprinkles/core/src/Bakery/BuildAssets.php +++ b/app/sprinkles/core/src/Bakery/BuildAssets.php @@ -82,7 +82,7 @@ protected function execute(InputInterface $input, OutputInterface $output) */ protected function npmInstall($force) { - $this->io->section('Installing npm dependencies'); + $this->io->section('Installing npm dependencies'); $this->io->writeln('> npm install'); // Temporarily change the working directory so we can install npm dependencies @@ -96,7 +96,7 @@ protected function npmInstall($force) // Skip if lockfile indicates previous run if (!$force && file_exists('package.lock') && filemtime('package.json') < filemtime('package.lock') - 1) { - $this->io->writeln('> Skipping as package-lock.json age indicates dependencies are already installed'); + $this->io->writeln('Skipping as package-lock.json age indicates dependencies are already installed'); chdir($wd); return; From 1d2d5d1ec4f25ecec85582533b7a91ac269a9d7a Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 20:35:48 -0500 Subject: [PATCH 203/237] Move locator stream registration to core sprinkle --- app/sprinkles/core/src/Core.php | 29 +++++++++++++++++-- .../src/ServicesProvider/ServicesProvider.php | 3 +- app/system/ServicesProvider.php | 17 ++--------- 3 files changed, 30 insertions(+), 19 deletions(-) diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index 19e992794..16bcd45f0 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -33,9 +33,7 @@ public function __construct(ContainerInterface $ci) { $this->ci = $ci; - // Register core locator streams - $this->ci->locator->registerStream('migrations', '', \UserFrosting\MIGRATIONS_DIR); - $this->ci->locator->registerStream('seeds', '', \UserFrosting\SEEDS_DIR); + $this->registerStreams(); } /** @@ -114,4 +112,29 @@ public function onAddGlobalMiddleware(Event $event) { SlimCsrfProvider::registerMiddleware($event->getApp(), $this->ci->request, $this->ci->csrf); } + + /** + * Register Core sprinkle locator streams + */ + protected function registerStreams() + { + /** @var \UserFrosting\UniformResourceLocator\ResourceLocator $locator */ + $locator = $this->ci->locator; + + // Register core locator shared streams + $locator->registerStream('cache', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\CACHE_DIR_NAME, true); + $locator->registerStream('config', '', \UserFrosting\DS . \UserFrosting\CONFIG_DIR_NAME); + $locator->registerStream('log', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\LOG_DIR_NAME, true); + $locator->registerStream('migrations', '', \UserFrosting\MIGRATIONS_DIR); + $locator->registerStream('seeds', '', \UserFrosting\SEEDS_DIR); + $locator->registerStream('session', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); + + // Register core locator sprinkle streams + $locator->registerStream('extra', '', \UserFrosting\DS . \UserFrosting\EXTRA_DIR_NAME); + $locator->registerStream('factories', '', \UserFrosting\DS . \UserFrosting\FACTORY_DIR_NAME); + $locator->registerStream('locale', '', \UserFrosting\DS . \UserFrosting\LOCALE_DIR_NAME); + $locator->registerStream('routes', '', \UserFrosting\DS . \UserFrosting\ROUTE_DIR_NAME); + $locator->registerStream('schema', '', \UserFrosting\DS . \UserFrosting\SCHEMA_DIR_NAME); + $locator->registerStream('templates', '', \UserFrosting\DS . \UserFrosting\TEMPLATE_DIR_NAME); + } } diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 9ef01d860..479a30175 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -152,9 +152,10 @@ public function register(ContainerInterface $container) } } else { - // Register compiled assets stream in public folder + alias for vendor ones + // Register compiled assets stream in public folder + alias for vendor ones + build stream for CompiledAssetBundles $c->locator->registerStream('assets', '', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); $c->locator->registerStream('assets', 'vendor', \UserFrosting\PUBLIC_DIR_NAME . '/' . \UserFrosting\ASSET_DIR_NAME, true); + $c->locator->registerStream('build', '', \UserFrosting\BUILD_DIR_NAME, true); $baseUrl = $config['site.uri.public'] . '/' . $config['assets.compiled.path']; $assets = new Assets($locator, 'assets', $baseUrl); diff --git a/app/system/ServicesProvider.php b/app/system/ServicesProvider.php index 5323ece06..8a8e331f1 100644 --- a/app/system/ServicesProvider.php +++ b/app/system/ServicesProvider.php @@ -48,23 +48,10 @@ public function register(ContainerInterface $container) $container['locator'] = function ($c) { $locator = new ResourceLocator(\UserFrosting\ROOT_DIR); - // Register shared streams + // Register streams $locator->registerStream('bakery', '', \UserFrosting\BAKERY_SYSTEM_DIR, true); - $locator->registerStream('build', '', \UserFrosting\BUILD_DIR_NAME, true); - $locator->registerStream('log', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\LOG_DIR_NAME, true); - $locator->registerStream('cache', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\CACHE_DIR_NAME, true); - $locator->registerStream('session', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); - - // Register sprinkles streams - $locator->registerStream('config', '', \UserFrosting\DS . \UserFrosting\CONFIG_DIR_NAME); - $locator->registerStream('extra', '', \UserFrosting\DS . \UserFrosting\EXTRA_DIR_NAME); - $locator->registerStream('factories', '', \UserFrosting\DS . \UserFrosting\FACTORY_DIR_NAME); - $locator->registerStream('locale', '', \UserFrosting\DS . \UserFrosting\LOCALE_DIR_NAME); - $locator->registerStream('routes', '', \UserFrosting\DS . \UserFrosting\ROUTE_DIR_NAME); - $locator->registerStream('schema', '', \UserFrosting\DS . \UserFrosting\SCHEMA_DIR_NAME); - $locator->registerStream('sprinkles', '', ''); - $locator->registerStream('templates', '', \UserFrosting\DS . \UserFrosting\TEMPLATE_DIR_NAME); $locator->registerStream('bakery', '', \UserFrosting\BAKERY_DIR); + $locator->registerStream('sprinkles', '', ''); return $locator; }; From 0e29f174826d92471db527e3c4bb6c9d133438b1 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 21:00:38 -0500 Subject: [PATCH 204/237] Use locator to find `routerCacheFile` --- CHANGELOG.md | 1 + app/sprinkles/core/config/production.php | 2 +- app/sprinkles/core/src/Bakery/ClearCacheCommand.php | 3 ++- app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8996962f5..ae2e1561c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - Sprinkle list in the bakery `debug` command to uses the new `sprinkle:list` table +- `routerCacheFile` config now only contains filename. Locator is used to find the full path ### Fix - Fix for `Test` Bakery command diff --git a/app/sprinkles/core/config/production.php b/app/sprinkles/core/config/production.php index 425416eac..e3b217bcf 100644 --- a/app/sprinkles/core/config/production.php +++ b/app/sprinkles/core/config/production.php @@ -35,7 +35,7 @@ * Use router cache, disable full error details */ 'settings' => [ - 'routerCacheFile' => \UserFrosting\ROOT_DIR . '/' . \UserFrosting\APP_DIR_NAME . '/' . \UserFrosting\CACHE_DIR_NAME . '/' . 'routes.cache', + 'routerCacheFile' => 'routes.cache', 'displayErrorDetails' => false ], /* diff --git a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php index 36a9577f8..7dc6ca2b5 100644 --- a/app/sprinkles/core/src/Bakery/ClearCacheCommand.php +++ b/app/sprinkles/core/src/Bakery/ClearCacheCommand.php @@ -51,7 +51,8 @@ protected function execute(InputInterface $input, OutputInterface $output) // Clear router cache $this->io->writeln(' > Clearing Router cache file', OutputInterface::VERBOSITY_VERBOSE); if (!$this->clearRouterCache()) { - $file = $this->ci->config['settings.routerCacheFile']; + $filename = $this->ci->config['settings.routerCacheFile']; + $file = $this->ci->locator->findResource("cache://$filename", true, true); $this->io->error("Failed to delete Router cache file. Make sure you have write access to the `$file` file."); exit(1); } diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 479a30175..cc9504bef 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -593,7 +593,8 @@ public function register(ContainerInterface $container) $container['router'] = function ($c) { $routerCacheFile = false; if (isset($c->config['settings.routerCacheFile'])) { - $routerCacheFile = $c->config['settings.routerCacheFile']; + $filename = $c->config['settings.routerCacheFile']; + $routerCacheFile = $c->locator->findResource("cache://$filename", true, true); } return (new Router())->setCacheFile($routerCacheFile); From 491db0948f1d896fa193a68ebe206e4794f433bb Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 22:00:59 -0500 Subject: [PATCH 205/237] Moved constants from app/defines.php to app/sprinkles/core/defines.php Those constants are not used by the base system. They should really be in the core sprinkle. Less we have in system, and more in core, better it is for #830 --- CHANGELOG.md | 4 +++ app/defines.php | 46 +++++++-------------------------- app/sprinkles/core/defines.php | 39 ++++++++++++++++++++++++++-- app/sprinkles/core/src/Core.php | 13 +++++----- 4 files changed, 57 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae2e1561c..e823c3fb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Changed - Sprinkle list in the bakery `debug` command to uses the new `sprinkle:list` table - `routerCacheFile` config now only contains filename. Locator is used to find the full path +- Moved some constants from `app/defines.php` to `app/sprinkles/core/defines.php` ### Fix - Fix for `Test` Bakery command @@ -32,6 +33,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Ignore existing `package-lock.json` which caused incorrect dependencies to be installed when upgrading from older versions of UserFrosting. - Vendor assets not found in production mode +### Deprecated +- `UserFrosting\APP_DIR_NAME` : Use `UserFrosting\APP_DIR` instead. + ## 4.2.0-beta.1 ### Changed Requirements diff --git a/app/defines.php b/app/defines.php index 5cf40c12b..bdfb996ff 100755 --- a/app/defines.php +++ b/app/defines.php @@ -27,49 +27,21 @@ // The directory containing APP_DIR. Usually, this will contain the entire website. define('UserFrosting\ROOT_DIR', realpath(__DIR__ . '/..')); -// Directory names -define('UserFrosting\APP_DIR_NAME', basename(__DIR__)); -define('UserFrosting\BUILD_DIR_NAME', 'build'); -define('UserFrosting\CACHE_DIR_NAME', 'cache'); -define('UserFrosting\DB_DIR_NAME', 'database'); -define('UserFrosting\SESSION_DIR_NAME', 'sessions'); +// Names of app directories +define('UserFrosting\APP_DIR_NAME', basename(__DIR__)); //@deprecated; Use `UserFrosting\APP_DIR` instead define('UserFrosting\SPRINKLES_DIR_NAME', 'sprinkles'); +// Names of src directories within Sprinkles +define('UserFrosting\SRC_DIR_NAME', 'src'); + // Full path to Sprinkles directory define('UserFrosting\SPRINKLES_DIR', APP_DIR . DS . SPRINKLES_DIR_NAME); -// Sprinkles schema file +// Full path to sprinkles schema file define('UserFrosting\SPRINKLES_SCHEMA_FILE', APP_DIR . DS . 'sprinkles.json'); -define('UserFrosting\LOG_DIR_NAME', 'logs'); -define('UserFrosting\VENDOR_DIR_NAME', 'vendor'); - -// Full path to Composer's vendor directory -define('UserFrosting\VENDOR_DIR', APP_DIR . DS . VENDOR_DIR_NAME); - -// Full path to database directory (SQLite only) -define('UserFrosting\DB_DIR', APP_DIR . DS . DB_DIR_NAME); +// Full path to system Bakery commands +define('UserFrosting\BAKERY_SYSTEM_DIR', APP_DIR . DS . 'system' . DS . 'Bakery' . DS . 'Command'); -// Names of directories within Sprinkles -define('UserFrosting\ASSET_DIR_NAME', 'assets'); -define('UserFrosting\EXTRA_DIR_NAME', 'extra'); -define('UserFrosting\CONFIG_DIR_NAME', 'config'); -define('UserFrosting\LOCALE_DIR_NAME', 'locale'); -define('UserFrosting\ROUTE_DIR_NAME', 'routes'); -define('UserFrosting\SCHEMA_DIR_NAME', 'schema'); -define('UserFrosting\SRC_DIR_NAME', 'src'); -define('UserFrosting\TEMPLATE_DIR_NAME', 'templates'); -define('UserFrosting\FACTORY_DIR_NAME', 'factories'); -define('UserFrosting\PUBLIC_DIR_NAME', 'public'); - -// Paths for the different class sources +// Relative path from within sprinkle directory define('UserFrosting\BAKERY_DIR', SRC_DIR_NAME . DS . 'Bakery'); - -// Path to system Bakery commands -define('UserFrosting\BAKERY_SYSTEM_DIR', APP_DIR_NAME . DS . 'system' . DS . 'Bakery' . DS . 'Command'); - -// Full path to frontend vendor asset directories -define('UserFrosting\ASSET_DIR', APP_DIR_NAME . DS . ASSET_DIR_NAME); -define('UserFrosting\NPM_ASSET_DIR', ASSET_DIR . DS . 'node_modules'); -define('UserFrosting\BROWSERIFIED_ASSET_DIR', ASSET_DIR . DS . 'browser_modules'); -define('UserFrosting\BOWER_ASSET_DIR', ASSET_DIR . DS . 'bower_components'); diff --git a/app/sprinkles/core/defines.php b/app/sprinkles/core/defines.php index 0e5aded43..0dc0268a2 100644 --- a/app/sprinkles/core/defines.php +++ b/app/sprinkles/core/defines.php @@ -9,8 +9,43 @@ namespace UserFrosting; +// Names of root directories +define('UserFrosting\BUILD_DIR_NAME', 'build'); +define('UserFrosting\PUBLIC_DIR_NAME', 'public'); + +// Names of app directories +define('UserFrosting\CACHE_DIR_NAME', 'cache'); +define('UserFrosting\DB_DIR_NAME', 'database'); +define('UserFrosting\LOG_DIR_NAME', 'logs'); +define('UserFrosting\SESSION_DIR_NAME', 'sessions'); +define('UserFrosting\VENDOR_DIR_NAME', 'vendor'); + // Names of directories within Sprinkles -define('UserFrosting\MIGRATIONS_DIR', SRC_DIR_NAME . DS . 'Database' . DS . 'Migrations'); -define('UserFrosting\SEEDS_DIR', SRC_DIR_NAME . DS . 'Database' . DS . 'Seeds'); +define('UserFrosting\ASSET_DIR_NAME', 'assets'); +define('UserFrosting\EXTRA_DIR_NAME', 'extra'); +define('UserFrosting\CONFIG_DIR_NAME', 'config'); +define('UserFrosting\LOCALE_DIR_NAME', 'locale'); +define('UserFrosting\ROUTE_DIR_NAME', 'routes'); +define('UserFrosting\SCHEMA_DIR_NAME', 'schema'); +define('UserFrosting\TEMPLATE_DIR_NAME', 'templates'); +define('UserFrosting\FACTORY_DIR_NAME', 'factories'); + +// Full path to database directory (SQLite only) +define('UserFrosting\DB_DIR', APP_DIR . DS . DB_DIR_NAME); + +// Full path to storage directories define('UserFrosting\STORAGE_DIR', APP_DIR . DS . 'storage'); define('UserFrosting\STORAGE_PUBLIC_DIR', PUBLIC_DIR_NAME . DS . 'files'); + +// Full path to Composer's vendor directory +define('UserFrosting\VENDOR_DIR', APP_DIR . DS . VENDOR_DIR_NAME); + +// Full path to frontend vendor asset directories +define('UserFrosting\ASSET_DIR', APP_DIR . DS . ASSET_DIR_NAME); +define('UserFrosting\NPM_ASSET_DIR', ASSET_DIR . DS . 'node_modules'); +define('UserFrosting\BROWSERIFIED_ASSET_DIR', ASSET_DIR . DS . 'browser_modules'); +define('UserFrosting\BOWER_ASSET_DIR', ASSET_DIR . DS . 'bower_components'); + +// Relative path from within sprinkle directory +define('UserFrosting\MIGRATIONS_DIR', SRC_DIR_NAME . DS . 'Database' . DS . 'Migrations'); +define('UserFrosting\SEEDS_DIR', SRC_DIR_NAME . DS . 'Database' . DS . 'Seeds'); diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index 16bcd45f0..6ab0bafa0 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -122,19 +122,20 @@ protected function registerStreams() $locator = $this->ci->locator; // Register core locator shared streams - $locator->registerStream('cache', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\CACHE_DIR_NAME, true); - $locator->registerStream('config', '', \UserFrosting\DS . \UserFrosting\CONFIG_DIR_NAME); - $locator->registerStream('log', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\LOG_DIR_NAME, true); - $locator->registerStream('migrations', '', \UserFrosting\MIGRATIONS_DIR); - $locator->registerStream('seeds', '', \UserFrosting\SEEDS_DIR); - $locator->registerStream('session', '', \UserFrosting\APP_DIR_NAME . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); + $locator->registerStream('cache', '', \UserFrosting\APP_DIR . \UserFrosting\DS . \UserFrosting\CACHE_DIR_NAME, true); + $locator->registerStream('log', '', \UserFrosting\APP_DIR . \UserFrosting\DS . \UserFrosting\LOG_DIR_NAME, true); + $locator->registerStream('session', '', \UserFrosting\APP_DIR . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); // Register core locator sprinkle streams + $locator->registerStream('config', '', \UserFrosting\DS . \UserFrosting\CONFIG_DIR_NAME); $locator->registerStream('extra', '', \UserFrosting\DS . \UserFrosting\EXTRA_DIR_NAME); $locator->registerStream('factories', '', \UserFrosting\DS . \UserFrosting\FACTORY_DIR_NAME); $locator->registerStream('locale', '', \UserFrosting\DS . \UserFrosting\LOCALE_DIR_NAME); $locator->registerStream('routes', '', \UserFrosting\DS . \UserFrosting\ROUTE_DIR_NAME); $locator->registerStream('schema', '', \UserFrosting\DS . \UserFrosting\SCHEMA_DIR_NAME); $locator->registerStream('templates', '', \UserFrosting\DS . \UserFrosting\TEMPLATE_DIR_NAME); + $locator->registerStream('seeds', '', \UserFrosting\SEEDS_DIR); + $locator->registerStream('migrations', '', \UserFrosting\MIGRATIONS_DIR); + } } From eb2ec33a063621a4614adedc46bda5cc0cacc97f Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 22:09:03 -0500 Subject: [PATCH 206/237] Streams doesn't require the `\UserFrosting\DS` with new locator It actually doesn't make sense, as on Unix it would be seen as absolute path within sprinkle location. This scenario is ignored by ResourceLocator. --- app/sprinkles/core/src/Bakery/BuildAssets.php | 2 +- app/sprinkles/core/src/Core.php | 16 +++++++++------- .../src/ServicesProvider/ServicesProvider.php | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/app/sprinkles/core/src/Bakery/BuildAssets.php b/app/sprinkles/core/src/Bakery/BuildAssets.php index 1301e7698..032ed0a8a 100644 --- a/app/sprinkles/core/src/Bakery/BuildAssets.php +++ b/app/sprinkles/core/src/Bakery/BuildAssets.php @@ -54,7 +54,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->checkNodeVersion(false); $this->checkNpmVersion(false); - // Set $path + // Set $buildPath. We'll use the aboslute path for this task $this->buildPath = \UserFrosting\ROOT_DIR . \UserFrosting\DS . \UserFrosting\BUILD_DIR_NAME; // Delete cached data is requested diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index 6ab0bafa0..41218b2ba 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -127,13 +127,15 @@ protected function registerStreams() $locator->registerStream('session', '', \UserFrosting\APP_DIR . \UserFrosting\DS . \UserFrosting\SESSION_DIR_NAME, true); // Register core locator sprinkle streams - $locator->registerStream('config', '', \UserFrosting\DS . \UserFrosting\CONFIG_DIR_NAME); - $locator->registerStream('extra', '', \UserFrosting\DS . \UserFrosting\EXTRA_DIR_NAME); - $locator->registerStream('factories', '', \UserFrosting\DS . \UserFrosting\FACTORY_DIR_NAME); - $locator->registerStream('locale', '', \UserFrosting\DS . \UserFrosting\LOCALE_DIR_NAME); - $locator->registerStream('routes', '', \UserFrosting\DS . \UserFrosting\ROUTE_DIR_NAME); - $locator->registerStream('schema', '', \UserFrosting\DS . \UserFrosting\SCHEMA_DIR_NAME); - $locator->registerStream('templates', '', \UserFrosting\DS . \UserFrosting\TEMPLATE_DIR_NAME); + $locator->registerStream('config', '', \UserFrosting\CONFIG_DIR_NAME); + $locator->registerStream('extra', '', \UserFrosting\EXTRA_DIR_NAME); + $locator->registerStream('factories', '', \UserFrosting\FACTORY_DIR_NAME); + $locator->registerStream('locale', '', \UserFrosting\LOCALE_DIR_NAME); + $locator->registerStream('routes', '', \UserFrosting\ROUTE_DIR_NAME); + $locator->registerStream('schema', '', \UserFrosting\SCHEMA_DIR_NAME); + $locator->registerStream('templates', '', \UserFrosting\TEMPLATE_DIR_NAME); + + // Register core sprinkle class streams $locator->registerStream('seeds', '', \UserFrosting\SEEDS_DIR); $locator->registerStream('migrations', '', \UserFrosting\MIGRATIONS_DIR); diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index cc9504bef..3296cb067 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -128,7 +128,7 @@ public function register(ContainerInterface $container) $locator->registerStream('assets', 'vendor', \UserFrosting\BOWER_ASSET_DIR, true); $locator->registerStream('assets', 'vendor', \UserFrosting\NPM_ASSET_DIR, true); $locator->registerStream('assets', 'vendor', \UserFrosting\BROWSERIFIED_ASSET_DIR, true); - $locator->registerStream('assets', '', \UserFrosting\DS . \UserFrosting\ASSET_DIR_NAME); + $locator->registerStream('assets', '', \UserFrosting\ASSET_DIR_NAME); $baseUrl = $config['site.uri.public'] . '/' . $config['assets.raw.path']; From 3ae268687da2821b362e8f7d245c9ee296633db7 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 22:28:16 -0500 Subject: [PATCH 207/237] Move route initialization from system to core sprinkle... ...as router service is located in the core sprinkle --- CHANGELOG.md | 1 + app/sprinkles/core/src/Core.php | 13 ++++++++++++- app/system/UserFrosting.php | 3 --- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e823c3fb7..108865634 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Sprinkle list in the bakery `debug` command to uses the new `sprinkle:list` table - `routerCacheFile` config now only contains filename. Locator is used to find the full path - Moved some constants from `app/defines.php` to `app/sprinkles/core/defines.php` +- Move route initialization from system to core sprinkle as router service is located in the core sprinkle ### Fix - Fix for `Test` Bakery command diff --git a/app/sprinkles/core/src/Core.php b/app/sprinkles/core/src/Core.php index 41218b2ba..e786a1ac7 100644 --- a/app/sprinkles/core/src/Core.php +++ b/app/sprinkles/core/src/Core.php @@ -44,7 +44,8 @@ public static function getSubscribedEvents() return [ 'onSprinklesInitialized' => ['onSprinklesInitialized', 0], 'onSprinklesRegisterServices' => ['onSprinklesRegisterServices', 0], - 'onAddGlobalMiddleware' => ['onAddGlobalMiddleware', 0] + 'onAddGlobalMiddleware' => ['onAddGlobalMiddleware', 0], + 'onAppInitialize' => ['onAppInitialize', 0] ]; } @@ -103,6 +104,16 @@ public function onSprinklesRegisterServices() $sh->register(); } + /** + * Register routes + * + * @param Event $event + */ + public function onAppInitialize(Event $event) + { + $this->ci->router->loadRoutes($event->getApp()); + } + /** * Add CSRF middleware. * diff --git a/app/system/UserFrosting.php b/app/system/UserFrosting.php index 2c29cbb09..b784d6fe1 100644 --- a/app/system/UserFrosting.php +++ b/app/system/UserFrosting.php @@ -149,9 +149,6 @@ protected function setupApp() $this->fireEvent('onAppInitialize', $slimAppEvent); - // Set up all routes - $this->ci->router->loadRoutes($this->app); - // Add global middleware $this->fireEvent('onAddGlobalMiddleware', $slimAppEvent); } From cc736edf10984b151fca9f08c1676828ed9ad088 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 26 Jan 2019 23:14:45 -0500 Subject: [PATCH 208/237] Fix path issue on Windows --- CHANGELOG.md | 4 +--- app/defines.php | 4 ++-- .../src/ServicesProvider/ServicesProvider.php | 3 ++- app/system/Sprinkle/SprinkleManager.php | 13 ++++++------ app/tests/Unit/SprinkleManagerTest.php | 20 ++++++++++--------- 5 files changed, 23 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 108865634..9773cc657 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,9 +33,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added specific tests for sprinkleManager with 100% test coverage - Ignore existing `package-lock.json` which caused incorrect dependencies to be installed when upgrading from older versions of UserFrosting. - Vendor assets not found in production mode - -### Deprecated -- `UserFrosting\APP_DIR_NAME` : Use `UserFrosting\APP_DIR` instead. +- Fix path issue on Windows ## 4.2.0-beta.1 diff --git a/app/defines.php b/app/defines.php index bdfb996ff..00b2a5b51 100755 --- a/app/defines.php +++ b/app/defines.php @@ -28,14 +28,14 @@ define('UserFrosting\ROOT_DIR', realpath(__DIR__ . '/..')); // Names of app directories -define('UserFrosting\APP_DIR_NAME', basename(__DIR__)); //@deprecated; Use `UserFrosting\APP_DIR` instead +define('UserFrosting\APP_DIR_NAME', basename(__DIR__)); define('UserFrosting\SPRINKLES_DIR_NAME', 'sprinkles'); // Names of src directories within Sprinkles define('UserFrosting\SRC_DIR_NAME', 'src'); // Full path to Sprinkles directory -define('UserFrosting\SPRINKLES_DIR', APP_DIR . DS . SPRINKLES_DIR_NAME); +define('UserFrosting\SPRINKLES_DIR', APP_DIR_NAME . DS . SPRINKLES_DIR_NAME); // Full path to sprinkles schema file define('UserFrosting\SPRINKLES_SCHEMA_FILE', APP_DIR . DS . 'sprinkles.json'); diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 3296cb067..6f6846b13 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -698,8 +698,9 @@ public function register(ContainerInterface $container) $sprinkles = $c->sprinkleManager->getSprinkleNames(); // Add Sprinkles' templates namespaces + // TODO : Use locator foreach ($sprinkles as $sprinkle) { - $path = \UserFrosting\SPRINKLES_DIR . \UserFrosting\DS . + $path = \UserFrosting\APP_DIR . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . $sprinkle . \UserFrosting\DS . \UserFrosting\TEMPLATE_DIR_NAME . \UserFrosting\DS; diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index 670c2027a..d5f1f0cad 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -34,7 +34,7 @@ class SprinkleManager protected $sprinkles = []; /** - * @var string The full absolute base path to the sprinkles directory. + * @var string Relaive path to the sprinkles directory. Will be used to register the location with the ResourceLocator */ protected $sprinklesPath = \UserFrosting\SPRINKLES_DIR . \UserFrosting\DS; @@ -60,7 +60,7 @@ public function addResources() } /** - * Register a sprinkle as a locator location + * Register a sprinkle as a locator location, using relative path to the sprinkle * @param string $sprinkleName */ public function addSprinkleResources($sprinkleName) @@ -85,12 +85,13 @@ public function getSprinklePath($sprinkleName) } // Get path and make sure it exist - $path = $this->getSprinklesPath() . $sprinkle; - if (!file_exists($path)) { - throw new FileNotFoundException("Sprinkle `$sprinkleName` should be found at `$path`, but that directory doesn't exist."); + $relPath = $this->getSprinklesPath() . $sprinkle; + $fullpath = \UserFrosting\ROOT_DIR . \UserFrosting\DS . $relPath; + if (!file_exists($fullpath)) { + throw new FileNotFoundException("Sprinkle `$sprinkleName` should be found at `$fullpath`, but that directory doesn't exist."); } - return $path; + return $relPath; } /** diff --git a/app/tests/Unit/SprinkleManagerTest.php b/app/tests/Unit/SprinkleManagerTest.php index c6ee90edc..d8953f70f 100644 --- a/app/tests/Unit/SprinkleManagerTest.php +++ b/app/tests/Unit/SprinkleManagerTest.php @@ -134,16 +134,16 @@ public function testIsAvailable($sprinkleName, $isAvailable, SprinkleManager $sp /** * @depends testInitFromSchema * @param string $sprinkleName - * @param bool $path * @param SprinkleManager $sprinkleManager - * @testWith ["foo", "/data/foo"] - * ["bar", "/data/bar"] - * ["test", "/data/test"] + * @testWith ["foo"] + * ["bar"] + * ["test"] */ - public function testGetSprinklePath($sprinkleName, $path, SprinkleManager $sprinkleManager) + public function testGetSprinklePath($sprinkleName, SprinkleManager $sprinkleManager) { - $sprinkleManager->setSprinklesPath(__DIR__ . '/data/'); - $this->assertSame(__DIR__ . $path, $sprinkleManager->getSprinklePath($sprinkleName)); + $basePath = 'app/tests/Unit/data/'; + $sprinkleManager->setSprinklesPath($basePath); + $this->assertSame($basePath . $sprinkleName, $sprinkleManager->getSprinklePath($sprinkleName)); } /** @@ -154,7 +154,8 @@ public function testGetSprinklePath($sprinkleName, $path, SprinkleManager $sprin */ public function testGetSprinklePathWherePathDoesntExist(SprinkleManager $sprinkleManager) { - $sprinkleManager->setSprinklesPath(__DIR__ . '/foo/'); + $basePath = 'app/tests/Unit/foo/'; + $sprinkleManager->setSprinklesPath($basePath); $sprinkleManager->getSprinklePath('foo'); } @@ -193,7 +194,8 @@ class_alias('foo', 'UserFrosting\Sprinkle\Test\ServicesProvider\ServicesProvider */ public function testAddResources(SprinkleManager $sprinkleManager) { - $sprinkleManager->setSprinklesPath(__DIR__ . '/data/'); + $basePath = 'app/tests/Unit/data/'; + $sprinkleManager->setSprinklesPath($basePath); $sprinkleManager->addResources(); } From 9f668f560ac2f97f03948ad18309e0503c17b2f3 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sun, 27 Jan 2019 15:23:41 +1100 Subject: [PATCH 209/237] - Updated docker documentation - Minor clean up of unneeded docker configurations --- docker-compose-testdb.yml | 1 - docker-compose.yml | 1 - docker/README.md | 62 +++++++++++++++++++++------------------ docker/php/Dockerfile | 1 - 4 files changed, 34 insertions(+), 31 deletions(-) diff --git a/docker-compose-testdb.yml b/docker-compose-testdb.yml index b40530c95..ba9d845d7 100644 --- a/docker-compose-testdb.yml +++ b/docker-compose-testdb.yml @@ -74,7 +74,6 @@ services: working_dir: /app command: -V node: - image: node:alpine build: context: ./docker/node volumes: diff --git a/docker-compose.yml b/docker-compose.yml index b5dc75645..6c7f9a397 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -54,7 +54,6 @@ services: command: -V node: - image: node:alpine build: context: ./docker/node volumes: diff --git a/docker/README.md b/docker/README.md index e97cfac06..0c00f2496 100644 --- a/docker/README.md +++ b/docker/README.md @@ -1,48 +1,54 @@ # Docker Development Environment +>This is also documented at [UserFrosting Learn](https://learn.userfrosting.com/installation/environment/docker). + First, install [Docker Compose](https://docs.docker.com/compose/install/). Second, initialize a new UserFrosting project: -1. Clone the repository `git clone https://github.com/userfrosting/UserFrosting.git .` and change into that directory `cd userfrosting` -1. Run `cp app/sprinkles.example.json app/sprinkles.json` or upload your own (also upload your sprinkles if you have some) -2. Run `sudo chown -R 33 app/{logs,cache,sessions}` (Changes the user to the www-data user of the image, more information [here](https://serversforhackers.com/c/dckr-file-permissions) ) -2. Run `sudo docker-compose run composer install` to install all composer modules. -3. Run `sudo docker-compose run node npm install` to install all npm modules. + +1. Copy `app/sprinkles.example.json` to `app/sprinkles.json` +2. Run `chmod 777 app/{logs,cache,sessions}` to fix file permissions for web server. (NOTE: File + permissions should be properly secured in a production environment!) +3. Run `docker-compose run composer install --ignore-platform-reqs --no-scripts` to install all composer modules. (https://hub.docker.com/_/composer) Sometimes dependencies or Composer scripts require the availability of certain PHP extensions. You can work around this as follows: Pass the `--ignore-platform-reqs and --no-scripts` flags to install or update +4. Run `docker-compose run node npm install` to install all npm modules. +5. Run `docker-compose run composer update --ignore-platform-reqs --no-scripts` to install remaining composer modules Now you can start up the entire Nginx + PHP + MySQL stack using docker with: - $ sudo docker-compose up -d + $ docker-compose up -d + +the `-d` flag will launch this in the background so you can continue to use the terminal window. On the first run you need to init the database (your container name may be different depending on the name of your root directory): + + $ docker exec -it -u www-data userfrosting_php_1 bash -c 'php bakery migrate' -On the first run you need to init the database (Be sure to execute this in the same directory, `${PWD##*/}` is a statement to get your current working directorys name. Docker uses it to name your container): +You also need to setup the first admin user (again, your container name may be different depending on the name of your root directory): - $ sudo docker exec -it -u www-data ${PWD##*/}_php_1 bash -c 'php bakery migrate' - -You also need to setup the first admin user (again, `${PWD##*/}` is a statement to get your current working directorys name): + $ docker exec -it -u www-data userfrosting_php_1 bash -c 'php bakery create-admin' - $ sudo docker exec -it -u www-data ${PWD##*/}_php_1 bash -c 'php bakery create-admin' +Now visit `http://localhost:8591/` to see your UserFrosting homepage! -Now visit http://localhost:8570/ to see your UserFrosting homepage! +**Paste these into a bash file and execute it!** -**This is not (yet) meant for production!!** +``` +chmod 777 app/{logs,cache,sessions} +docker-compose build --force-rm --no-cache +docker-compose run composer install --ignore-platform-reqs --no-scripts +docker-compose run node npm install +docker-compose run composer update --ignore-platform-reqs --no-scripts +docker-compose up -d +echo -n "Enter Docker Container Name --> " +read docker_container +docker exec -it -u www-data $docker_container bash -c 'php bakery migrate' +docker exec -it -u www-data $docker_container bash -c 'php bakery create-admin' +``` + +**This is not (yet) meant for production!** You may be tempted to run with this in production but this setup has not been security-hardened. For example: -- Database is exposed on port 8571 so you can access MySQL using your favorite client at localhost:8571. However, +- Database is exposed on port 8593 so you can access MySQL using your favorite client at localhost:8593. However, the way Docker exposes this actually bypasses common firewalls like `ufw` so this should not be exposed in production. - Database credentials are hard-coded so obviously not secure. - File permissions may be more open than necessary. +- HTTPS not implemented fully - It just hasn't been thoroughly tested in the capacity of being a production system. - -## Updating your code -As you might guessed you will have to run - - $ sudo docker exec -it -u www-data userfrosting_php_1 bash -c 'php bakery migrate' - -again if you want to migrate tables. -You can change `php bakery migrate` to other `bakery` commands as well. -Be aware that the userfrosting container doesn't know about npm! -Similary for composer: - - $ sudo docker-compose run composer update - -See the [Docker](https://docs.docker.com/engine) and [Docker-compose documentation](https://docs.docker.com/compose/) for more details. diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index c85e87089..010d9a264 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -8,5 +8,4 @@ RUN apt-get update && apt-get install -y \ && docker-php-ext-install -j$(nproc) gd \ && docker-php-ext-install -j$(nproc) pdo pdo_mysql \ && docker-php-ext-install -j$(nproc) zip -RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer WORKDIR /app \ No newline at end of file From 274a54527e9149d8c69d7d7933ad971e138b1fe9 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sun, 27 Jan 2019 15:34:27 +1100 Subject: [PATCH 210/237] Added docker changes to `CHANGELOG` --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae2e1561c..db0302432 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,10 +10,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ### Added - `sprinkle:list` bakery command - `NoCache` middleware to prevent caching of routes with dynamic content +- Sample test environment for Docker ### Changed - Sprinkle list in the bakery `debug` command to uses the new `sprinkle:list` table - `routerCacheFile` config now only contains filename. Locator is used to find the full path +- Updated Docker integration ### Fix - Fix for `Test` Bakery command @@ -31,6 +33,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Added specific tests for sprinkleManager with 100% test coverage - Ignore existing `package-lock.json` which caused incorrect dependencies to be installed when upgrading from older versions of UserFrosting. - Vendor assets not found in production mode +- Various Docker specific edge cases and misconfigurations ## 4.2.0-beta.1 From ac1490e0b593b965e6e2587ac3f19e1dbf1cc7c4 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Tue, 29 Jan 2019 20:39:13 -0500 Subject: [PATCH 211/237] Typo --- build/before_install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/before_install.sh b/build/before_install.sh index 57250a8a7..b37ce4f7b 100644 --- a/build/before_install.sh +++ b/build/before_install.sh @@ -28,7 +28,7 @@ if [ "$DB" == "pgsql" ] ; then psql -c "GRANT ALL PRIVILEGES ON DATABASE userfrosting TO postgres;" -U postgres printf "UF_MODE=\"debug\"\nDB_DRIVER=\"pgsql\"\nDB_HOST=\"localhost\"\nDB_PORT=\"5432\"\nDB_NAME=\"userfrosting\"\nDB_USER=\"postgres\"\nDB_PASSWORD=\"\"\nTEST_DB=\"default\"\n" > app/.env fi -s + # # set up sqlite # From cdc2d7175d0adb84ae1dc334b71520fbafe92b04 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 16 Feb 2019 16:05:24 +1100 Subject: [PATCH 212/237] Simplified `ClassMapper->staticMethod` implementation --- app/sprinkles/core/src/Util/ClassMapper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/Util/ClassMapper.php b/app/sprinkles/core/src/Util/ClassMapper.php index 4c3edc3b7..a6abff99e 100644 --- a/app/sprinkles/core/src/Util/ClassMapper.php +++ b/app/sprinkles/core/src/Util/ClassMapper.php @@ -90,6 +90,6 @@ public function staticMethod($identifier, $methodName) $params = array_slice(func_get_args(), 2); - return call_user_func_array("$className::$methodName", $params); + return $className::$methodName(...$params); } } From 55dd43326afe23714038bee8c97cbee6dbbfc5fc Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 16 Feb 2019 16:23:51 +1100 Subject: [PATCH 213/237] Simplified `ClassMapper->createInstance` implementation --- app/sprinkles/core/src/Util/ClassMapper.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/app/sprinkles/core/src/Util/ClassMapper.php b/app/sprinkles/core/src/Util/ClassMapper.php index a6abff99e..b7314e781 100644 --- a/app/sprinkles/core/src/Util/ClassMapper.php +++ b/app/sprinkles/core/src/Util/ClassMapper.php @@ -37,10 +37,7 @@ public function createInstance($identifier) $params = array_slice(func_get_args(), 1); - // We must use reflection in PHP < 5.6. See http://stackoverflow.com/questions/8734522/dynamically-call-class-with-variable-number-of-parameters-in-the-constructor - $reflection = new \ReflectionClass($className); - - return $reflection->newInstanceArgs($params); + return new $className(...$params); } /** From d4157ce10764913fdec4b2f7dbef98d2e170972d Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 16 Feb 2019 17:46:35 +1100 Subject: [PATCH 214/237] Updated docker configuration - Use Alpine for PHP - Removed commands from composer and node services in favour of on-demand command execution - Updated docker README --- docker-compose.yml | 2 -- docker/README.md | 10 ++++++---- docker/php/Dockerfile | 18 ++++++++++++------ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 6c7f9a397..76edb2a59 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -51,7 +51,6 @@ services: volumes: - .:/app working_dir: /app - command: -V node: build: @@ -59,7 +58,6 @@ services: volumes: - .:/app working_dir: /app/build - command: npm run uf-assets-install volumes: userfrosting-db: diff --git a/docker/README.md b/docker/README.md index 0c00f2496..7ce433f49 100644 --- a/docker/README.md +++ b/docker/README.md @@ -12,6 +12,7 @@ Second, initialize a new UserFrosting project: 3. Run `docker-compose run composer install --ignore-platform-reqs --no-scripts` to install all composer modules. (https://hub.docker.com/_/composer) Sometimes dependencies or Composer scripts require the availability of certain PHP extensions. You can work around this as follows: Pass the `--ignore-platform-reqs and --no-scripts` flags to install or update 4. Run `docker-compose run node npm install` to install all npm modules. 5. Run `docker-compose run composer update --ignore-platform-reqs --no-scripts` to install remaining composer modules +6. Run `docker-compose run node npm run uf-assets-install` to install all frontend vendor assets. Now you can start up the entire Nginx + PHP + MySQL stack using docker with: @@ -19,11 +20,11 @@ Now you can start up the entire Nginx + PHP + MySQL stack using docker with: the `-d` flag will launch this in the background so you can continue to use the terminal window. On the first run you need to init the database (your container name may be different depending on the name of your root directory): - $ docker exec -it -u www-data userfrosting_php_1 bash -c 'php bakery migrate' + $ docker exec -it -u www-data userfrosting_php_1 sh -c 'php bakery migrate' You also need to setup the first admin user (again, your container name may be different depending on the name of your root directory): - $ docker exec -it -u www-data userfrosting_php_1 bash -c 'php bakery create-admin' + $ docker exec -it -u www-data userfrosting_php_1 sh -c 'php bakery create-admin' Now visit `http://localhost:8591/` to see your UserFrosting homepage! @@ -35,11 +36,12 @@ docker-compose build --force-rm --no-cache docker-compose run composer install --ignore-platform-reqs --no-scripts docker-compose run node npm install docker-compose run composer update --ignore-platform-reqs --no-scripts +docker-compose run node npm run uf-assets-install docker-compose up -d echo -n "Enter Docker Container Name --> " read docker_container -docker exec -it -u www-data $docker_container bash -c 'php bakery migrate' -docker exec -it -u www-data $docker_container bash -c 'php bakery create-admin' +docker exec -it -u www-data $docker_container sh -c 'php bakery migrate' +docker exec -it -u www-data $docker_container sh -c 'php bakery create-admin' ``` **This is not (yet) meant for production!** diff --git a/docker/php/Dockerfile b/docker/php/Dockerfile index 010d9a264..951928abb 100644 --- a/docker/php/Dockerfile +++ b/docker/php/Dockerfile @@ -1,11 +1,17 @@ -FROM php:7.2-fpm -RUN apt-get update && apt-get install -y \ - libfreetype6-dev \ - libjpeg62-turbo-dev \ +FROM php:7.2-fpm-alpine + +# Update and install packages +RUN apk update +RUN apk add \ + freetype-dev \ + libjpeg-turbo-dev \ libpng-dev \ - zip \ - && docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ + zip + +# Install and configure PHP extensions +RUN docker-php-ext-configure gd --with-freetype-dir=/usr/include/ --with-jpeg-dir=/usr/include/ \ && docker-php-ext-install -j$(nproc) gd \ && docker-php-ext-install -j$(nproc) pdo pdo_mysql \ && docker-php-ext-install -j$(nproc) zip + WORKDIR /app \ No newline at end of file From 32b34d99ea6b3759c24031f902b5e93e213abea0 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 16 Feb 2019 18:26:52 +1100 Subject: [PATCH 215/237] Simplified results file generation logic --- build/gulpfile.esm.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/build/gulpfile.esm.js b/build/gulpfile.esm.js index 1da2ca193..2a5c62b18 100644 --- a/build/gulpfile.esm.js +++ b/build/gulpfile.esm.js @@ -261,29 +261,29 @@ export function bundle() { rawConfig.BundlesVirtualBasePath = "./assets/"; // Bundle results callback + /** + * + * @param {Map Date: Sat, 16 Feb 2019 18:30:24 +1100 Subject: [PATCH 216/237] Updated npm dependency versions - Bower updated to address vulnerability --- build/package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/package.json b/build/package.json index be8c8340f..9dad746e1 100755 --- a/build/package.json +++ b/build/package.json @@ -2,10 +2,10 @@ "private": true, "dependencies": { "@userfrosting/browserify-dependencies": "^1.0.0-beta.1", - "@userfrosting/gulp-bundle-assets": "^3.0.0-rc.1", + "@userfrosting/gulp-bundle-assets": "^3.0.0-rc.2", "@userfrosting/merge-package-dependencies": "^1.2.1", - "bower": "^1.8.4", - "esm": "^3.0.84", + "bower": "^1.8.8", + "esm": "^3.2.5", "del": "^3.0.0", "dotenv": "^6.2.0", "gulp": "^4.0.0", From 86821fba4ddeb468072c3c8a8a79312bc4cd1928 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sat, 16 Feb 2019 18:44:25 +1100 Subject: [PATCH 217/237] Harmonise docker-compose files --- docker-compose-testdb.yml | 9 +++++++-- docker-compose.yml | 3 +++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/docker-compose-testdb.yml b/docker-compose-testdb.yml index ba9d845d7..7813b06b3 100644 --- a/docker-compose-testdb.yml +++ b/docker-compose-testdb.yml @@ -24,6 +24,7 @@ services: - ./docker/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini networks: - backend + nginx: restart: unless-stopped tty: true @@ -41,6 +42,7 @@ services: networks: - frontend - backend + ufmysql: image: mysql:5.7 networks: @@ -54,6 +56,7 @@ services: - 8593:3306 volumes: - userfrosting-db:/var/lib/mysql + ufmysqltest: image: mysql:5.7 networks: @@ -67,24 +70,26 @@ services: - 8594:3306 volumes: - userfrosting-test-db:/var/lib/mysql + composer: image: "composer" volumes: - .:/app working_dir: /app - command: -V + node: build: context: ./docker/node volumes: - .:/app working_dir: /app/build - command: npm run uf-assets-install + volumes: userfrosting-db: driver: local userfrosting-test-db: driver: local + networks: frontend: backend: \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 76edb2a59..6ff08f6f5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -17,6 +17,7 @@ services: - ./docker/php/custom.ini:/usr/local/etc/php/conf.d/custom.ini networks: - backend + nginx: restart: unless-stopped tty: true @@ -33,6 +34,7 @@ services: networks: - frontend - backend + ufmysql: image: mysql:5.7 networks: @@ -46,6 +48,7 @@ services: - 8593:3306 volumes: - userfrosting-db:/var/lib/mysql + composer: image: "composer" volumes: From 16f7e8fe576054af5b4f905f17cdcd10120fa15c Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 16 Feb 2019 15:31:08 -0500 Subject: [PATCH 218/237] Use locator instead of hardcoded path --- .../src/ServicesProvider/ServicesProvider.php | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index 6f6846b13..ee72a56c3 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -689,24 +689,17 @@ public function register(ContainerInterface $container) * @return \Slim\Views\Twig */ $container['view'] = function ($c) { - $templatePaths = $c->locator->findResources('templates://', true, false); - $view = new Twig($templatePaths); + /** @var \UserFrosting\UniformResourceLocator\ResourceLocator $locator */ + $locator = $c->locator; + $templatePaths = $locator->getResources('templates://'); + $view = new Twig($templatePaths); $loader = $view->getLoader(); - $sprinkles = $c->sprinkleManager->getSprinkleNames(); - // Add Sprinkles' templates namespaces - // TODO : Use locator - foreach ($sprinkles as $sprinkle) { - $path = \UserFrosting\APP_DIR . \UserFrosting\DS . \UserFrosting\SPRINKLES_DIR_NAME . \UserFrosting\DS . - $sprinkle . \UserFrosting\DS . - \UserFrosting\TEMPLATE_DIR_NAME . \UserFrosting\DS; - - if (is_dir($path)) { - $loader->addPath($path, $sprinkle); - } + foreach (array_reverse($templatePaths) as $templateResource) { + $loader->addPath($templateResource->getAbsolutePath(), $templateResource->getLocation()->getName()); } $twig = $view->getEnvironment(); From 1abeb655e6cad2c41d664d0037d1b2708ad31e03 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 16 Feb 2019 16:29:10 -0500 Subject: [PATCH 219/237] Changed back sprinkle path constant to full app dir path. Fixes error in CheckEnvironment. Revert part of cc736edf10984b151fca9f08c1676828ed9ad088. Windows path should be fixed from URI package update. --- app/defines.php | 2 +- app/system/Sprinkle/SprinkleManager.php | 13 ++++++------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/app/defines.php b/app/defines.php index 00b2a5b51..c2ffc676e 100755 --- a/app/defines.php +++ b/app/defines.php @@ -35,7 +35,7 @@ define('UserFrosting\SRC_DIR_NAME', 'src'); // Full path to Sprinkles directory -define('UserFrosting\SPRINKLES_DIR', APP_DIR_NAME . DS . SPRINKLES_DIR_NAME); +define('UserFrosting\SPRINKLES_DIR', APP_DIR . DS . SPRINKLES_DIR_NAME); // Full path to sprinkles schema file define('UserFrosting\SPRINKLES_SCHEMA_FILE', APP_DIR . DS . 'sprinkles.json'); diff --git a/app/system/Sprinkle/SprinkleManager.php b/app/system/Sprinkle/SprinkleManager.php index d5f1f0cad..f1479d699 100644 --- a/app/system/Sprinkle/SprinkleManager.php +++ b/app/system/Sprinkle/SprinkleManager.php @@ -34,7 +34,7 @@ class SprinkleManager protected $sprinkles = []; /** - * @var string Relaive path to the sprinkles directory. Will be used to register the location with the ResourceLocator + * @var string Path to the sprinkles directory. Will be used to register the location with the ResourceLocator */ protected $sprinklesPath = \UserFrosting\SPRINKLES_DIR . \UserFrosting\DS; @@ -60,7 +60,7 @@ public function addResources() } /** - * Register a sprinkle as a locator location, using relative path to the sprinkle + * Register a sprinkle as a locator location * @param string $sprinkleName */ public function addSprinkleResources($sprinkleName) @@ -85,13 +85,12 @@ public function getSprinklePath($sprinkleName) } // Get path and make sure it exist - $relPath = $this->getSprinklesPath() . $sprinkle; - $fullpath = \UserFrosting\ROOT_DIR . \UserFrosting\DS . $relPath; - if (!file_exists($fullpath)) { - throw new FileNotFoundException("Sprinkle `$sprinkleName` should be found at `$fullpath`, but that directory doesn't exist."); + $path = $this->getSprinklesPath() . $sprinkle; + if (!file_exists($path)) { + throw new FileNotFoundException("Sprinkle `$sprinkleName` should be found at `$path`, but that directory doesn't exist."); } - return $relPath; + return $path; } /** From a9ff4c7aa77ab8040c76f04980be6172405d8bf1 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 16 Feb 2019 17:14:46 -0500 Subject: [PATCH 220/237] Change seeds so they extends the base Seed --- app/sprinkles/account/src/Database/Seeds/DefaultGroups.php | 4 ++-- .../account/src/Database/Seeds/DefaultPermissions.php | 4 ++-- app/sprinkles/account/src/Database/Seeds/DefaultRoles.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php b/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php index 7d6c5a4d6..3888caa67 100644 --- a/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php +++ b/app/sprinkles/account/src/Database/Seeds/DefaultGroups.php @@ -9,13 +9,13 @@ namespace UserFrosting\Sprinkle\Account\Database\Seeds; -use UserFrosting\Sprinkle\Core\Database\Seeder\SeedInterface; +use UserFrosting\Sprinkle\Core\Database\Seeder\BaseSeed; use UserFrosting\Sprinkle\Account\Database\Models\Group; /** * Seeder for the default groups */ -class DefaultGroups implements SeedInterface +class DefaultGroups extends BaseSeed { /** * {@inheritdoc} diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php b/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php index 8df28e0a8..c29eb55dd 100644 --- a/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php +++ b/app/sprinkles/account/src/Database/Seeds/DefaultPermissions.php @@ -9,7 +9,7 @@ namespace UserFrosting\Sprinkle\Account\Database\Seeds; -use UserFrosting\Sprinkle\Core\Database\Seeder\SeedInterface; +use UserFrosting\Sprinkle\Core\Database\Seeder\BaseSeed; use UserFrosting\Sprinkle\Account\Database\Models\Permission; use UserFrosting\Sprinkle\Account\Database\Models\Role; use UserFrosting\Sprinkle\Core\Facades\Seeder; @@ -17,7 +17,7 @@ /** * Seeder for the default permissions */ -class DefaultPermissions implements SeedInterface +class DefaultPermissions extends BaseSeed { /** * {@inheritdoc} diff --git a/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php b/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php index b6dcd4447..a3edead75 100644 --- a/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php +++ b/app/sprinkles/account/src/Database/Seeds/DefaultRoles.php @@ -9,13 +9,13 @@ namespace UserFrosting\Sprinkle\Account\Database\Seeds; -use UserFrosting\Sprinkle\Core\Database\Seeder\SeedInterface; +use UserFrosting\Sprinkle\Core\Database\Seeder\BaseSeed; use UserFrosting\Sprinkle\Account\Database\Models\Role; /** * Seeder for the default roles */ -class DefaultRoles implements SeedInterface +class DefaultRoles extends BaseSeed { /** * {@inheritdoc} From 5483ff2eb9b4727e7e48b7ac21a1d2e341d24219 Mon Sep 17 00:00:00 2001 From: Louis Charette Date: Sat, 16 Feb 2019 17:28:39 -0500 Subject: [PATCH 221/237] Fix issue with Twig "Cannot use object of type UserFrosting\UniformResourceLocator\Resource as array in Filesystem.php" --- app/sprinkles/core/src/ServicesProvider/ServicesProvider.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php index ee72a56c3..f1634249a 100755 --- a/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php +++ b/app/sprinkles/core/src/ServicesProvider/ServicesProvider.php @@ -694,7 +694,7 @@ public function register(ContainerInterface $container) $locator = $c->locator; $templatePaths = $locator->getResources('templates://'); - $view = new Twig($templatePaths); + $view = new Twig(array_map('strval', $templatePaths)); $loader = $view->getLoader(); // Add Sprinkles' templates namespaces From 1f2723e9af2fc55f40fcf8eced3bd764517a3e16 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sun, 17 Feb 2019 09:31:37 +1100 Subject: [PATCH 222/237] Consistent use of UF's NotFoundException --- .../src/Controller/AccountController.php | 4 +-- .../admin/src/Controller/GroupController.php | 14 +++++----- .../src/Controller/PermissionController.php | 6 ++--- .../admin/src/Controller/RoleController.php | 20 +++++++------- .../admin/src/Controller/UserController.php | 26 +++++++++---------- 5 files changed, 35 insertions(+), 35 deletions(-) diff --git a/app/sprinkles/account/src/Controller/AccountController.php b/app/sprinkles/account/src/Controller/AccountController.php index 15982e0f9..46d890896 100644 --- a/app/sprinkles/account/src/Controller/AccountController.php +++ b/app/sprinkles/account/src/Controller/AccountController.php @@ -13,7 +13,6 @@ use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Slim\Exception\NotFoundException as NotFoundException; use UserFrosting\Fortress\RequestDataTransformer; use UserFrosting\Fortress\RequestSchema; use UserFrosting\Fortress\ServerSideValidator; @@ -28,6 +27,7 @@ use UserFrosting\Sprinkle\Core\Util\Captcha; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; +use UserFrosting\Support\Exception\NotFoundException; /** * Controller class for /account/* URLs. Handles account-related activities, including login, registration, password recovery, and account settings. @@ -489,7 +489,7 @@ public function pageRegister(Request $request, Response $response, $args) $localePathBuilder = $this->ci->localePathBuilder; if (!$config['site.registration.enabled']) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authenticate\Authenticator $authenticator */ diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index 924762818..ec981094c 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -12,7 +12,6 @@ use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Slim\Exception\NotFoundException; use UserFrosting\Fortress\RequestDataTransformer; use UserFrosting\Fortress\RequestSchema; use UserFrosting\Fortress\ServerSideValidator; @@ -21,6 +20,7 @@ use UserFrosting\Sprinkle\Core\Controller\SimpleController; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; +use UserFrosting\Support\Exception\NotFoundException; /** * Controller class for group-related requests, including listing groups, CRUD for groups, etc. @@ -147,7 +147,7 @@ public function delete(Request $request, Response $response, $args) // If the group doesn't exist, return 404 if (!$group) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -243,7 +243,7 @@ public function getInfo(Request $request, Response $response, $args) // If the group doesn't exist, return 404 if (!$group) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } // Get group @@ -311,7 +311,7 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg // If the group no longer exists, forward to main group listing page if (!$group) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -431,7 +431,7 @@ public function getModalEdit(Request $request, Response $response, $args) // If the group doesn't exist, return 404 if (!$group) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -494,7 +494,7 @@ public function getUsers(Request $request, Response $response, $args) // If the group no longer exists, forward to main group listing page if (!$group) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } // GET parameters @@ -659,7 +659,7 @@ public function updateInfo(Request $request, Response $response, $args) $group = $this->getGroupFromParams($args); if (!$group) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Support\Repository\Repository $config */ diff --git a/app/sprinkles/admin/src/Controller/PermissionController.php b/app/sprinkles/admin/src/Controller/PermissionController.php index fd92d0da5..402442ef6 100644 --- a/app/sprinkles/admin/src/Controller/PermissionController.php +++ b/app/sprinkles/admin/src/Controller/PermissionController.php @@ -11,9 +11,9 @@ use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Slim\Exception\NotFoundException; use UserFrosting\Sprinkle\Core\Controller\SimpleController; use UserFrosting\Support\Exception\ForbiddenException; +use UserFrosting\Support\Exception\NotFoundException; /** * Controller class for permission-related requests, including listing permissions, CRUD for permissions, etc. @@ -56,7 +56,7 @@ public function getInfo(Request $request, Response $response, $args) // If the permission doesn't exist, return 404 if (!$permission) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } // Get permission @@ -182,7 +182,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the permission doesn't exist, return 404 if (!$permission) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } return $this->ci->view->render($response, 'pages/permission.html.twig', [ diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index 86e433f43..8656b8d39 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -12,7 +12,6 @@ use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Slim\Exception\NotFoundException; use UserFrosting\Fortress\RequestDataTransformer; use UserFrosting\Fortress\RequestSchema; use UserFrosting\Fortress\ServerSideValidator; @@ -21,6 +20,7 @@ use UserFrosting\Sprinkle\Core\Controller\SimpleController; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; +use UserFrosting\Support\Exception\NotFoundException; /** * Controller class for role-related requests, including listing roles, CRUD for roles, etc. @@ -147,7 +147,7 @@ public function delete(Request $request, Response $response, $args) // If the role doesn't exist, return 404 if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -242,7 +242,7 @@ public function getInfo(Request $request, Response $response, $args) // If the role doesn't exist, return 404 if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } // Get role @@ -310,7 +310,7 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg // If the role no longer exists, forward to main role listing page if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -438,7 +438,7 @@ public function getModalEdit(Request $request, Response $response, $args) // If the role doesn't exist, return 404 if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -508,7 +508,7 @@ public function getModalEditPermissions(Request $request, Response $response, $a // If the role doesn't exist, return 404 if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -549,7 +549,7 @@ public function getPermissions(Request $request, Response $response, $args) // If the role no longer exists, forward to main role listing page if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } // GET parameters @@ -600,7 +600,7 @@ public function getUsers(Request $request, Response $response, $args) // If the role doesn't exist, return 404 if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -765,7 +765,7 @@ public function updateInfo(Request $request, Response $response, $args) $role = $this->getRoleFromParams($args); if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Support\Repository\Repository $config */ @@ -886,7 +886,7 @@ public function updateField(Request $request, Response $response, $args) $role = $this->getRoleFromParams($args); if (!$role) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } // Get key->value pair from URL and request body diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index 0b12fac7e..8692400e2 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -13,7 +13,6 @@ use Illuminate\Database\Capsule\Manager as Capsule; use Psr\Http\Message\ResponseInterface as Response; use Psr\Http\Message\ServerRequestInterface as Request; -use Slim\Exception\NotFoundException; use UserFrosting\Fortress\RequestDataTransformer; use UserFrosting\Fortress\RequestSchema; use UserFrosting\Fortress\ServerSideValidator; @@ -25,6 +24,7 @@ use UserFrosting\Sprinkle\Core\Mail\TwigMailMessage; use UserFrosting\Support\Exception\BadRequestException; use UserFrosting\Support\Exception\ForbiddenException; +use UserFrosting\Support\Exception\NotFoundException; /** * Controller class for user-related requests, including listing users, CRUD for users, etc. @@ -192,7 +192,7 @@ public function createPasswordReset(Request $request, Response $response, $args) $user = $this->getUserFromParams($args); if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -265,7 +265,7 @@ public function delete(Request $request, Response $response, $args) // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -333,7 +333,7 @@ public function getActivities(Request $request, Response $response, $args) // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -384,7 +384,7 @@ public function getInfo(Request $request, Response $response, $args) // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -476,7 +476,7 @@ public function getModalConfirmDelete(Request $request, Response $response, $arg // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -624,7 +624,7 @@ public function getModalEdit(Request $request, Response $response, $args) // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -717,7 +717,7 @@ public function getModalEditPassword(Request $request, Response $response, $args // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -768,7 +768,7 @@ public function getModalEditRoles(Request $request, Response $response, $args) // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ @@ -808,7 +808,7 @@ public function getPermissions(Request $request, Response $response, $args) // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } // GET parameters @@ -856,7 +856,7 @@ public function getRoles(Request $request, Response $response, $args) // If the user doesn't exist, return 404 if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Core\Util\ClassMapper $classMapper */ @@ -1077,7 +1077,7 @@ public function updateInfo(Request $request, Response $response, $args) $user = $this->getUserFromParams($args); if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } /** @var \UserFrosting\Support\Repository\Repository $config */ @@ -1205,7 +1205,7 @@ public function updateField(Request $request, Response $response, $args) $user = $this->getUserFromParams($args); if (!$user) { - throw new NotFoundException($request, $response); + throw new NotFoundException(); } // Get key->value pair from URL and request body From 6464e0491d1125bce05113f41fa55f25ac283c36 Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sun, 17 Feb 2019 16:36:38 +1100 Subject: [PATCH 223/237] Return 404 when group, role, or user not found --- app/sprinkles/admin/src/Controller/GroupController.php | 4 +--- app/sprinkles/admin/src/Controller/RoleController.php | 4 +--- app/sprinkles/admin/src/Controller/UserController.php | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index ec981094c..f5821739f 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -547,9 +547,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the group no longer exists, forward to main group listing page if (!$group) { - $redirectPage = $this->ci->router->pathFor('uri_groups'); - - return $response->withRedirect($redirectPage); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index 8656b8d39..22e2ec2ee 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -653,9 +653,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the role no longer exists, forward to main role listing page if (!$role) { - $redirectPage = $this->ci->router->pathFor('uri_roles'); - - return $response->withRedirect($redirectPage); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index 8692400e2..23bbf612b 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -909,9 +909,7 @@ public function pageInfo(Request $request, Response $response, $args) // If the user no longer exists, forward to main user listing page if (!$user) { - $usersPage = $this->ci->router->pathFor('uri_users'); - - return $response->withRedirect($usersPage); + throw new NotFoundException(); } /** @var \UserFrosting\Sprinkle\Account\Authorize\AuthorizationManager $authorizer */ From 38c860552de66f320d322c1548323cb4001046cd Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sun, 17 Feb 2019 16:42:47 +1100 Subject: [PATCH 224/237] Prevent button clicks from clearing ufTable slug --- .../assets/userfrosting/js/pages/register.js | 4 ++- .../assets/userfrosting/js/pages/dashboard.js | 4 ++- .../assets/userfrosting/js/widgets/groups.js | 14 ++++++--- .../assets/userfrosting/js/widgets/roles.js | 16 +++++++--- .../assets/userfrosting/js/widgets/users.js | 30 ++++++++++++++----- 5 files changed, 50 insertions(+), 18 deletions(-) diff --git a/app/sprinkles/account/assets/userfrosting/js/pages/register.js b/app/sprinkles/account/assets/userfrosting/js/pages/register.js index 255bb287f..0ba3286a1 100644 --- a/app/sprinkles/account/assets/userfrosting/js/pages/register.js +++ b/app/sprinkles/account/assets/userfrosting/js/pages/register.js @@ -8,7 +8,9 @@ */ $(document).ready(function() { // TOS modal - $(this).find('.js-show-tos').click(function() { + $(this).find('.js-show-tos').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/account/tos", msgTarget: $("#alerts-page") diff --git a/app/sprinkles/admin/assets/userfrosting/js/pages/dashboard.js b/app/sprinkles/admin/assets/userfrosting/js/pages/dashboard.js index e1d644a57..109045f73 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/pages/dashboard.js +++ b/app/sprinkles/admin/assets/userfrosting/js/pages/dashboard.js @@ -6,7 +6,9 @@ */ $(document).ready(function() { - $('.js-clear-cache').click(function() { + $('.js-clear-cache').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/dashboard/clear-cache", ajaxParams: { diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js index b90121831..e4a2ef0b4 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js @@ -63,7 +63,9 @@ function bindGroupButtons(el) { * Buttons that launch a modal dialog */ // Edit group details button - el.find('.js-group-edit').click(function() { + el.find('.js-group-edit').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/groups/edit", ajaxParams: { @@ -76,7 +78,9 @@ function bindGroupButtons(el) { }); // Delete group button - el.find('.js-group-delete').click(function() { + el.find('.js-group-delete').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/groups/confirm-delete", ajaxParams: { @@ -85,7 +89,7 @@ function bindGroupButtons(el) { msgTarget: $("#alerts-page") }); - $("body").on('renderSuccess.ufModal', function (data) { + $("body").on('renderSuccess.ufModal', function () { var modal = $(this).ufModal('getModal'); var form = modal.find('.js-form'); @@ -100,7 +104,9 @@ function bindGroupButtons(el) { function bindGroupCreationButton(el) { // Link create button - el.find('.js-group-create').click(function() { + el.find('.js-group-create').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/groups/create", msgTarget: $("#alerts-page") diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js index 2edff7172..bfb8afbf6 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js @@ -51,7 +51,9 @@ function bindRoleButtons(el) { */ // Manage permissions button - el.find('.js-role-permissions').click(function() { + el.find('.js-role-permissions').click(function(e) { + e.preventDefault(); + var slug = $(this).data('slug'); $("body").ufModal({ sourceUrl: site.uri.public + "/modals/roles/permissions", @@ -100,7 +102,9 @@ function bindRoleButtons(el) { * Buttons that launch a modal dialog */ // Edit role details button - el.find('.js-role-edit').click(function() { + el.find('.js-role-edit').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/roles/edit", ajaxParams: { @@ -113,7 +117,9 @@ function bindRoleButtons(el) { }); // Delete role button - el.find('.js-role-delete').click(function() { + el.find('.js-role-delete').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/roles/confirm-delete", ajaxParams: { @@ -137,7 +143,9 @@ function bindRoleButtons(el) { function bindRoleCreationButton(el) { // Link create button - el.find('.js-role-create').click(function() { + el.find('.js-role-create').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/roles/create", msgTarget: $("#alerts-page") diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js index 8668f44ef..cc33bbf40 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js @@ -132,7 +132,9 @@ function updateUser(userName, fieldName, fieldValue) { * Buttons that launch a modal dialog */ // Edit general user details button - el.find('.js-user-edit').click(function() { + el.find('.js-user-edit').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/users/edit", ajaxParams: { @@ -145,7 +147,9 @@ function updateUser(userName, fieldName, fieldValue) { }); // Manage user roles button - el.find('.js-user-roles').click(function() { + el.find('.js-user-roles').click(function(e) { + e.preventDefault(); + var userName = $(this).data('user_name'); $("body").ufModal({ sourceUrl: site.uri.public + "/modals/users/roles", @@ -191,7 +195,9 @@ function updateUser(userName, fieldName, fieldValue) { }); // Change user password button - el.find('.js-user-password').click(function() { + el.find('.js-user-password').click(function(e) { + e.preventDefault(); + var userName = $(this).data('user_name'); $("body").ufModal({ sourceUrl: site.uri.public + "/modals/users/password", @@ -201,7 +207,7 @@ function updateUser(userName, fieldName, fieldValue) { msgTarget: $("#alerts-page") }); - $("body").on('renderSuccess.ufModal', function (data) { + $("body").on('renderSuccess.ufModal', function () { var modal = $(this).ufModal('getModal'); var form = modal.find('.js-form'); @@ -216,7 +222,9 @@ function updateUser(userName, fieldName, fieldValue) { toggleChangePasswordMode(modal, userName, 'link'); // On submission, submit either the PUT request, or POST for a password reset, depending on the toggle state - modal.find("input[name='change_password_mode']").click(function() { + modal.find("input[name='change_password_mode']").click(function(e) { + e.preventDefault(); + var changePasswordMode = $(this).val(); toggleChangePasswordMode(modal, userName, changePasswordMode); }); @@ -224,7 +232,9 @@ function updateUser(userName, fieldName, fieldValue) { }); // Delete user button - el.find('.js-user-delete').click(function() { + el.find('.js-user-delete').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/users/confirm-delete", ajaxParams: { @@ -248,7 +258,9 @@ function updateUser(userName, fieldName, fieldValue) { /** * Direct action buttons */ - el.find('.js-user-activate').click(function() { + el.find('.js-user-activate').click(function(e) { + e.preventDefault(); + var btn = $(this); updateUser(btn.data('user_name'), 'flag_verified', '1'); }); @@ -266,7 +278,9 @@ function updateUser(userName, fieldName, fieldValue) { function bindUserCreationButton(el) { // Link create button - el.find('.js-user-create').click(function() { + el.find('.js-user-create').click(function(e) { + e.preventDefault(); + $("body").ufModal({ sourceUrl: site.uri.public + "/modals/users/create", msgTarget: $("#alerts-page") From 589c1e3ffaf6fe651d09f870ca715d0630b5e9bc Mon Sep 17 00:00:00 2001 From: Jordan Mele Date: Sun, 17 Feb 2019 18:16:14 +1100 Subject: [PATCH 225/237] #932 Implemented redirect on deletion option for user, role, and group pages --- .../admin/assets/userfrosting/js/pages/group.js | 2 +- .../admin/assets/userfrosting/js/pages/role.js | 2 +- .../admin/assets/userfrosting/js/pages/user.js | 2 +- .../admin/assets/userfrosting/js/widgets/groups.js | 11 ++++++++--- .../admin/assets/userfrosting/js/widgets/roles.js | 11 ++++++++--- .../admin/assets/userfrosting/js/widgets/users.js | 12 ++++++++---- .../admin/src/Controller/GroupController.php | 3 ++- .../admin/src/Controller/RoleController.php | 3 ++- .../admin/src/Controller/UserController.php | 3 ++- app/sprinkles/admin/templates/pages/group.html.twig | 7 ++++--- app/sprinkles/admin/templates/pages/role.html.twig | 7 ++++--- app/sprinkles/admin/templates/pages/user.html.twig | 5 +++-- 12 files changed, 44 insertions(+), 24 deletions(-) diff --git a/app/sprinkles/admin/assets/userfrosting/js/pages/group.js b/app/sprinkles/admin/assets/userfrosting/js/pages/group.js index a1ca959a5..66b35b9fc 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/pages/group.js +++ b/app/sprinkles/admin/assets/userfrosting/js/pages/group.js @@ -9,7 +9,7 @@ $(document).ready(function() { // Control buttons - bindGroupButtons($("#view-group")); + bindGroupButtons($("#view-group"), { delete_redirect: page.delete_redirect }); // Table of users in this group $("#widget-group-users").ufTable({ diff --git a/app/sprinkles/admin/assets/userfrosting/js/pages/role.js b/app/sprinkles/admin/assets/userfrosting/js/pages/role.js index 8dae7f50f..bcec074da 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/pages/role.js +++ b/app/sprinkles/admin/assets/userfrosting/js/pages/role.js @@ -9,7 +9,7 @@ $(document).ready(function() { // Control buttons - bindRoleButtons($("#view-role")); + bindRoleButtons($("#view-role"), { delete_redirect: page.delete_redirect }); $("#widget-role-permissions").ufTable({ dataUrl: site.uri.public + '/api/roles/r/' + page.role_slug + '/permissions', diff --git a/app/sprinkles/admin/assets/userfrosting/js/pages/user.js b/app/sprinkles/admin/assets/userfrosting/js/pages/user.js index 70acf7c92..fd328c8b3 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/pages/user.js +++ b/app/sprinkles/admin/assets/userfrosting/js/pages/user.js @@ -9,7 +9,7 @@ $(document).ready(function() { // Control buttons - bindUserButtons($("#view-user")); + bindUserButtons($("#view-user"), { delete_redirect: page.delete_redirect }); // Table of activities $("#widget-user-activities").ufTable({ diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js index e4a2ef0b4..47c9d15e7 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/groups.js @@ -53,8 +53,12 @@ function attachGroupForm() { /** * Link group action buttons, for example in a table or on a specific group's page. + * @param {module:jQuery} el jQuery wrapped element to target. + * @param {{delete_redirect: string}} options Options used to modify behaviour of button actions. */ -function bindGroupButtons(el) { +function bindGroupButtons(el, options) { + if (!options) options = {}; + /** * Link row buttons after table is loaded. */ @@ -95,8 +99,9 @@ function bindGroupButtons(el) { form.ufForm() .on("submitSuccess.ufForm", function() { - // Reload page on success - window.location.reload(); + // Navigate or reload page on success + if (options.delete_redirect) window.location.href = options.delete_redirect; + else window.location.reload(); }); }); }); diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js index bfb8afbf6..0fcfb6abd 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/roles.js @@ -44,8 +44,12 @@ function attachRoleForm() { /** * Link role action buttons, for example in a table or on a specific role's page. + * @param {module:jQuery} el jQuery wrapped element to target. + * @param {{delete_redirect: string}} options Options used to modify behaviour of button actions. */ -function bindRoleButtons(el) { +function bindRoleButtons(el, options) { + if (!options) options = {}; + /** * Link row buttons after table is loaded. */ @@ -134,8 +138,9 @@ function bindRoleButtons(el) { form.ufForm() .on("submitSuccess.ufForm", function() { - // Reload page on success - window.location.reload(); + // Navigate or reload page on success + if (options.delete_redirect) window.location.href = options.delete_redirect; + else window.location.reload(); }); }); }); diff --git a/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js b/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js index cc33bbf40..6c05b91c7 100644 --- a/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js +++ b/app/sprinkles/admin/assets/userfrosting/js/widgets/users.js @@ -125,8 +125,11 @@ function updateUser(userName, fieldName, fieldValue) { /** * Link user action buttons, for example in a table or on a specific user's page. + * @param {module:jQuery} el jQuery wrapped element to target. + * @param {{delete_redirect: string}} options Options used to modify behaviour of button actions. */ - function bindUserButtons(el) { + function bindUserButtons(el, options) { + if (!options) options = {}; /** * Buttons that launch a modal dialog @@ -243,14 +246,15 @@ function updateUser(userName, fieldName, fieldValue) { msgTarget: $("#alerts-page") }); - $("body").on('renderSuccess.ufModal', function (data) { + $("body").on('renderSuccess.ufModal', function () { var modal = $(this).ufModal('getModal'); var form = modal.find('.js-form'); form.ufForm() .on("submitSuccess.ufForm", function() { - // Reload page on success - window.location.reload(); + // Navigate or reload page on success + if (options.delete_redirect) window.location.href = options.delete_redirect; + else window.location.reload(); }); }); }); diff --git a/app/sprinkles/admin/src/Controller/GroupController.php b/app/sprinkles/admin/src/Controller/GroupController.php index f5821739f..0e97b7df3 100644 --- a/app/sprinkles/admin/src/Controller/GroupController.php +++ b/app/sprinkles/admin/src/Controller/GroupController.php @@ -601,7 +601,8 @@ public function pageInfo(Request $request, Response $response, $args) return $this->ci->view->render($response, 'pages/group.html.twig', [ 'group' => $group, 'fields' => $fields, - 'tools' => $editButtons + 'tools' => $editButtons, + 'delete_redirect' => $this->ci->router->pathFor('uri_groups') ]); } diff --git a/app/sprinkles/admin/src/Controller/RoleController.php b/app/sprinkles/admin/src/Controller/RoleController.php index 22e2ec2ee..3232e266c 100644 --- a/app/sprinkles/admin/src/Controller/RoleController.php +++ b/app/sprinkles/admin/src/Controller/RoleController.php @@ -707,7 +707,8 @@ public function pageInfo(Request $request, Response $response, $args) return $this->ci->view->render($response, 'pages/role.html.twig', [ 'role' => $role, 'fields' => $fields, - 'tools' => $editButtons + 'tools' => $editButtons, + 'delete_redirect' => $this->ci->router->pathFor('uri_roles') ]); } diff --git a/app/sprinkles/admin/src/Controller/UserController.php b/app/sprinkles/admin/src/Controller/UserController.php index 23bbf612b..d6293ec49 100644 --- a/app/sprinkles/admin/src/Controller/UserController.php +++ b/app/sprinkles/admin/src/Controller/UserController.php @@ -1020,7 +1020,8 @@ public function pageInfo(Request $request, Response $response, $args) 'locales' => $locales, 'fields' => $fields, 'tools' => $editButtons, - 'widgets' => $widgets + 'widgets' => $widgets, + 'delete_redirect' => $this->ci->router->pathFor('uri_users') ]); } diff --git a/app/sprinkles/admin/templates/pages/group.html.twig b/app/sprinkles/admin/templates/pages/group.html.twig index bf4d275b2..35bf233f0 100644 --- a/app/sprinkles/admin/templates/pages/group.html.twig +++ b/app/sprinkles/admin/templates/pages/group.html.twig @@ -88,11 +88,12 @@