diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index dc0cc13..83e80e6 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -22,5 +22,3 @@ jobs: composer install php artisan migrate --force php artisan cache:clear - npm ci - npm run build diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..a7135b9 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,32 @@ +name: CI-BUILD-TEST +on: [ push, pull_request ] + +jobs: + coding-standard: + name: Coding Standard + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: '8.3' + coverage: none + + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + + - name: Cache composer dependencies + uses: actions/cache@v1 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-composer- + + - name: Install dependencies + run: composer install --no-progress --no-suggest --prefer-dist --no-interaction --ignore-platform-reqs + + - name: Check coding style + run: composer cs-check diff --git a/app/Models/Achievement.php b/app/Models/Achievement.php new file mode 100644 index 0000000..468fb1f --- /dev/null +++ b/app/Models/Achievement.php @@ -0,0 +1,23 @@ +hasMany(Challenge::class); + } + + public function image() + { + return $this->belongsTo(Image::class); + } +} diff --git a/app/Models/Category.php b/app/Models/Category.php new file mode 100644 index 0000000..db6da00 --- /dev/null +++ b/app/Models/Category.php @@ -0,0 +1,18 @@ +hasMany(Challenge::class); + } +} diff --git a/app/Models/Challenge.php b/app/Models/Challenge.php new file mode 100644 index 0000000..b9fa4bb --- /dev/null +++ b/app/Models/Challenge.php @@ -0,0 +1,41 @@ +belongsToMany(User::class, 'users_challenges'); + } + + public function image() + { + return $this->belongsTo(Image::class); + } + + public function category() + { + return $this->belongsTo(Category::class); + } + + public function achievement() + { + return $this->belongsTo(Achievement::class); + } +} diff --git a/app/Models/Image.php b/app/Models/Image.php new file mode 100644 index 0000000..ca530ba --- /dev/null +++ b/app/Models/Image.php @@ -0,0 +1,28 @@ +hasMany(User::class); + } + + public function challenges() + { + return $this->hasMany(Challenge::class); + } + + public function achievements() + { + return $this->hasMany(Achievement::class); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index 3dfbd80..958bb48 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -19,10 +19,24 @@ class User extends Authenticatable */ protected $fillable = [ 'name', + 'surname', 'email', 'password', + 'about', + 'image_id', + 'is_admin' ]; + public function challenges() + { + return $this->belongsToMany(Challenge::class, 'users_challenges'); + } + + public function image() + { + return $this->belongsTo(Image::class); + } + /** * The attributes that should be hidden for serialization. * diff --git a/composer.json b/composer.json index efc0f7e..82ad9c4 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,9 @@ "laravel/sail": "^1.26", "mockery/mockery": "^1.6", "nunomaduro/collision": "^8.1", - "phpunit/phpunit": "^11.0.1" + "phpunit/phpunit": "^11.0.1", + "slevomat/coding-standard": "^8.15", + "squizlabs/php_codesniffer": "^3.10" }, "autoload": { "psr-4": { @@ -50,7 +52,9 @@ "dev": [ "Composer\\Config::disableProcessTimeout", "npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite" - ] + ], + "cs-check": "phpcs", + "cs-fix": "phpcbf" }, "extra": { "laravel": { @@ -63,7 +67,8 @@ "sort-packages": true, "allow-plugins": { "pestphp/pest-plugin": true, - "php-http/discovery": true + "php-http/discovery": true, + "dealerdirect/phpcodesniffer-composer-installer": true } }, "minimum-stability": "stable", diff --git a/composer.lock b/composer.lock index 5cfa736..d3240a6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "071932fc77f95477cb014ca9c6d9152d", + "content-hash": "58d2205fe8a263a17422e92586c0298c", "packages": [ { "name": "anourvalar/eloquent-serialize", @@ -7455,6 +7455,84 @@ } ], "packages-dev": [ + { + "name": "dealerdirect/phpcodesniffer-composer-installer", + "version": "v1.0.0", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/composer-installer.git", + "reference": "4be43904336affa5c2f70744a348312336afd0da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/composer-installer/zipball/4be43904336affa5c2f70744a348312336afd0da", + "reference": "4be43904336affa5c2f70744a348312336afd0da", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^1.0 || ^2.0", + "php": ">=5.4", + "squizlabs/php_codesniffer": "^2.0 || ^3.1.0 || ^4.0" + }, + "require-dev": { + "composer/composer": "*", + "ext-json": "*", + "ext-zip": "*", + "php-parallel-lint/php-parallel-lint": "^1.3.1", + "phpcompatibility/php-compatibility": "^9.0", + "yoast/phpunit-polyfills": "^1.0" + }, + "type": "composer-plugin", + "extra": { + "class": "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\Plugin" + }, + "autoload": { + "psr-4": { + "PHPCSStandards\\Composer\\Plugin\\Installers\\PHPCodeSniffer\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Franck Nijhof", + "email": "franck.nijhof@dealerdirect.com", + "homepage": "http://www.frenck.nl", + "role": "Developer / IT Manager" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/composer-installer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer Standards Composer Installer Plugin", + "homepage": "http://www.dealerdirect.com", + "keywords": [ + "PHPCodeSniffer", + "PHP_CodeSniffer", + "code quality", + "codesniffer", + "composer", + "installer", + "phpcbf", + "phpcs", + "plugin", + "qa", + "quality", + "standard", + "standards", + "style guide", + "stylecheck", + "tests" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/composer-installer/issues", + "source": "https://github.com/PHPCSStandards/composer-installer" + }, + "time": "2023-01-05T11:28:13+00:00" + }, { "name": "fakerphp/faker", "version": "v1.23.1", @@ -8204,6 +8282,53 @@ }, "time": "2022-02-21T01:04:05+00:00" }, + { + "name": "phpstan/phpdoc-parser", + "version": "1.33.0", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpdoc-parser.git", + "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpdoc-parser/zipball/82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "reference": "82a311fd3690fb2bf7b64d5c98f912b3dd746140", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "require-dev": { + "doctrine/annotations": "^2.0", + "nikic/php-parser": "^4.15", + "php-parallel-lint/php-parallel-lint": "^1.2", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^1.5", + "phpstan/phpstan-phpunit": "^1.1", + "phpstan/phpstan-strict-rules": "^1.0", + "phpunit/phpunit": "^9.5", + "symfony/process": "^5.2" + }, + "type": "library", + "autoload": { + "psr-4": { + "PHPStan\\PhpDocParser\\": [ + "src/" + ] + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPDoc parser with support for nullable, intersection and generic types", + "support": { + "issues": "https://github.com/phpstan/phpdoc-parser/issues", + "source": "https://github.com/phpstan/phpdoc-parser/tree/1.33.0" + }, + "time": "2024-10-13T11:25:22+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "11.0.7", @@ -9550,6 +9675,151 @@ ], "time": "2024-10-09T05:16:32+00:00" }, + { + "name": "slevomat/coding-standard", + "version": "8.15.0", + "source": { + "type": "git", + "url": "https://github.com/slevomat/coding-standard.git", + "reference": "7d1d957421618a3803b593ec31ace470177d7817" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/slevomat/coding-standard/zipball/7d1d957421618a3803b593ec31ace470177d7817", + "reference": "7d1d957421618a3803b593ec31ace470177d7817", + "shasum": "" + }, + "require": { + "dealerdirect/phpcodesniffer-composer-installer": "^0.6.2 || ^0.7 || ^1.0", + "php": "^7.2 || ^8.0", + "phpstan/phpdoc-parser": "^1.23.1", + "squizlabs/php_codesniffer": "^3.9.0" + }, + "require-dev": { + "phing/phing": "2.17.4", + "php-parallel-lint/php-parallel-lint": "1.3.2", + "phpstan/phpstan": "1.10.60", + "phpstan/phpstan-deprecation-rules": "1.1.4", + "phpstan/phpstan-phpunit": "1.3.16", + "phpstan/phpstan-strict-rules": "1.5.2", + "phpunit/phpunit": "8.5.21|9.6.8|10.5.11" + }, + "type": "phpcodesniffer-standard", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + } + }, + "autoload": { + "psr-4": { + "SlevomatCodingStandard\\": "SlevomatCodingStandard/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Slevomat Coding Standard for PHP_CodeSniffer complements Consistence Coding Standard by providing sniffs with additional checks.", + "keywords": [ + "dev", + "phpcs" + ], + "support": { + "issues": "https://github.com/slevomat/coding-standard/issues", + "source": "https://github.com/slevomat/coding-standard/tree/8.15.0" + }, + "funding": [ + { + "url": "https://github.com/kukulich", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/slevomat/coding-standard", + "type": "tidelift" + } + ], + "time": "2024-03-09T15:20:58+00:00" + }, + { + "name": "squizlabs/php_codesniffer", + "version": "3.10.3", + "source": { + "type": "git", + "url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git", + "reference": "62d32998e820bddc40f99f8251958aed187a5c9c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/62d32998e820bddc40f99f8251958aed187a5c9c", + "reference": "62d32998e820bddc40f99f8251958aed187a5c9c", + "shasum": "" + }, + "require": { + "ext-simplexml": "*", + "ext-tokenizer": "*", + "ext-xmlwriter": "*", + "php": ">=5.4.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.3.4" + }, + "bin": [ + "bin/phpcbf", + "bin/phpcs" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Greg Sherwood", + "role": "Former lead" + }, + { + "name": "Juliette Reinders Folmer", + "role": "Current lead" + }, + { + "name": "Contributors", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer/graphs/contributors" + } + ], + "description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.", + "homepage": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "keywords": [ + "phpcs", + "standards", + "static analysis" + ], + "support": { + "issues": "https://github.com/PHPCSStandards/PHP_CodeSniffer/issues", + "security": "https://github.com/PHPCSStandards/PHP_CodeSniffer/security/policy", + "source": "https://github.com/PHPCSStandards/PHP_CodeSniffer", + "wiki": "https://github.com/PHPCSStandards/PHP_CodeSniffer/wiki" + }, + "funding": [ + { + "url": "https://github.com/PHPCSStandards", + "type": "github" + }, + { + "url": "https://github.com/jrfnl", + "type": "github" + }, + { + "url": "https://opencollective.com/php_codesniffer", + "type": "open_collective" + } + ], + "time": "2024-09-18T10:38:58+00:00" + }, { "name": "symfony/yaml", "version": "v7.1.5", @@ -9681,5 +9951,5 @@ "php": "^8.2" }, "platform-dev": [], - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.2.0" } diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 584104c..63d6747 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -1,5 +1,7 @@ id(); + $table->string('image_path'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('images'); + } +}; diff --git a/database/migrations/2024_10_25_213135_create_achievements_table.php b/database/migrations/2024_10_25_213135_create_achievements_table.php new file mode 100644 index 0000000..c7bf293 --- /dev/null +++ b/database/migrations/2024_10_25_213135_create_achievements_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('name'); + $table->text('description'); + $table->foreignId('image_id')->nullable()->constrained('images')->onDelete('set null'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('achievements'); + } +}; diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/2024_10_25_213720_create_users_table.php similarity index 80% rename from database/migrations/0001_01_01_000000_create_users_table.php rename to database/migrations/2024_10_25_213720_create_users_table.php index 05fb5d9..a4c0404 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/2024_10_25_213720_create_users_table.php @@ -14,9 +14,15 @@ public function up(): void Schema::create('users', function (Blueprint $table) { $table->id(); $table->string('name'); + $table->string('surname'); + $table->string('patronymic'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); + $table->text('about')->nullable(); + $table->foreignId('image_id')->nullable()->constrained('images')->onDelete('set null'); + $table->boolean('is_admin')->default(false); + $table->boolean('is_confirmed')->default(false); $table->rememberToken(); $table->timestamps(); }); diff --git a/database/migrations/2024_10_25_214120_create_challenges_table.php b/database/migrations/2024_10_25_214120_create_challenges_table.php new file mode 100644 index 0000000..64345c3 --- /dev/null +++ b/database/migrations/2024_10_25_214120_create_challenges_table.php @@ -0,0 +1,35 @@ +id(); + $table->string('name'); + $table->text('description'); + $table->dateTime('start_date'); + $table->dateTime('end_date'); + $table->text('result')->nullable(); + $table->timestamps(); + $table->foreignId('achievement_id')->nullable()->constrained('achievements')->onDelete('set null'); + $table->foreignId('image_id')->nullable()->constrained('images')->onDelete('set null'); + $table->string('type')->default(false); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('challenges'); + } +}; diff --git a/database/migrations/2024_10_25_214308_create_users_challenges_table.php b/database/migrations/2024_10_25_214308_create_users_challenges_table.php new file mode 100644 index 0000000..25f399f --- /dev/null +++ b/database/migrations/2024_10_25_214308_create_users_challenges_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); + $table->foreignId('challenge_id')->constrained('challenges')->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_challenges'); + } +}; diff --git a/database/migrations/2024_10_26_081158_create_users_achievements_table.php b/database/migrations/2024_10_26_081158_create_users_achievements_table.php new file mode 100755 index 0000000..39b0c2b --- /dev/null +++ b/database/migrations/2024_10_26_081158_create_users_achievements_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); + $table->foreignId('achievement_id')->constrained('achievements')->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_achievements'); + } +}; diff --git a/database/migrations/2024_10_26_081419_create_teams_table.php b/database/migrations/2024_10_26_081419_create_teams_table.php new file mode 100644 index 0000000..f536371 --- /dev/null +++ b/database/migrations/2024_10_26_081419_create_teams_table.php @@ -0,0 +1,30 @@ +id(); + $table->string('name'); + $table->text('description'); + $table->string('code'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('teams'); + } +}; diff --git a/database/migrations/2024_10_26_081833_create_users_teams_table.php b/database/migrations/2024_10_26_081833_create_users_teams_table.php new file mode 100644 index 0000000..d8bd152 --- /dev/null +++ b/database/migrations/2024_10_26_081833_create_users_teams_table.php @@ -0,0 +1,30 @@ +id(); + $table->foreignId('user_id')->constrained('users')->onDelete('cascade'); + $table->foreignId('team_id')->constrained('teams')->onDelete('cascade'); + $table->boolean('is_captain')->default(false); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('users_teams'); + } +}; diff --git a/database/migrations/2024_10_26_083853_create_teams_challenge_table.php b/database/migrations/2024_10_26_083853_create_teams_challenge_table.php new file mode 100644 index 0000000..d188941 --- /dev/null +++ b/database/migrations/2024_10_26_083853_create_teams_challenge_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('team_id')->constrained('teams')->onDelete('cascade'); + $table->foreignId('challenge_id')->constrained('challenges')->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('teams_challenge'); + } +}; diff --git a/database/migrations/2024_10_26_084324_create_teams_achievements_table.php b/database/migrations/2024_10_26_084324_create_teams_achievements_table.php new file mode 100644 index 0000000..49d8ee6 --- /dev/null +++ b/database/migrations/2024_10_26_084324_create_teams_achievements_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('team_id')->constrained('teams')->onDelete('cascade'); + $table->foreignId('achievement_id')->constrained('achievements')->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('teams_achievements'); + } +}; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index d01a0ef..392c776 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -1,5 +1,7 @@ + + Coding standard + + + + + + + + database/factories + database/seeders + routes + *\.blade\.php + *\.js + *\.ts + *\.vue + config/* + resources/* + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/routes/console.php b/routes/console.php index eff2ed2..12eea61 100644 --- a/routes/console.php +++ b/routes/console.php @@ -1,5 +1,7 @@