diff --git a/.env.example b/.env.example index 7defe3d8f..dd9912833 100644 --- a/.env.example +++ b/.env.example @@ -29,3 +29,8 @@ MIX_ALGOLIA_APP_ID="${ALGOLIA_APP_ID}" MIX_ALGOLIA_SECRET= MIX_ALGOLIA_THREADS_INDEX=threads MIX_ALGOLIA_ARTICLES_INDEX=articles + +TWITTER_CONSUMER_KEY= +TWITTER_CONSUMER_SECRET= +TWITTER_ACCESS_TOKEN= +TWITTER_ACCESS_SECRET= diff --git a/README.md b/README.md index f4781a671..387eafcf7 100644 --- a/README.md +++ b/README.md @@ -86,6 +86,19 @@ New threads will be automatically added to the index and threads which get edite `php artisan scout:flush App\\Models\\Thread` +### Twitter sharing (optional) + +To enable published articles to be automatically shared to on Twitter, you'll need to [create a Twitter app](https://developer.twitter.com/apps/). Once the app has been created, update the below variables in your `.env` file. The consumer key and secret and access token and secret can be found in the `Keys and tokens` section of the Twitter developers UI. + +``` +TWITTER_CONSUMER_KEY= +TWITTER_CONSUMER_SECRET= +TWITTER_ACCESS_TOKEN= +TWITTER_ACCESS_SECRET= +``` + +Approved articles are shared in the order they were submitted for approval. Articles are shared twice per day at 14:00 and 18:00 UTC. Once an article has been shared, it will not be shared again. + ## Maintainers The Laravel.io portal is currently maintained by [Dries Vints](https://github.com/driesvints) and [Joe Dixon](https://github.com/joedixon). If you have any questions please don't hesitate to create an issue on this repo. diff --git a/app/Console/Commands/PostArticleToTwitter.php b/app/Console/Commands/PostArticleToTwitter.php new file mode 100644 index 000000000..327e87f8a --- /dev/null +++ b/app/Console/Commands/PostArticleToTwitter.php @@ -0,0 +1,33 @@ +notifiable = $notifiable; + } + + public function handle(): void + { + if ($article = Article::nextForSharing()) { + $this->notifiable->notify(new PostArticleToTwitterNotification($article)); + + $article->markAsShared(); + } + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 9721403f2..aaf46ea4c 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -23,6 +23,7 @@ protected function schedule(Schedule $schedule) $schedule->command('schedule-monitor:sync')->dailyAt('04:56'); $schedule->command('schedule-monitor:clean')->daily(); $schedule->command('horizon:snapshot')->everyFiveMinutes(); + $schedule->command('post-article-to-twitter')->twiceDaily(14, 18); } /** diff --git a/app/Http/Requests/UpdateProfileRequest.php b/app/Http/Requests/UpdateProfileRequest.php index 6961209c5..23ea0dc25 100644 --- a/app/Http/Requests/UpdateProfileRequest.php +++ b/app/Http/Requests/UpdateProfileRequest.php @@ -12,6 +12,7 @@ public function rules() 'name' => 'required|max:255', 'email' => 'required|email|max:255|unique:users,email,'.Auth::id(), 'username' => 'required|alpha_dash|max:255|unique:users,username,'.Auth::id(), + 'twitter' => 'max:255|nullable|unique:users,twitter,'.Auth::id(), 'bio' => 'max:160', ]; } @@ -35,4 +36,9 @@ public function username(): string { return (string) $this->get('username'); } + + public function twitter(): ?string + { + return $this->get('twitter'); + } } diff --git a/app/Jobs/UpdateProfile.php b/app/Jobs/UpdateProfile.php index 1fedef474..a835afe3b 100644 --- a/app/Jobs/UpdateProfile.php +++ b/app/Jobs/UpdateProfile.php @@ -22,7 +22,7 @@ final class UpdateProfile public function __construct(User $user, array $attributes = []) { $this->user = $user; - $this->attributes = Arr::only($attributes, ['name', 'email', 'username', 'github_username', 'bio']); + $this->attributes = Arr::only($attributes, ['name', 'email', 'username', 'github_username', 'bio', 'twitter']); } public static function fromRequest(User $user, UpdateProfileRequest $request): self @@ -32,6 +32,7 @@ public static function fromRequest(User $user, UpdateProfileRequest $request): s 'email' => $request->email(), 'username' => strtolower($request->username()), 'bio' => trim(strip_tags($request->bio())), + 'twitter' => $request->twitter(), ]); } diff --git a/app/Listeners/StoreTweetIdentifier.php b/app/Listeners/StoreTweetIdentifier.php new file mode 100644 index 000000000..873d7fc3a --- /dev/null +++ b/app/Listeners/StoreTweetIdentifier.php @@ -0,0 +1,20 @@ +notification instanceof PostArticleToTwitter) { + $event->notification->article()->update([ + 'tweet_id' => $event->response->id, + ]); + } + } +} diff --git a/app/Models/Article.php b/app/Models/Article.php index 244b20d0d..d06649eed 100644 --- a/app/Models/Article.php +++ b/app/Models/Article.php @@ -35,8 +35,10 @@ final class Article extends Model 'original_url', 'slug', 'is_pinned', + 'tweet_id', 'submitted_at', 'approved_at', + 'shared_at', ]; /** @@ -45,6 +47,7 @@ final class Article extends Model protected $dates = [ 'submitted_at', 'approved_at', + 'shared_at', ]; public function id(): int @@ -84,7 +87,7 @@ public function series() public function updateSeries(Series $series = null): self { - if (is_null($series)) { + if ($series === null) { return $this->removeSeries(); } @@ -124,7 +127,7 @@ public function isSubmitted(): bool public function isNotSubmitted(): bool { - return is_null($this->submitted_at); + return $this->submitted_at === null; } public function isApproved(): bool @@ -134,7 +137,7 @@ public function isApproved(): bool public function isNotApproved(): bool { - return is_null($this->approved_at); + return $this->approved_at === null; } public function isPublished(): bool @@ -152,6 +155,16 @@ public function isPinned(): bool return (bool) $this->is_pinned; } + public function isNotShared(): bool + { + return $this->shared_at === null; + } + + public function isShared(): bool + { + return ! $this->isNotShared(); + } + public function isAwaitingApproval(): bool { return $this->isSubmitted() && $this->isNotApproved(); @@ -204,6 +217,16 @@ public function scopeNotPublished(Builder $query): Builder }); } + public function scopeShared(Builder $query): Builder + { + return $query->whereNotNull('shared_at'); + } + + public function scopeNotShared(Builder $query): Builder + { + return $query->whereNull('shared_at'); + } + public function scopeForTag(Builder $query, string $tag): Builder { return $query->whereHas('tagsRelation', function ($query) use ($tag) { @@ -272,4 +295,19 @@ public function splitBody($value) { return $this->split($value); } + + public function markAsShared() + { + $this->update([ + 'shared_at' => now(), + ]); + } + + public static function nextForSharing(): ?self + { + return self::notShared() + ->published() + ->orderBy('submitted_at', 'asc') + ->first(); + } } diff --git a/app/Notifications/PostArticleToTwitter.php b/app/Notifications/PostArticleToTwitter.php new file mode 100644 index 000000000..752ebb202 --- /dev/null +++ b/app/Notifications/PostArticleToTwitter.php @@ -0,0 +1,46 @@ +article = $article; + } + + public function via($notifiable) + { + return [TwitterChannel::class]; + } + + public function toTwitter($notifiable) + { + return new TwitterStatusUpdate($this->generateTweet()); + } + + public function generateTweet() + { + $title = $this->article->title(); + $url = route('articles.show', $this->article->slug()); + $author = $this->article->author(); + $author = $author->twitter() ? "@{$author->twitter()}" : $author->name(); + + return "{$title} by {$author}\n\n{$url}"; + } + + public function article() + { + return $this->article; + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 896695bd0..c8895e060 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -6,7 +6,9 @@ use App\Events\ReplyWasCreated; use App\Listeners\SendArticleApprovedNotification; use App\Listeners\SendNewReplyNotification; +use App\Listeners\StoreTweetIdentifier; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; +use Illuminate\Notifications\Events\NotificationSent; class EventServiceProvider extends ServiceProvider { @@ -22,5 +24,8 @@ class EventServiceProvider extends ServiceProvider ArticleWasApproved::class => [ SendArticleApprovedNotification::class, ], + NotificationSent::class => [ + StoreTweetIdentifier::class, + ], ]; } diff --git a/app/User.php b/app/User.php index 4a64aa8f5..8c6a44bd3 100644 --- a/app/User.php +++ b/app/User.php @@ -39,6 +39,7 @@ final class User extends Authenticatable implements MustVerifyEmail protected $fillable = [ 'name', 'email', + 'twitter', 'username', 'password', 'ip', @@ -84,6 +85,11 @@ public function githubUsername(): string return $this->github_username; } + public function twitter(): ?string + { + return $this->twitter; + } + public function gravatarUrl($size = 100): string { $hash = md5(strtolower(trim($this->email))); diff --git a/composer.json b/composer.json index 799a29264..f97d7ffaf 100644 --- a/composer.json +++ b/composer.json @@ -20,6 +20,7 @@ "laravel/framework": "^8.10", "laravel/horizon": "^5.2", "laravel/socialite": "^5.0", + "laravel-notification-channels/twitter": "^5.0", "laravel/tinker": "^2.0", "laravel/ui": "^3.0", "lasserafn/php-initial-avatar-generator": "^2.0", @@ -89,4 +90,4 @@ }, "minimum-stability": "dev", "prefer-stable": true -} +} \ No newline at end of file diff --git a/composer.lock b/composer.lock index 609bd2807..a4f7c22d1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,20 +4,81 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "53cc8748a36e14e2ee8c0810940665cd", + "content-hash": "0f9c389d0b91db2a70453fda01ffaf7d", "packages": [ + { + "name": "abraham/twitteroauth", + "version": "2.0.1", + "source": { + "type": "git", + "url": "https://github.com/abraham/twitteroauth.git", + "reference": "af6d0ba772731d4f83524fccb24281fe6149ef43" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/abraham/twitteroauth/zipball/af6d0ba772731d4f83524fccb24281fe6149ef43", + "reference": "af6d0ba772731d4f83524fccb24281fe6149ef43", + "shasum": "" + }, + "require": { + "composer/ca-bundle": "^1.2", + "ext-curl": "*", + "php": "^7.3 || ^7.4 || ^8.0" + }, + "require-dev": { + "php-vcr/php-vcr": "^1", + "php-vcr/phpunit-testlistener-vcr": "dev-php-8", + "phpmd/phpmd": "^2", + "phpunit/phpunit": "^8", + "squizlabs/php_codesniffer": "^3" + }, + "type": "library", + "autoload": { + "psr-4": { + "Abraham\\TwitterOAuth\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Abraham Williams", + "email": "abraham@abrah.am", + "homepage": "https://abrah.am", + "role": "Developer" + } + ], + "description": "The most popular PHP library for use with the Twitter OAuth REST API.", + "homepage": "https://twitteroauth.com", + "keywords": [ + "Twitter API", + "Twitter oAuth", + "api", + "oauth", + "rest", + "social", + "twitter" + ], + "support": { + "issues": "https://github.com/abraham/twitteroauth/issues", + "source": "https://github.com/abraham/twitteroauth" + }, + "time": "2020-12-02T01:37:06+00:00" + }, { "name": "algolia/algoliasearch-client-php", - "version": "2.7.1", + "version": "2.7.2", "source": { "type": "git", "url": "https://github.com/algolia/algoliasearch-client-php.git", - "reference": "19c0a6c1ef44c0aafaf6c6238c1509ebde2d1a35" + "reference": "a915109c76d5f4af67f10cd21855ea2d4c9aec9f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/algolia/algoliasearch-client-php/zipball/19c0a6c1ef44c0aafaf6c6238c1509ebde2d1a35", - "reference": "19c0a6c1ef44c0aafaf6c6238c1509ebde2d1a35", + "url": "https://api.github.com/repos/algolia/algoliasearch-client-php/zipball/a915109c76d5f4af67f10cd21855ea2d4c9aec9f", + "reference": "a915109c76d5f4af67f10cd21855ea2d4c9aec9f", "shasum": "" }, "require": { @@ -76,22 +137,22 @@ ], "support": { "issues": "https://github.com/algolia/algoliasearch-client-php/issues", - "source": "https://github.com/algolia/algoliasearch-client-php/tree/2.7.1" + "source": "https://github.com/algolia/algoliasearch-client-php/tree/2.7.2" }, - "time": "2020-11-12T13:52:28+00:00" + "time": "2020-11-24T10:16:46+00:00" }, { "name": "algolia/scout-extended", - "version": "v1.10.1", + "version": "1.10.2", "source": { "type": "git", "url": "https://github.com/algolia/scout-extended.git", - "reference": "d3932eee760f6bf205560b61152392acddbfb50f" + "reference": "ff39d6734b87b0ae1ba26e1752ecb0be021d9fc2" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/algolia/scout-extended/zipball/d3932eee760f6bf205560b61152392acddbfb50f", - "reference": "d3932eee760f6bf205560b61152392acddbfb50f", + "url": "https://api.github.com/repos/algolia/scout-extended/zipball/ff39d6734b87b0ae1ba26e1752ecb0be021d9fc2", + "reference": "ff39d6734b87b0ae1ba26e1752ecb0be021d9fc2", "shasum": "" }, "require": { @@ -157,9 +218,9 @@ ], "support": { "issues": "https://github.com/algolia/scout-extended/issues", - "source": "https://github.com/algolia/scout-extended/tree/v1.10.1" + "source": "https://github.com/algolia/scout-extended/tree/1.10.2" }, - "time": "2020-09-23T13:38:42+00:00" + "time": "2020-11-24T10:23:31+00:00" }, { "name": "asm89/stack-cors", @@ -219,16 +280,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.162.0", + "version": "3.168.1", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "64b0468417c4a84ff5cc51a69cf2ff9d899c2e8e" + "reference": "d648085cce7bfadc8973a8ded401921583c1e3f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/64b0468417c4a84ff5cc51a69cf2ff9d899c2e8e", - "reference": "64b0468417c4a84ff5cc51a69cf2ff9d899c2e8e", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/d648085cce7bfadc8973a8ded401921583c1e3f9", + "reference": "d648085cce7bfadc8973a8ded401921583c1e3f9", "shasum": "" }, "require": { @@ -303,22 +364,22 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.162.0" + "source": "https://github.com/aws/aws-sdk-php/tree/3.168.1" }, - "time": "2020-11-17T19:12:26+00:00" + "time": "2020-12-09T19:17:01+00:00" }, { "name": "blade-ui-kit/blade-heroicons", - "version": "0.3.0", + "version": "0.3.1", "source": { "type": "git", "url": "https://github.com/blade-ui-kit/blade-heroicons.git", - "reference": "c95a3af006f0fb00020002896b4737ce927f37c2" + "reference": "b80c667dfe6eb5c69730e11810ca2d5d1654314a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/blade-ui-kit/blade-heroicons/zipball/c95a3af006f0fb00020002896b4737ce927f37c2", - "reference": "c95a3af006f0fb00020002896b4737ce927f37c2", + "url": "https://api.github.com/repos/blade-ui-kit/blade-heroicons/zipball/b80c667dfe6eb5c69730e11810ca2d5d1654314a", + "reference": "b80c667dfe6eb5c69730e11810ca2d5d1654314a", "shasum": "" }, "require": { @@ -364,7 +425,7 @@ ], "support": { "issues": "https://github.com/blade-ui-kit/blade-heroicons/issues", - "source": "https://github.com/blade-ui-kit/blade-heroicons/tree/0.3.0" + "source": "https://github.com/blade-ui-kit/blade-heroicons/tree/0.3.1" }, "funding": [ { @@ -372,7 +433,7 @@ "type": "github" } ], - "time": "2020-10-31T20:09:21+00:00" + "time": "2020-11-23T21:21:12+00:00" }, { "name": "blade-ui-kit/blade-icons", @@ -649,6 +710,81 @@ ], "time": "2020-08-18T23:57:15+00:00" }, + { + "name": "composer/ca-bundle", + "version": "1.2.8", + "source": { + "type": "git", + "url": "https://github.com/composer/ca-bundle.git", + "reference": "8a7ecad675253e4654ea05505233285377405215" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/composer/ca-bundle/zipball/8a7ecad675253e4654ea05505233285377405215", + "reference": "8a7ecad675253e4654ea05505233285377405215", + "shasum": "" + }, + "require": { + "ext-openssl": "*", + "ext-pcre": "*", + "php": "^5.3.2 || ^7.0 || ^8.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7 || 6.5 - 8", + "psr/log": "^1.0", + "symfony/process": "^2.5 || ^3.0 || ^4.0 || ^5.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.x-dev" + } + }, + "autoload": { + "psr-4": { + "Composer\\CaBundle\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jordi Boggiano", + "email": "j.boggiano@seld.be", + "homepage": "http://seld.be" + } + ], + "description": "Lets you find a path to the system CA bundle, and includes a fallback to the Mozilla CA bundle.", + "keywords": [ + "cabundle", + "cacert", + "certificate", + "ssl", + "tls" + ], + "support": { + "irc": "irc://irc.freenode.org/composer", + "issues": "https://github.com/composer/ca-bundle/issues", + "source": "https://github.com/composer/ca-bundle/tree/1.2.8" + }, + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://github.com/composer", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], + "time": "2020-08-23T12:54:47+00:00" + }, { "name": "dnoegel/php-xdg-base-dir", "version": "v0.1.1", @@ -1168,26 +1304,29 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.0.2", + "version": "v3.1.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "48212cdc0a79051d50d7fc2f0645c5a321caf926" + "reference": "7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/48212cdc0a79051d50d7fc2f0645c5a321caf926", - "reference": "48212cdc0a79051d50d7fc2f0645c5a321caf926", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c", + "reference": "7a8c6e56ab3ffcc538d05e8155bb42269abf1a0c", "shasum": "" }, "require": { - "php": "^7.1|^8.0" + "php": "^7.2|^8.0", + "webmozart/assert": "^1.7.0" }, "replace": { "mtdowling/cron-expression": "^1.0" }, "require-dev": { - "phpstan/phpstan": "^0.11|^0.12", + "phpstan/extension-installer": "^1.0", + "phpstan/phpstan": "^0.12", + "phpstan/phpstan-webmozart-assert": "^0.12.7", "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", @@ -1214,7 +1353,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.0.2" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.1.0" }, "funding": [ { @@ -1222,7 +1361,7 @@ "type": "github" } ], - "time": "2020-10-13T01:26:01+00:00" + "time": "2020-11-24T19:55:57+00:00" }, { "name": "egulias/email-validator", @@ -1359,16 +1498,16 @@ }, { "name": "facade/ignition", - "version": "2.5.2", + "version": "2.5.3", "source": { "type": "git", "url": "https://github.com/facade/ignition.git", - "reference": "08668034beb185fa2ac6f09b1034eaa440952ace" + "reference": "d8dc4f90ed469f9f9313b976fb078c20585d5c99" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/facade/ignition/zipball/08668034beb185fa2ac6f09b1034eaa440952ace", - "reference": "08668034beb185fa2ac6f09b1034eaa440952ace", + "url": "https://api.github.com/repos/facade/ignition/zipball/d8dc4f90ed469f9f9313b976fb078c20585d5c99", + "reference": "d8dc4f90ed469f9f9313b976fb078c20585d5c99", "shasum": "" }, "require": { @@ -1432,7 +1571,7 @@ "issues": "https://github.com/facade/ignition/issues", "source": "https://github.com/facade/ignition" }, - "time": "2020-11-17T09:18:51+00:00" + "time": "2020-12-09T20:25:45+00:00" }, { "name": "facade/ignition-contracts", @@ -2061,16 +2200,16 @@ }, { "name": "intervention/imagecache", - "version": "2.5.0", + "version": "2.5.1", "source": { "type": "git", "url": "https://github.com/Intervention/imagecache.git", - "reference": "5c98e720fcdb6e7e54fc31832f49613a4c9920ce" + "reference": "e714f13298ecaf9b2d11cb7106a0415d5615cbe5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Intervention/imagecache/zipball/5c98e720fcdb6e7e54fc31832f49613a4c9920ce", - "reference": "5c98e720fcdb6e7e54fc31832f49613a4c9920ce", + "url": "https://api.github.com/repos/Intervention/imagecache/zipball/e714f13298ecaf9b2d11cb7106a0415d5615cbe5", + "reference": "e714f13298ecaf9b2d11cb7106a0415d5615cbe5", "shasum": "" }, "require": { @@ -2079,7 +2218,7 @@ "intervention/image": ">=2.2.0", "nesbot/carbon": "^2.39", "opis/closure": "^3.5", - "php": "^7.2" + "php": ">=7.2" }, "require-dev": { "phpunit/phpunit": "^8.0" @@ -2112,28 +2251,131 @@ ], "support": { "issues": "https://github.com/Intervention/imagecache/issues", - "source": "https://github.com/Intervention/imagecache/tree/2.5.0" + "source": "https://github.com/Intervention/imagecache/tree/2.5.1" }, "funding": [ + { + "url": "https://www.paypal.me/interventionphp", + "type": "custom" + }, { "url": "https://github.com/Intervention", "type": "github" } ], - "time": "2020-09-10T18:34:02+00:00" + "time": "2020-12-07T15:07:18+00:00" + }, + { + "name": "kylewm/brevity", + "version": "0.2.10", + "source": { + "type": "git", + "url": "https://github.com/kylewm/brevity-php.git", + "reference": "9700a3ca666ff9486bd8bed322d7096ef78b6580" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/kylewm/brevity-php/zipball/9700a3ca666ff9486bd8bed322d7096ef78b6580", + "reference": "9700a3ca666ff9486bd8bed322d7096ef78b6580", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "^4.8" + }, + "type": "library", + "autoload": { + "psr-0": { + "Kylewm\\Brevity": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "CC0" + ], + "authors": [ + { + "name": "Kyle Mahan", + "email": "kyle+brevityphp@kylewm.com" + } + ], + "description": "A small utility to count characters and shorten posts to tweet-length.", + "support": { + "issues": "https://github.com/kylewm/brevity-php/issues", + "source": "https://github.com/kylewm/brevity-php/tree/master" + }, + "time": "2017-11-25T19:51:26+00:00" + }, + { + "name": "laravel-notification-channels/twitter", + "version": "v5.1.0", + "source": { + "type": "git", + "url": "https://github.com/laravel-notification-channels/twitter.git", + "reference": "bcab129f7f294b0a192aaefbfde7266a39a6b2ba" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel-notification-channels/twitter/zipball/bcab129f7f294b0a192aaefbfde7266a39a6b2ba", + "reference": "bcab129f7f294b0a192aaefbfde7266a39a6b2ba", + "shasum": "" + }, + "require": { + "abraham/twitteroauth": "^2.0.0", + "illuminate/notifications": "^8.0", + "illuminate/support": "^8.0", + "kylewm/brevity": "^0.2.9", + "php": "^7.3|^8.0" + }, + "require-dev": { + "mockery/mockery": "^1.3.1", + "orchestra/testbench": "~6.0", + "phpunit/phpunit": "^9.3" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "NotificationChannels\\Twitter\\TwitterServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "NotificationChannels\\Twitter\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Christoph Rumpel", + "email": "c.rumpel@kabsi.at", + "homepage": "https://christoph-rumpel.com", + "role": "Developer" + } + ], + "description": "This package makes it easy to send notifications via Twitter with Laravel", + "homepage": "https://github.com/laravel-notification-channels/twitter", + "support": { + "issues": "https://github.com/laravel-notification-channels/twitter/issues", + "source": "https://github.com/laravel-notification-channels/twitter/tree/v5.1.0" + }, + "time": "2020-12-09T09:49:26+00:00" }, { "name": "laravel/framework", - "version": "v8.15.0", + "version": "v8.18.1", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "22e4182fa0885dea3772106c3b6df705b7c7363e" + "reference": "31747193c26ba0a9cb7929a912895d3cdefd10cf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/22e4182fa0885dea3772106c3b6df705b7c7363e", - "reference": "22e4182fa0885dea3772106c3b6df705b7c7363e", + "url": "https://api.github.com/repos/laravel/framework/zipball/31747193c26ba0a9cb7929a912895d3cdefd10cf", + "reference": "31747193c26ba0a9cb7929a912895d3cdefd10cf", "shasum": "" }, "require": { @@ -2153,15 +2395,15 @@ "psr/simple-cache": "^1.0", "ramsey/uuid": "^4.0", "swiftmailer/swiftmailer": "^6.0", - "symfony/console": "^5.1", - "symfony/error-handler": "^5.1", - "symfony/finder": "^5.1", - "symfony/http-foundation": "^5.1", - "symfony/http-kernel": "^5.1", - "symfony/mime": "^5.1", - "symfony/process": "^5.1", - "symfony/routing": "^5.1", - "symfony/var-dumper": "^5.1", + "symfony/console": "^5.1.4", + "symfony/error-handler": "^5.1.4", + "symfony/finder": "^5.1.4", + "symfony/http-foundation": "^5.1.4", + "symfony/http-kernel": "^5.1.4", + "symfony/mime": "^5.1.4", + "symfony/process": "^5.1.4", + "symfony/routing": "^5.1.4", + "symfony/var-dumper": "^5.1.4", "tijsverkoyen/css-to-inline-styles": "^2.2.2", "vlucas/phpdotenv": "^5.2", "voku/portable-ascii": "^1.4.8" @@ -2206,20 +2448,20 @@ "illuminate/view": "self.version" }, "require-dev": { - "aws/aws-sdk-php": "^3.0", + "aws/aws-sdk-php": "^3.155", "doctrine/dbal": "^2.6|^3.0", "filp/whoops": "^2.8", "guzzlehttp/guzzle": "^6.5.5|^7.0.1", "league/flysystem-cached-adapter": "^1.0", "mockery/mockery": "^1.4.2", - "orchestra/testbench-core": "^6.5", + "orchestra/testbench-core": "^6.8", "pda/pheanstalk": "^4.0", "phpunit/phpunit": "^8.5.8|^9.3.3", "predis/predis": "^1.1.1", - "symfony/cache": "^5.1" + "symfony/cache": "^5.1.4" }, "suggest": { - "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.0).", + "aws/aws-sdk-php": "Required to use the SQS queue driver, DynamoDb failed job storage and SES mail driver (^3.155).", "doctrine/dbal": "Required to rename columns and drop SQLite columns (^2.6|^3.0).", "ext-ftp": "Required to use the Flysystem FTP driver.", "ext-gd": "Required to use Illuminate\\Http\\Testing\\FileFactory::image().", @@ -2241,8 +2483,8 @@ "predis/predis": "Required to use the predis connector (^1.1.2).", "psr/http-message": "Required to allow Storage::put to accept a StreamInterface (^1.0).", "pusher/pusher-php-server": "Required to use the Pusher broadcast driver (^4.0).", - "symfony/cache": "Required to PSR-6 cache bridge (^5.1).", - "symfony/filesystem": "Required to enable support for relative symbolic links (^5.1).", + "symfony/cache": "Required to PSR-6 cache bridge (^5.1.4).", + "symfony/filesystem": "Required to enable support for relative symbolic links (^5.1.4).", "symfony/psr-http-message-bridge": "Required to use PSR-7 bridging features (^2.0).", "wildbit/swiftmailer-postmark": "Required to use Postmark mail driver (^3.0)." }, @@ -2287,20 +2529,20 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2020-11-17T14:53:20+00:00" + "time": "2020-12-08T22:05:12+00:00" }, { "name": "laravel/horizon", - "version": "v5.4.0", + "version": "v5.6.1", "source": { "type": "git", "url": "https://github.com/laravel/horizon.git", - "reference": "d08d10ee12f53b7ba2cbb938eb23857e93fe51d3" + "reference": "e3809cfaf575a79bc1c846e217d1aa9d4950b316" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/horizon/zipball/d08d10ee12f53b7ba2cbb938eb23857e93fe51d3", - "reference": "d08d10ee12f53b7ba2cbb938eb23857e93fe51d3", + "url": "https://api.github.com/repos/laravel/horizon/zipball/e3809cfaf575a79bc1c846e217d1aa9d4950b316", + "reference": "e3809cfaf575a79bc1c846e217d1aa9d4950b316", "shasum": "" }, "require": { @@ -2362,9 +2604,9 @@ ], "support": { "issues": "https://github.com/laravel/horizon/issues", - "source": "https://github.com/laravel/horizon/tree/v5.4.0" + "source": "https://github.com/laravel/horizon/tree/v5.6.1" }, - "time": "2020-11-03T16:55:40+00:00" + "time": "2020-12-08T18:29:48+00:00" }, { "name": "laravel/scout", @@ -2438,16 +2680,16 @@ }, { "name": "laravel/socialite", - "version": "v5.1.0", + "version": "v5.1.2", "source": { "type": "git", "url": "https://github.com/laravel/socialite.git", - "reference": "14082c665186348028e5bde17ab33b21b36dac79" + "reference": "19fc65ac28e0b4684a8735b14c1dc6f6ef5d62c7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/socialite/zipball/14082c665186348028e5bde17ab33b21b36dac79", - "reference": "14082c665186348028e5bde17ab33b21b36dac79", + "url": "https://api.github.com/repos/laravel/socialite/zipball/19fc65ac28e0b4684a8735b14c1dc6f6ef5d62c7", + "reference": "19fc65ac28e0b4684a8735b14c1dc6f6ef5d62c7", "shasum": "" }, "require": { @@ -2503,7 +2745,7 @@ "issues": "https://github.com/laravel/socialite/issues", "source": "https://github.com/laravel/socialite" }, - "time": "2020-11-03T19:24:43+00:00" + "time": "2020-12-04T15:30:50+00:00" }, { "name": "laravel/tinker", @@ -3433,16 +3675,16 @@ }, { "name": "nesbot/carbon", - "version": "2.41.5", + "version": "2.42.0", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "c4a9caf97cfc53adfc219043bcecf42bc663acee" + "reference": "d0463779663437392fe42ff339ebc0213bd55498" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/c4a9caf97cfc53adfc219043bcecf42bc663acee", - "reference": "c4a9caf97cfc53adfc219043bcecf42bc663acee", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/d0463779663437392fe42ff339ebc0213bd55498", + "reference": "d0463779663437392fe42ff339ebc0213bd55498", "shasum": "" }, "require": { @@ -3457,7 +3699,7 @@ "kylekatarnls/multi-tester": "^2.0", "phpmd/phpmd": "^2.9", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.35", + "phpstan/phpstan": "^0.12.54", "phpunit/phpunit": "^7.5 || ^8.0", "squizlabs/php_codesniffer": "^3.4" }, @@ -3522,20 +3764,20 @@ "type": "tidelift" } ], - "time": "2020-10-23T06:02:30+00:00" + "time": "2020-11-28T14:25:28+00:00" }, { "name": "nikic/php-parser", - "version": "v4.10.2", + "version": "v4.10.3", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "658f1be311a230e0907f5dfe0213742aff0596de" + "reference": "dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/658f1be311a230e0907f5dfe0213742aff0596de", - "reference": "658f1be311a230e0907f5dfe0213742aff0596de", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984", + "reference": "dbe56d23de8fcb157bbc0cfb3ad7c7de0cfb0984", "shasum": "" }, "require": { @@ -3576,34 +3818,32 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.2" + "source": "https://github.com/nikic/PHP-Parser/tree/v4.10.3" }, - "time": "2020-09-26T10:30:38+00:00" + "time": "2020-12-03T17:45:45+00:00" }, { "name": "ohdearapp/ohdear-php-sdk", - "version": "3.0.1", + "version": "3.0.2", "source": { "type": "git", "url": "https://github.com/ohdearapp/ohdear-php-sdk.git", - "reference": "54d027647cf79cdc8d66daff7620eaa47b3ccd2e" + "reference": "6d8eed7ce34e12067c13d392bffd3ecf71b2f026" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ohdearapp/ohdear-php-sdk/zipball/54d027647cf79cdc8d66daff7620eaa47b3ccd2e", - "reference": "54d027647cf79cdc8d66daff7620eaa47b3ccd2e", + "url": "https://api.github.com/repos/ohdearapp/ohdear-php-sdk/zipball/6d8eed7ce34e12067c13d392bffd3ecf71b2f026", + "reference": "6d8eed7ce34e12067c13d392bffd3ecf71b2f026", "shasum": "" }, "require": { "guzzlehttp/guzzle": "^6.3|^7.0", "nesbot/carbon": "^2.35.0", - "php": "^7.4" + "php": "^7.4|^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", "phpunit/phpunit": "^9.0", "psalm/plugin-laravel": "^1.2", - "vimeo/psalm": "^3.11", "vlucas/phpdotenv": "^4.0" }, "type": "library", @@ -3634,9 +3874,9 @@ ], "support": { "issues": "https://github.com/ohdearapp/ohdear-php-sdk/issues", - "source": "https://github.com/ohdearapp/ohdear-php-sdk/tree/3.0.1" + "source": "https://github.com/ohdearapp/ohdear-php-sdk/tree/3.0.2" }, - "time": "2020-08-21T21:38:17+00:00" + "time": "2020-11-30T19:06:34+00:00" }, { "name": "opis/closure", @@ -4162,16 +4402,16 @@ }, { "name": "psy/psysh", - "version": "v0.10.4", + "version": "v0.10.5", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "a8aec1b2981ab66882a01cce36a49b6317dc3560" + "reference": "7c710551d4a2653afa259c544508dc18a9098956" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/a8aec1b2981ab66882a01cce36a49b6317dc3560", - "reference": "a8aec1b2981ab66882a01cce36a49b6317dc3560", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/7c710551d4a2653afa259c544508dc18a9098956", + "reference": "7c710551d4a2653afa259c544508dc18a9098956", "shasum": "" }, "require": { @@ -4232,9 +4472,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/master" + "source": "https://github.com/bobthecow/psysh/tree/v0.10.5" }, - "time": "2020-05-03T19:32:03+00:00" + "time": "2020-12-04T02:51:30+00:00" }, { "name": "ralouphie/getallheaders", @@ -4447,23 +4687,23 @@ }, { "name": "riimu/kit-phpencoder", - "version": "v2.4.0", + "version": "v2.4.1", "source": { "type": "git", "url": "https://github.com/Riimu/Kit-PHPEncoder.git", - "reference": "7e876d25019c3f6c23321ab5ac1a55c72fcd0933" + "reference": "ca6f004e1290aec7ef4bebf6c0807b30fcf981d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Riimu/Kit-PHPEncoder/zipball/7e876d25019c3f6c23321ab5ac1a55c72fcd0933", - "reference": "7e876d25019c3f6c23321ab5ac1a55c72fcd0933", + "url": "https://api.github.com/repos/Riimu/Kit-PHPEncoder/zipball/ca6f004e1290aec7ef4bebf6c0807b30fcf981d7", + "reference": "ca6f004e1290aec7ef4bebf6c0807b30fcf981d7", "shasum": "" }, "require": { "php": ">=5.6.0" }, "require-dev": { - "phpunit/phpunit": "^7.2 || ^6.5 || ^5.7" + "phpunit/phpunit": "^9.4 || ^6.5 || ^5.7" }, "suggest": { "ext-gmp": "To convert GMP numbers into PHP code" @@ -4496,9 +4736,9 @@ ], "support": { "issues": "https://github.com/Riimu/Kit-PHPEncoder/issues", - "source": "https://github.com/Riimu/Kit-PHPEncoder/tree/master" + "source": "https://github.com/Riimu/Kit-PHPEncoder/tree/v2.4.1" }, - "time": "2018-07-03T12:46:23+00:00" + "time": "2020-11-29T16:53:17+00:00" }, { "name": "roave/security-advisories", @@ -4506,12 +4746,12 @@ "source": { "type": "git", "url": "https://github.com/Roave/SecurityAdvisories.git", - "reference": "4100ec7deab9f78b3b7685fedc6c9b82c15b5c76" + "reference": "d5961914bf7f90e81af509b81e51450bff419815" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/4100ec7deab9f78b3b7685fedc6c9b82c15b5c76", - "reference": "4100ec7deab9f78b3b7685fedc6c9b82c15b5c76", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/d5961914bf7f90e81af509b81e51450bff419815", + "reference": "d5961914bf7f90e81af509b81e51450bff419815", "shasum": "" }, "conflict": { @@ -4541,7 +4781,7 @@ "composer/composer": "<=1-alpha.11", "contao-components/mediaelement": ">=2.14.2,<2.21.1", "contao/core": ">=2,<3.5.39", - "contao/core-bundle": "= 4.10.0|>=4,<4.4.52|>=4.5,<4.9.6", + "contao/core-bundle": ">=4,<4.4.52|>=4.5,<4.9.6|= 4.10.0", "contao/listing-bundle": ">=4,<4.4.8", "datadog/dd-trace": ">=0.30,<0.30.2", "david-garcia/phpwhois": "<=4.3.1", @@ -4557,12 +4797,13 @@ "doctrine/orm": ">=2,<2.4.8|>=2.5,<2.5.1", "dolibarr/dolibarr": "<11.0.4", "dompdf/dompdf": ">=0.6,<0.6.2", - "drupal/core": ">=7,<7.73|>=8,<8.8.10|>=8.9,<8.9.6|>=9,<9.0.6", - "drupal/drupal": ">=7,<7.73|>=8,<8.8.10|>=8.9,<8.9.6|>=9,<9.0.6", + "drupal/core": ">=7,<7.74|>=8,<8.8.11|>=8.9,<8.9.9|>=9,<9.0.8", + "drupal/drupal": ">=7,<7.74|>=8,<8.8.11|>=8.9,<8.9.9|>=9,<9.0.8", "endroid/qr-code-bundle": "<3.4.2", "enshrined/svg-sanitize": "<0.13.1", "erusev/parsedown": "<1.7.2", "ezsystems/demobundle": ">=5.4,<5.4.6.1", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1", "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1|>=5.4,<5.4.11.1|>=2017.12,<2017.12.0.1", "ezsystems/ezplatform": ">=1.7,<1.7.9.1|>=1.13,<1.13.5.1|>=2.5,<2.5.4", @@ -4584,6 +4825,8 @@ "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", "fuel/core": "<1.8.1", "getgrav/grav": "<1.7-beta.8", + "getkirby/cms": ">=3,<3.4.5", + "getkirby/panel": "<2.5.14", "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", "gree/jose": "<=2.2", "gregwar/rst": "<1.0.3", @@ -4611,7 +4854,7 @@ "magento/magento1ee": ">=1,<1.14.4.3", "magento/product-community-edition": ">=2,<2.2.10|>=2.3,<2.3.2-p.2", "marcwillmann/turn": "<0.3.3", - "mediawiki/core": ">=1.31,<1.31.9|>=1.32,<1.32.4|>=1.33,<1.33.3|>=1.34,<1.34.3|>=1.34.99,<1.35", + "mediawiki/core": ">=1.27,<1.27.6|>=1.29,<1.29.3|>=1.30,<1.30.2|>=1.31,<1.31.9|>=1.32,<1.32.6|>=1.32.99,<1.33.3|>=1.33.99,<1.34.3|>=1.34.99,<1.35", "mittwald/typo3_forum": "<1.2.1", "monolog/monolog": ">=1.8,<1.12", "namshi/jose": "<2.2", @@ -4619,8 +4862,8 @@ "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", "nystudio107/craft-seomatic": "<3.3", "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", - "october/backend": ">=1.0.319,<1.0.467", - "october/cms": ">=1.0.319,<1.0.466", + "october/backend": ">=1.0.319,<1.0.470", + "october/cms": "= 1.0.469|>=1.0.319,<1.0.469", "october/october": ">=1.0.319,<1.0.466", "october/rain": ">=1.0.319,<1.0.468", "onelogin/php-saml": "<2.10.4", @@ -4633,13 +4876,14 @@ "padraic/humbug_get_contents": "<1.1.2", "pagarme/pagarme-php": ">=0,<3", "paragonie/random_compat": "<2", + "passbolt/passbolt_api": "<2.11", "paypal/merchant-sdk-php": "<3.12", - "pear/archive_tar": "<1.4.4", + "pear/archive_tar": "<1.4.11", "personnummer/personnummer": "<3.0.2", "phpfastcache/phpfastcache": ">=5,<5.0.13", "phpmailer/phpmailer": "<6.1.6", "phpmussel/phpmussel": ">=1,<1.6", - "phpmyadmin/phpmyadmin": "<4.9.2", + "phpmyadmin/phpmyadmin": "<4.9.6|>=5,<5.0.3", "phpoffice/phpexcel": "<1.8.2", "phpoffice/phpspreadsheet": "<1.8", "phpunit/phpunit": ">=4.8.19,<4.8.28|>=5.0.10,<5.6.3", @@ -4736,12 +4980,12 @@ "titon/framework": ">=0,<9.9.99", "truckersmp/phpwhois": "<=4.3.1", "twig/twig": "<1.38|>=2,<2.7", - "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.30|>=9,<9.5.20|>=10,<10.4.6", - "typo3/cms-core": ">=8,<8.7.30|>=9,<9.5.20|>=10,<10.4.6", + "typo3/cms": ">=6.2,<6.2.30|>=7,<7.6.32|>=8,<8.7.38|>=9,<9.5.23|>=10,<10.4.10", + "typo3/cms-core": ">=8,<8.7.38|>=9,<9.5.23|>=10,<10.4.10", "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.10|>=3.1,<3.1.7|>=3.2,<3.2.7|>=3.3,<3.3.5", "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4", "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", - "typo3fluid/fluid": ">=2,<2.0.5|>=2.1,<2.1.4|>=2.2,<2.2.1|>=2.3,<2.3.5|>=2.4,<2.4.1|>=2.5,<2.5.5|>=2.6,<2.6.1", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", "ua-parser/uap-php": "<3.8", "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", "verot/class.upload.php": "<=1.0.3|>=2,<=2.0.4", @@ -4815,7 +5059,7 @@ "type": "tidelift" } ], - "time": "2020-11-18T07:02:14+00:00" + "time": "2020-12-08T15:02:56+00:00" }, { "name": "spatie/laravel-feed", @@ -4901,24 +5145,24 @@ }, { "name": "spatie/laravel-robots-middleware", - "version": "1.2.1", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-robots-middleware.git", - "reference": "4980d989305c5bfec00780d754fa915b491022b8" + "reference": "ba0e38e2192e6d054ba4b1cd5d9fb3bd7c8db0f7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-robots-middleware/zipball/4980d989305c5bfec00780d754fa915b491022b8", - "reference": "4980d989305c5bfec00780d754fa915b491022b8", + "url": "https://api.github.com/repos/spatie/laravel-robots-middleware/zipball/ba0e38e2192e6d054ba4b1cd5d9fb3bd7c8db0f7", + "reference": "ba0e38e2192e6d054ba4b1cd5d9fb3bd7c8db0f7", "shasum": "" }, "require": { - "illuminate/http": "^5.8|^6.0|^7.0|^8.0", - "php": "^7.2" + "illuminate/http": "^6.0|^7.0|^8.0", + "php": "^7.2|^8.0" }, "require-dev": { - "orchestra/testbench": "^3.8|^4.0|^5.0|^6.0", + "orchestra/testbench": "^4.0|^5.0|^6.0", "phpunit/phpunit": "^8.0|^9.3" }, "type": "library", @@ -4949,7 +5193,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-robots-middleware/issues", - "source": "https://github.com/spatie/laravel-robots-middleware/tree/1.2.1" + "source": "https://github.com/spatie/laravel-robots-middleware/tree/1.3.0" }, "funding": [ { @@ -4957,37 +5201,37 @@ "type": "custom" } ], - "time": "2020-09-09T10:09:18+00:00" + "time": "2020-12-04T13:00:24+00:00" }, { "name": "spatie/laravel-schedule-monitor", - "version": "2.0.2", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/spatie/laravel-schedule-monitor.git", - "reference": "40964a420d0207780beb9f0667f9ce5d9c25d82a" + "reference": "e4611b34dd1452d0d241f8a9c83c42564d2d45cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/spatie/laravel-schedule-monitor/zipball/40964a420d0207780beb9f0667f9ce5d9c25d82a", - "reference": "40964a420d0207780beb9f0667f9ce5d9c25d82a", + "url": "https://api.github.com/repos/spatie/laravel-schedule-monitor/zipball/e4611b34dd1452d0d241f8a9c83c42564d2d45cc", + "reference": "e4611b34dd1452d0d241f8a9c83c42564d2d45cc", "shasum": "" }, "require": { "illuminate/bus": "^8.0", "lorisleiva/cron-translator": "^0.1.1", "nesbot/carbon": "^2.41.3", - "php": "^7.4" + "php": "^7.4|^8.0" }, "require-dev": { - "friendsofphp/php-cs-fixer": "^2.16", "laravel/legacy-factories": "^1.0.4", + "mockery/mockery": "^1.4", "ohdearapp/ohdear-php-sdk": "^3.0", "orchestra/testbench": "^6.0", "phpunit/phpunit": "^9.3", "spatie/phpunit-snapshot-assertions": "^4.2", "spatie/test-time": "^1.2", - "vimeo/psalm": "^3.11" + "vimeo/psalm": "^4.0" }, "suggest": { "ohdearapp/ohdear-php-sdk": "Needed to sync your schedule with Oh Dear" @@ -5025,7 +5269,7 @@ ], "support": { "issues": "https://github.com/spatie/laravel-schedule-monitor/issues", - "source": "https://github.com/spatie/laravel-schedule-monitor/tree/2.0.2" + "source": "https://github.com/spatie/laravel-schedule-monitor/tree/2.1.0" }, "funding": [ { @@ -5033,36 +5277,35 @@ "type": "github" } ], - "time": "2020-10-14T07:24:48+00:00" + "time": "2020-12-04T08:02:17+00:00" }, { "name": "swiftmailer/swiftmailer", - "version": "v6.2.3", + "version": "v6.2.4", "source": { "type": "git", "url": "https://github.com/swiftmailer/swiftmailer.git", - "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9" + "reference": "56f0ab23f54c4ccbb0d5dcc67ff8552e0c98d59e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/149cfdf118b169f7840bbe3ef0d4bc795d1780c9", - "reference": "149cfdf118b169f7840bbe3ef0d4bc795d1780c9", + "url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/56f0ab23f54c4ccbb0d5dcc67ff8552e0c98d59e", + "reference": "56f0ab23f54c4ccbb0d5dcc67ff8552e0c98d59e", "shasum": "" }, "require": { - "egulias/email-validator": "~2.0", + "egulias/email-validator": "^2.0", "php": ">=7.0.0", "symfony/polyfill-iconv": "^1.0", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0" }, "require-dev": { - "mockery/mockery": "~0.9.1", - "symfony/phpunit-bridge": "^3.4.19|^4.1.8" + "mockery/mockery": "^1.0", + "symfony/phpunit-bridge": "^4.4|^5.0" }, "suggest": { - "ext-intl": "Needed to support internationalized email addresses", - "true/punycode": "Needed to support internationalized email addresses, if ext-intl is not installed" + "ext-intl": "Needed to support internationalized email addresses" }, "type": "library", "extra": { @@ -5097,22 +5340,32 @@ ], "support": { "issues": "https://github.com/swiftmailer/swiftmailer/issues", - "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.2.3" + "source": "https://github.com/swiftmailer/swiftmailer/tree/v6.2.4" }, - "time": "2019-11-12T09:31:26+00:00" + "funding": [ + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/swiftmailer/swiftmailer", + "type": "tidelift" + } + ], + "time": "2020-12-08T18:02:06+00:00" }, { "name": "symfony/console", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "e0b2c29c0fa6a69089209bbe8fcff4df2a313d0e" + "reference": "3e0564fb08d44a98bd5f1960204c958e57bd586b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/e0b2c29c0fa6a69089209bbe8fcff4df2a313d0e", - "reference": "e0b2c29c0fa6a69089209bbe8fcff4df2a313d0e", + "url": "https://api.github.com/repos/symfony/console/zipball/3e0564fb08d44a98bd5f1960204c958e57bd586b", + "reference": "3e0564fb08d44a98bd5f1960204c958e57bd586b", "shasum": "" }, "require": { @@ -5173,8 +5426,14 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", + "keywords": [ + "cli", + "command line", + "console", + "terminal" + ], "support": { - "source": "https://github.com/symfony/console/tree/v5.1.8" + "source": "https://github.com/symfony/console/tree/v5.2.0" }, "funding": [ { @@ -5190,20 +5449,20 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-11-28T11:24:18+00:00" }, { "name": "symfony/css-selector", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/css-selector.git", - "reference": "6cbebda22ffc0d4bb8fea0c1311c2ca54c4c8fa0" + "reference": "b8d8eb06b0942e84a69e7acebc3e9c1e6e6e7256" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/css-selector/zipball/6cbebda22ffc0d4bb8fea0c1311c2ca54c4c8fa0", - "reference": "6cbebda22ffc0d4bb8fea0c1311c2ca54c4c8fa0", + "url": "https://api.github.com/repos/symfony/css-selector/zipball/b8d8eb06b0942e84a69e7acebc3e9c1e6e6e7256", + "reference": "b8d8eb06b0942e84a69e7acebc3e9c1e6e6e7256", "shasum": "" }, "require": { @@ -5239,7 +5498,7 @@ "description": "Symfony CssSelector Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/css-selector/tree/v5.1.8" + "source": "https://github.com/symfony/css-selector/tree/v5.2.0" }, "funding": [ { @@ -5255,7 +5514,7 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-10-28T21:31:18+00:00" }, { "name": "symfony/deprecation-contracts", @@ -5326,16 +5585,16 @@ }, { "name": "symfony/error-handler", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/error-handler.git", - "reference": "a154f2b12fd1ec708559ba73ed58bd1304e55718" + "reference": "289008c5be039e39908d33ae0a8ac99be1210bba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/error-handler/zipball/a154f2b12fd1ec708559ba73ed58bd1304e55718", - "reference": "a154f2b12fd1ec708559ba73ed58bd1304e55718", + "url": "https://api.github.com/repos/symfony/error-handler/zipball/289008c5be039e39908d33ae0a8ac99be1210bba", + "reference": "289008c5be039e39908d33ae0a8ac99be1210bba", "shasum": "" }, "require": { @@ -5375,7 +5634,7 @@ "description": "Symfony ErrorHandler Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/error-handler/tree/v5.1.8" + "source": "https://github.com/symfony/error-handler/tree/v5.2.0" }, "funding": [ { @@ -5391,20 +5650,20 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-10-28T21:46:03+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "26f4edae48c913fc183a3da0553fe63bdfbd361a" + "reference": "aa13a09811e6d2ad43f8fb336bebdb7691d85d3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/26f4edae48c913fc183a3da0553fe63bdfbd361a", - "reference": "26f4edae48c913fc183a3da0553fe63bdfbd361a", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/aa13a09811e6d2ad43f8fb336bebdb7691d85d3c", + "reference": "aa13a09811e6d2ad43f8fb336bebdb7691d85d3c", "shasum": "" }, "require": { @@ -5460,7 +5719,7 @@ "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/event-dispatcher/tree/v5.1.8" + "source": "https://github.com/symfony/event-dispatcher/tree/v5.2.0" }, "funding": [ { @@ -5476,7 +5735,7 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-11-01T16:14:45+00:00" }, { "name": "symfony/event-dispatcher-contracts", @@ -5559,16 +5818,16 @@ }, { "name": "symfony/finder", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "e70eb5a69c2ff61ea135a13d2266e8914a67b3a0" + "reference": "fd8305521692f27eae3263895d1ef1571c71a78d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/e70eb5a69c2ff61ea135a13d2266e8914a67b3a0", - "reference": "e70eb5a69c2ff61ea135a13d2266e8914a67b3a0", + "url": "https://api.github.com/repos/symfony/finder/zipball/fd8305521692f27eae3263895d1ef1571c71a78d", + "reference": "fd8305521692f27eae3263895d1ef1571c71a78d", "shasum": "" }, "require": { @@ -5600,7 +5859,7 @@ "description": "Symfony Finder Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v5.1.8" + "source": "https://github.com/symfony/finder/tree/v5.2.0" }, "funding": [ { @@ -5616,7 +5875,7 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-11-18T09:42:36+00:00" }, { "name": "symfony/http-client-contracts", @@ -5699,16 +5958,16 @@ }, { "name": "symfony/http-foundation", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "a2860ec970404b0233ab1e59e0568d3277d32b6f" + "reference": "e4576271ee99123aa59a40564c7b5405f0ebd1e6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/a2860ec970404b0233ab1e59e0568d3277d32b6f", - "reference": "a2860ec970404b0233ab1e59e0568d3277d32b6f", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e4576271ee99123aa59a40564c7b5405f0ebd1e6", + "reference": "e4576271ee99123aa59a40564c7b5405f0ebd1e6", "shasum": "" }, "require": { @@ -5752,7 +6011,7 @@ "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.1.8" + "source": "https://github.com/symfony/http-foundation/tree/v5.2.0" }, "funding": [ { @@ -5768,20 +6027,20 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-11-27T06:13:25+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "a13b3c4d994a4fd051f4c6800c5e33c9508091dd" + "reference": "38907e5ccb2d9d371191a946734afc83c7a03160" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/a13b3c4d994a4fd051f4c6800c5e33c9508091dd", - "reference": "a13b3c4d994a4fd051f4c6800c5e33c9508091dd", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/38907e5ccb2d9d371191a946734afc83c7a03160", + "reference": "38907e5ccb2d9d371191a946734afc83c7a03160", "shasum": "" }, "require": { @@ -5801,7 +6060,7 @@ "symfony/cache": "<5.0", "symfony/config": "<5.0", "symfony/console": "<4.4", - "symfony/dependency-injection": "<4.4", + "symfony/dependency-injection": "<5.1.8", "symfony/doctrine-bridge": "<5.0", "symfony/form": "<5.0", "symfony/http-client": "<5.0", @@ -5821,7 +6080,7 @@ "symfony/config": "^5.0", "symfony/console": "^4.4|^5.0", "symfony/css-selector": "^4.4|^5.0", - "symfony/dependency-injection": "^4.4|^5.0", + "symfony/dependency-injection": "^5.1.8", "symfony/dom-crawler": "^4.4|^5.0", "symfony/expression-language": "^4.4|^5.0", "symfony/finder": "^4.4|^5.0", @@ -5864,7 +6123,7 @@ "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.1.8" + "source": "https://github.com/symfony/http-kernel/tree/v5.2.0" }, "funding": [ { @@ -5880,24 +6139,25 @@ "type": "tidelift" } ], - "time": "2020-10-28T05:55:23+00:00" + "time": "2020-11-30T05:54:18+00:00" }, { "name": "symfony/mime", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "f5485a92c24d4bcfc2f3fc648744fb398482ff1b" + "reference": "05f667e8fa029568964fd3bec6bc17765b853cc5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/f5485a92c24d4bcfc2f3fc648744fb398482ff1b", - "reference": "f5485a92c24d4bcfc2f3fc648744fb398482ff1b", + "url": "https://api.github.com/repos/symfony/mime/zipball/05f667e8fa029568964fd3bec6bc17765b853cc5", + "reference": "05f667e8fa029568964fd3bec6bc17765b853cc5", "shasum": "" }, "require": { "php": ">=7.2.5", + "symfony/deprecation-contracts": "^2.1", "symfony/polyfill-intl-idn": "^1.10", "symfony/polyfill-mbstring": "^1.0", "symfony/polyfill-php80": "^1.15" @@ -5907,7 +6167,11 @@ }, "require-dev": { "egulias/email-validator": "^2.1.10", - "symfony/dependency-injection": "^4.4|^5.0" + "phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0", + "symfony/dependency-injection": "^4.4|^5.0", + "symfony/property-access": "^4.4|^5.1", + "symfony/property-info": "^4.4|^5.1", + "symfony/serializer": "^5.2" }, "type": "library", "autoload": { @@ -5939,7 +6203,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.1.8" + "source": "https://github.com/symfony/mime/tree/v5.2.0" }, "funding": [ { @@ -5955,7 +6219,7 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-10-30T14:55:39+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6688,16 +6952,16 @@ }, { "name": "symfony/process", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "f00872c3f6804150d6a0f73b4151daab96248101" + "reference": "240e74140d4d956265048f3025c0aecbbc302d54" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/f00872c3f6804150d6a0f73b4151daab96248101", - "reference": "f00872c3f6804150d6a0f73b4151daab96248101", + "url": "https://api.github.com/repos/symfony/process/zipball/240e74140d4d956265048f3025c0aecbbc302d54", + "reference": "240e74140d4d956265048f3025c0aecbbc302d54", "shasum": "" }, "require": { @@ -6730,7 +6994,7 @@ "description": "Symfony Process Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v5.1.8" + "source": "https://github.com/symfony/process/tree/v5.2.0" }, "funding": [ { @@ -6746,20 +7010,20 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-11-02T15:47:15+00:00" }, { "name": "symfony/routing", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "d6ceee2a37b61b41079005207bf37746d1bfe71f" + "reference": "130ac5175ad2fd417978baebd8062e2e6b2bc28b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/d6ceee2a37b61b41079005207bf37746d1bfe71f", - "reference": "d6ceee2a37b61b41079005207bf37746d1bfe71f", + "url": "https://api.github.com/repos/symfony/routing/zipball/130ac5175ad2fd417978baebd8062e2e6b2bc28b", + "reference": "130ac5175ad2fd417978baebd8062e2e6b2bc28b", "shasum": "" }, "require": { @@ -6773,7 +7037,7 @@ "symfony/yaml": "<4.4" }, "require-dev": { - "doctrine/annotations": "~1.2", + "doctrine/annotations": "^1.7", "psr/log": "~1.0", "symfony/config": "^5.0", "symfony/dependency-injection": "^4.4|^5.0", @@ -6820,7 +7084,7 @@ "url" ], "support": { - "source": "https://github.com/symfony/routing/tree/v5.1.8" + "source": "https://github.com/symfony/routing/tree/v5.2.0" }, "funding": [ { @@ -6836,7 +7100,7 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-11-27T00:39:34+00:00" }, { "name": "symfony/service-contracts", @@ -6919,16 +7183,16 @@ }, { "name": "symfony/string", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a97573e960303db71be0dd8fda9be3bca5e0feea" + "reference": "40e975edadd4e32cd16f3753b3bad65d9ac48242" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a97573e960303db71be0dd8fda9be3bca5e0feea", - "reference": "a97573e960303db71be0dd8fda9be3bca5e0feea", + "url": "https://api.github.com/repos/symfony/string/zipball/40e975edadd4e32cd16f3753b3bad65d9ac48242", + "reference": "40e975edadd4e32cd16f3753b3bad65d9ac48242", "shasum": "" }, "require": { @@ -6982,7 +7246,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.1.8" + "source": "https://github.com/symfony/string/tree/v5.2.0" }, "funding": [ { @@ -6998,27 +7262,27 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-10-24T12:08:07+00:00" }, { "name": "symfony/translation", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/translation.git", - "reference": "27980838fd261e04379fa91e94e81e662fe5a1b6" + "reference": "52f486a707510884450df461b5a6429dd7a67379" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation/zipball/27980838fd261e04379fa91e94e81e662fe5a1b6", - "reference": "27980838fd261e04379fa91e94e81e662fe5a1b6", + "url": "https://api.github.com/repos/symfony/translation/zipball/52f486a707510884450df461b5a6429dd7a67379", + "reference": "52f486a707510884450df461b5a6429dd7a67379", "shasum": "" }, "require": { "php": ">=7.2.5", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php80": "^1.15", - "symfony/translation-contracts": "^2" + "symfony/translation-contracts": "^2.3" }, "conflict": { "symfony/config": "<4.4", @@ -7048,6 +7312,9 @@ }, "type": "library", "autoload": { + "files": [ + "Resources/functions.php" + ], "psr-4": { "Symfony\\Component\\Translation\\": "" }, @@ -7072,7 +7339,7 @@ "description": "Symfony Translation Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/translation/tree/v5.1.8" + "source": "https://github.com/symfony/translation/tree/v5.2.0" }, "funding": [ { @@ -7088,7 +7355,7 @@ "type": "tidelift" } ], - "time": "2020-10-24T12:01:57+00:00" + "time": "2020-11-28T11:24:18+00:00" }, { "name": "symfony/translation-contracts", @@ -7170,16 +7437,16 @@ }, { "name": "symfony/var-dumper", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "4e13f3fcefb1fcaaa5efb5403581406f4e840b9a" + "reference": "173a79c462b1c81e1fa26129f71e41333d846b26" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/4e13f3fcefb1fcaaa5efb5403581406f4e840b9a", - "reference": "4e13f3fcefb1fcaaa5efb5403581406f4e840b9a", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/173a79c462b1c81e1fa26129f71e41333d846b26", + "reference": "173a79c462b1c81e1fa26129f71e41333d846b26", "shasum": "" }, "require": { @@ -7238,7 +7505,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v5.1.8" + "source": "https://github.com/symfony/var-dumper/tree/v5.2.0" }, "funding": [ { @@ -7254,7 +7521,7 @@ "type": "tidelift" } ], - "time": "2020-10-27T10:11:13+00:00" + "time": "2020-11-27T00:39:34+00:00" }, { "name": "tijsverkoyen/css-to-inline-styles", @@ -7463,6 +7730,59 @@ ], "time": "2020-11-12T00:07:28+00:00" }, + { + "name": "webmozart/assert", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/webmozart/assert.git", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", + "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", + "shasum": "" + }, + "require": { + "php": "^5.3.3 || ^7.0 || ^8.0", + "symfony/polyfill-ctype": "^1.8" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<3.9.1" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.36 || ^7.5.13" + }, + "type": "library", + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozart/assert/issues", + "source": "https://github.com/webmozart/assert/tree/master" + }, + "time": "2020-07-08T17:02:28+00:00" + }, { "name": "yarri/link-finder", "version": "v2.6", @@ -7669,16 +7989,16 @@ }, { "name": "fakerphp/faker", - "version": "v1.11.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/FakerPHP/Faker.git", - "reference": "f228dc5112bafc14c77d40a2acc0c48058e184b0" + "reference": "9aa6c9e289860951e6b4d010c7a841802d015cd8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/f228dc5112bafc14c77d40a2acc0c48058e184b0", - "reference": "f228dc5112bafc14c77d40a2acc0c48058e184b0", + "url": "https://api.github.com/repos/FakerPHP/Faker/zipball/9aa6c9e289860951e6b4d010c7a841802d015cd8", + "reference": "9aa6c9e289860951e6b4d010c7a841802d015cd8", "shasum": "" }, "require": { @@ -7715,9 +8035,9 @@ ], "support": { "issues": "https://github.com/FakerPHP/Faker/issues", - "source": "https://github.com/FakerPHP/Faker/tree/v1.11.0" + "source": "https://github.com/FakerPHP/Faker/tree/v1.12.0" }, - "time": "2020-11-15T20:27:00+00:00" + "time": "2020-11-23T09:33:08+00:00" }, { "name": "hamcrest/hamcrest-php", @@ -7772,16 +8092,16 @@ }, { "name": "laravel/browser-kit-testing", - "version": "v6.2.1", + "version": "v6.2.2", "source": { "type": "git", "url": "https://github.com/laravel/browser-kit-testing.git", - "reference": "5f86191b955c88a888b53754ff75511dc60876da" + "reference": "a8bc92f2bb91db210ed2d8cbf4d6b16fa49453dc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/browser-kit-testing/zipball/5f86191b955c88a888b53754ff75511dc60876da", - "reference": "5f86191b955c88a888b53754ff75511dc60876da", + "url": "https://api.github.com/repos/laravel/browser-kit-testing/zipball/a8bc92f2bb91db210ed2d8cbf4d6b16fa49453dc", + "reference": "a8bc92f2bb91db210ed2d8cbf4d6b16fa49453dc", "shasum": "" }, "require": { @@ -7832,31 +8152,31 @@ ], "support": { "issues": "https://github.com/laravel/browser-kit-testing/issues", - "source": "https://github.com/laravel/browser-kit-testing/tree/v6.2.1" + "source": "https://github.com/laravel/browser-kit-testing/tree/v6.2.2" }, - "time": "2020-11-10T15:33:44+00:00" + "time": "2020-11-24T16:37:28+00:00" }, { "name": "maximebf/debugbar", - "version": "v1.16.3", + "version": "v1.16.4", "source": { "type": "git", "url": "https://github.com/maximebf/php-debugbar.git", - "reference": "1a1605b8e9bacb34cc0c6278206d699772e1d372" + "reference": "c86c717e4bf3c6d98422da5c38bfa7b0f494b04c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/1a1605b8e9bacb34cc0c6278206d699772e1d372", - "reference": "1a1605b8e9bacb34cc0c6278206d699772e1d372", + "url": "https://api.github.com/repos/maximebf/php-debugbar/zipball/c86c717e4bf3c6d98422da5c38bfa7b0f494b04c", + "reference": "c86c717e4bf3c6d98422da5c38bfa7b0f494b04c", "shasum": "" }, "require": { - "php": "^7.1", + "php": "^7.1|^8", "psr/log": "^1.0", "symfony/var-dumper": "^2.6|^3|^4|^5" }, "require-dev": { - "phpunit/phpunit": "^5" + "phpunit/phpunit": "^7.5.20 || ^9.4.2" }, "suggest": { "kriswallsmith/assetic": "The best way to manage assets", @@ -7897,9 +8217,9 @@ ], "support": { "issues": "https://github.com/maximebf/php-debugbar/issues", - "source": "https://github.com/maximebf/php-debugbar/tree/v1.16.3" + "source": "https://github.com/maximebf/php-debugbar/tree/v1.16.4" }, - "time": "2020-05-06T07:06:27+00:00" + "time": "2020-12-07T10:48:48+00:00" }, { "name": "mockery/mockery", @@ -8181,16 +8501,16 @@ }, { "name": "phar-io/version", - "version": "3.0.2", + "version": "3.0.3", "source": { "type": "git", "url": "https://github.com/phar-io/version.git", - "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0" + "reference": "726c026815142e4f8677b7cb7f2249c9ffb7ecae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phar-io/version/zipball/c6bb6825def89e0a32220f88337f8ceaf1975fa0", - "reference": "c6bb6825def89e0a32220f88337f8ceaf1975fa0", + "url": "https://api.github.com/repos/phar-io/version/zipball/726c026815142e4f8677b7cb7f2249c9ffb7ecae", + "reference": "726c026815142e4f8677b7cb7f2249c9ffb7ecae", "shasum": "" }, "require": { @@ -8226,9 +8546,9 @@ "description": "Library for handling version information and constraints", "support": { "issues": "https://github.com/phar-io/version/issues", - "source": "https://github.com/phar-io/version/tree/master" + "source": "https://github.com/phar-io/version/tree/3.0.3" }, - "time": "2020-06-27T14:39:04+00:00" + "time": "2020-11-30T09:21:21+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -8457,16 +8777,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.3", + "version": "9.2.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "6b20e2055f7c29b56cb3870b3de7cc463d7add41" + "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6b20e2055f7c29b56cb3870b3de7cc463d7add41", - "reference": "6b20e2055f7c29b56cb3870b3de7cc463d7add41", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/f3e026641cc91909d421802dd3ac7827ebfd97e1", + "reference": "f3e026641cc91909d421802dd3ac7827ebfd97e1", "shasum": "" }, "require": { @@ -8480,7 +8800,7 @@ "sebastian/code-unit-reverse-lookup": "^2.0.2", "sebastian/complexity": "^2.0", "sebastian/environment": "^5.1.2", - "sebastian/lines-of-code": "^1.0", + "sebastian/lines-of-code": "^1.0.3", "sebastian/version": "^3.0.1", "theseer/tokenizer": "^1.2.0" }, @@ -8522,7 +8842,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.3" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.5" }, "funding": [ { @@ -8530,7 +8850,7 @@ "type": "github" } ], - "time": "2020-10-30T10:46:41+00:00" + "time": "2020-11-28T06:44:49+00:00" }, { "name": "phpunit/php-file-iterator", @@ -8775,16 +9095,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.4.3", + "version": "9.5.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab" + "reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab", - "reference": "9fa359ff5ddaa5eb2be2bedb08a6a5787a5807ab", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/8e16c225d57c3d6808014df6b1dd7598d0a5bbbe", + "reference": "8e16c225d57c3d6808014df6b1dd7598d0a5bbbe", "shasum": "" }, "require": { @@ -8800,7 +9120,7 @@ "phar-io/version": "^3.0.2", "php": ">=7.3", "phpspec/prophecy": "^1.12.1", - "phpunit/php-code-coverage": "^9.2", + "phpunit/php-code-coverage": "^9.2.3", "phpunit/php-file-iterator": "^3.0.5", "phpunit/php-invoker": "^3.1.1", "phpunit/php-text-template": "^2.0.3", @@ -8831,7 +9151,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.4-dev" + "dev-master": "9.5-dev" } }, "autoload": { @@ -8862,7 +9182,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.4.3" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.5.0" }, "funding": [ { @@ -8874,7 +9194,7 @@ "type": "github" } ], - "time": "2020-11-10T12:53:30+00:00" + "time": "2020-12-04T05:05:53+00:00" }, { "name": "sebastian/cli-parser", @@ -9446,16 +9766,16 @@ }, { "name": "sebastian/lines-of-code", - "version": "1.0.2", + "version": "1.0.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "acf76492a65401babcf5283296fa510782783a7a" + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/acf76492a65401babcf5283296fa510782783a7a", - "reference": "acf76492a65401babcf5283296fa510782783a7a", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/c1c2e997aa3146983ed888ad08b15470a2e22ecc", + "reference": "c1c2e997aa3146983ed888ad08b15470a2e22ecc", "shasum": "" }, "require": { @@ -9491,7 +9811,7 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.2" + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.3" }, "funding": [ { @@ -9499,7 +9819,7 @@ "type": "github" } ], - "time": "2020-10-26T17:03:56+00:00" + "time": "2020-11-28T06:42:11+00:00" }, { "name": "sebastian/object-enumerator", @@ -9842,16 +10162,16 @@ }, { "name": "symfony/debug", - "version": "v4.4.16", + "version": "v4.4.17", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "c87adf3fc1cd0bf4758316a3a150d50a8f957ef4" + "reference": "65fe7b49868378319b82da3035fb30801b931c47" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/c87adf3fc1cd0bf4758316a3a150d50a8f957ef4", - "reference": "c87adf3fc1cd0bf4758316a3a150d50a8f957ef4", + "url": "https://api.github.com/repos/symfony/debug/zipball/65fe7b49868378319b82da3035fb30801b931c47", + "reference": "65fe7b49868378319b82da3035fb30801b931c47", "shasum": "" }, "require": { @@ -9891,7 +10211,7 @@ "description": "Symfony Debug Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/debug/tree/v4.4.16" + "source": "https://github.com/symfony/debug/tree/v4.4.17" }, "funding": [ { @@ -9907,11 +10227,11 @@ "type": "tidelift" } ], - "time": "2020-10-24T11:50:19+00:00" + "time": "2020-10-28T20:42:29+00:00" }, { "name": "symfony/dom-crawler", - "version": "v5.1.8", + "version": "v5.2.0", "source": { "type": "git", "url": "https://github.com/symfony/dom-crawler.git", @@ -9965,7 +10285,7 @@ "description": "Symfony DomCrawler Component", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/dom-crawler/tree/v5.1.8" + "source": "https://github.com/symfony/dom-crawler/tree/v5.2.0" }, "funding": [ { @@ -10032,59 +10352,6 @@ } ], "time": "2020-07-12T23:59:07+00:00" - }, - { - "name": "webmozart/assert", - "version": "1.9.1", - "source": { - "type": "git", - "url": "https://github.com/webmozart/assert.git", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/bafc69caeb4d49c39fd0779086c03a3738cbb389", - "reference": "bafc69caeb4d49c39fd0779086c03a3738cbb389", - "shasum": "" - }, - "require": { - "php": "^5.3.3 || ^7.0 || ^8.0", - "symfony/polyfill-ctype": "^1.8" - }, - "conflict": { - "phpstan/phpstan": "<0.12.20", - "vimeo/psalm": "<3.9.1" - }, - "require-dev": { - "phpunit/phpunit": "^4.8.36 || ^7.5.13" - }, - "type": "library", - "autoload": { - "psr-4": { - "Webmozart\\Assert\\": "src/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Bernhard Schussek", - "email": "bschussek@gmail.com" - } - ], - "description": "Assertions to validate method input/output with nice error messages.", - "keywords": [ - "assert", - "check", - "validate" - ], - "support": { - "issues": "https://github.com/webmozart/assert/issues", - "source": "https://github.com/webmozart/assert/tree/master" - }, - "time": "2020-07-08T17:02:28+00:00" } ], "aliases": [], diff --git a/config/services.php b/config/services.php index 0d7315dc8..a59a428cb 100644 --- a/config/services.php +++ b/config/services.php @@ -44,4 +44,11 @@ ], ], + 'twitter' => [ + 'consumer_key' => env('TWITTER_CONSUMER_KEY'), + 'consumer_secret' => env('TWITTER_CONSUMER_SECRET'), + 'access_token' => env('TWITTER_ACCESS_TOKEN'), + 'access_secret' => env('TWITTER_ACCESS_SECRET'), + ], + ]; diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 0beef2c30..86f3282b8 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -34,6 +34,7 @@ public function definition() 'remember_token' => Str::random(10), 'github_id' => $this->faker->numberBetween(10000, 99999), 'github_username' => $this->faker->userName, + 'twitter' => $this->faker->userName, 'banned_at' => null, 'type' => User::DEFAULT, 'bio' => $this->faker->sentence, diff --git a/database/migrations/2020_07_16_185353_add_twitter_columns.php b/database/migrations/2020_07_16_185353_add_twitter_columns.php new file mode 100644 index 000000000..eca53374c --- /dev/null +++ b/database/migrations/2020_07_16_185353_add_twitter_columns.php @@ -0,0 +1,20 @@ +unsignedBigInteger('tweet_id')->after('is_pinned')->nullable(); + $table->dateTime('shared_at')->after('approved_at')->nullable(); + }); + + Schema::table('users', function (Blueprint $table) { + $table->string('twitter')->after('email')->nullable(); + }); + } +} diff --git a/resources/views/articles/_form.blade.php b/resources/views/articles/_form.blade.php index fb98c2c79..7220836d0 100644 --- a/resources/views/articles/_form.blade.php +++ b/resources/views/articles/_form.blade.php @@ -130,5 +130,13 @@ class="block px-4 py-2 text-sm leading-5 text-gray-700 hover:bg-gray-100 hover:t @endif + + @unless (Auth::user()->twitter()) + + Articles will be shared on Twitter. + Add your Twitter handle + and we'll include that too. + + @endunless diff --git a/resources/views/users/_user_info.blade.php b/resources/views/users/_user_info.blade.php index 4d8fc40e0..028200d34 100644 --- a/resources/views/users/_user_info.blade.php +++ b/resources/views/users/_user_info.blade.php @@ -51,9 +51,8 @@
@if ($user->githubUsername()) - - + + {{ '@' . $user->githubUsername() }} @@ -61,6 +60,17 @@ class="text-lio-700 text-3xl block flex items-center"> @endif + + @if ($user->twitter()) + + + + + {{ '@' . $user->twitter() }} + + + + @endif
diff --git a/resources/views/users/settings/profile.blade.php b/resources/views/users/settings/profile.blade.php index 5fcde1ea2..bcb6c42d6 100644 --- a/resources/views/users/settings/profile.blade.php +++ b/resources/views/users/settings/profile.blade.php @@ -41,6 +41,12 @@ @error('username') @endFormGroup + @formGroup('twitter') + + + @error('twitter_handle') + @endFormGroup + @formGroup('bio') diff --git a/tests/Feature/SettingsTest.php b/tests/Feature/SettingsTest.php index cba36fd41..2d39fcabe 100644 --- a/tests/Feature/SettingsTest.php +++ b/tests/Feature/SettingsTest.php @@ -27,11 +27,13 @@ public function users_can_update_their_profile() 'name' => 'Freek Murze', 'email' => 'freek@example.com', 'username' => 'freekmurze', + 'twitter' => 'freektwitter', 'bio' => 'My bio', ]) ->seePageIs('/settings') ->see('Freek Murze') ->see('freekmurze') + ->see('freektwitter') ->see('Settings successfully saved!') ->see('My bio'); } @@ -110,6 +112,26 @@ public function users_can_set_their_password_when_they_have_none_set_yet() $this->assertPasswordWasHashedAndSaved(); } + /** @test */ + public function twitter_is_optional() + { + $user = $this->createUser(['email' => 'freek@example.com', 'username' => 'freekmurze', 'twitter' => 'freektwitter']); + + $this->loginAs($user); + + $this->visit('/settings') + ->submitForm('Save', [ + 'name' => 'Freek Murze', + 'email' => 'freek@example.com', + 'username' => 'freekmurze', + 'twitter' => '', + ]) + ->seePageIs('/settings') + ->dontSee('freektwitter'); + + $this->assertNull($user->fresh()->twitter()); + } + private function assertPasswordWasHashedAndSaved(): void { $this->assertTrue($this->app['hash']->check('newpassword', Auth::user()->getAuthPassword())); diff --git a/tests/Unit/Commands/PostArticleToTwitterTest.php b/tests/Unit/Commands/PostArticleToTwitterTest.php new file mode 100644 index 000000000..0f801e2a0 --- /dev/null +++ b/tests/Unit/Commands/PostArticleToTwitterTest.php @@ -0,0 +1,135 @@ +create([ + 'title' => 'My First Article', + 'submitted_at' => now(), + 'approved_at' => now(), + ]); + + (new PostArticleToTwitter(new AnonymousNotifiable()))->handle(); + + Notification::assertSentTo( + new AnonymousNotifiable(), + PostArticleToTwitterNotification::class, + function ($notification, $channels, $notifiable) use ($article) { + $tweet = $notification->generateTweet(); + + return + Str::contains($tweet, 'My First Article') && + Str::contains($tweet, route('articles.show', $article->slug())); + }, + ); + + $this->assertTrue($article->fresh()->isShared()); + } + + /** @test */ + public function articles_are_shared_with_twitter_handle() + { + $user = $this->createUser([ + 'twitter' => '_joedixon', + ]); + + Article::factory()->create([ + 'author_id' => $user->id(), + 'submitted_at' => now(), + 'approved_at' => now(), + ]); + + (new PostArticleToTwitter(new AnonymousNotifiable()))->handle(); + + Notification::assertSentTo( + new AnonymousNotifiable(), + PostArticleToTwitterNotification::class, + function ($notification, $channels, $notifiable) { + return Str::contains($notification->generateTweet(), '@_joedixon'); + }, + ); + } + + /** @test */ + public function articles_are_shared_with_name_when_no_twitter_handle() + { + $user = $this->createUser([ + 'name' => 'Joe Dixon', + 'twitter' => null, + ]); + + Article::factory()->create([ + 'author_id' => $user->id(), + 'submitted_at' => now(), + 'approved_at' => now(), + ]); + + (new PostArticleToTwitter(new AnonymousNotifiable()))->handle(); + + Notification::assertSentTo( + new AnonymousNotifiable(), + PostArticleToTwitterNotification::class, + function ($notification, $channels, $notifiable) { + return Str::contains($notification->generateTweet(), 'Joe Dixon'); + }, + ); + } + + /** @test */ + public function already_shared_articles_are_not_shared_again() + { + Article::factory()->create([ + 'submitted_at' => now(), + 'approved_at' => now(), + 'shared_at' => now(), + ]); + + (new PostArticleToTwitter(new AnonymousNotifiable()))->handle(); + + Notification::assertNothingSent(); + } + + /** @test */ + public function unapproved_articles_are_not_shared() + { + Article::factory()->create([ + 'submitted_at' => now(), + ]); + + (new PostArticleToTwitter(new AnonymousNotifiable()))->handle(); + + Notification::assertNothingSent(); + } + + /** @test */ + public function unsubmitted_articles_are_not_shared() + { + Article::factory()->create(); + + (new PostArticleToTwitter(new AnonymousNotifiable()))->handle(); + + Notification::assertNothingSent(); + } +}