public function recipientsCount()
{
- return ['data' => \App\User::recievesEmails()->count()];
+ return ['data' => \App\User::receivesEmails()->count()];
}
/**
}
+ public function discover(PdfFile $file, Request $request)
+ {
+ if (! $request->hasValidSignature()) {
+ abort(401);
+ }
+ AccessLog::log($request, $file);
+ return $file->view();
+
+ }
+
+
/**
* @param PdfFile $file
* @param Request $request
namespace App\Http\Middleware;
use App\LoginToken;
+use App\User;
use Closure;
class LoginWithToken
public function handle($request, Closure $next, $delete = true)
{
LoginToken::checkAndLogin($request, filter_var($delete, FILTER_VALIDATE_BOOLEAN));
+ if(\Auth::check()) {
+ /** @var User $user */
+ $user = \Auth::user();
+ $user->markEmailAsVerified();
+ }
return $next($request);
}
'city' => $row['city'],
'phone' => $phone,
'password' => \Hash::make(Str::random()),
+ 'type' => $row['user_type'] ?? User::TYPE_SUBSCRIBER
]);
}
$this->batch = $batch;
$this->type = $type;
$this->users = $recipientGroup === null ?
- User::recievesEmails()->get() :
+ User::receivesEmails()->get() :
PublishController::sendGroups()[$recipientGroup['slug']]['builder']->get();
}
$fileVar = $this->batch->file === null ?
[] :
- ['file_url' => $this->batch->file->getUrlWithToken($user)];
+ ['file_url' => $this->batch->file->getMailableUrl($user)];
return [
public function toMail($notifiable)
{
return (new MailMessage)
- ->subject('Inscription réussie !')
- ->line("Bienvenue ! Vous bénéficiez dès aujourd'hui d'une période d'essai de ".User::trialDurationDays." jours.")
- ->line('Merci [....]');
+ ->subject('Email validé !')
+ ->line("Votre adresse email à bien été validée.");
}
/**
public $showOnTableRow = true;
public $confirmButtonText = "Appliquer";
- public $name = "Démarrer période d'essai";
+ public $name = "Démarrer période de découverte";
public function __construct()
{
- $this->confirmText = sprintf("Etes vous sûr de vouloir activer une période d'essai de %d jours ?", User::trialDurationDays);
-
+ $this->confirmText = sprintf("Etes vous sûr de vouloir activer une période de découverte de %d jours ?", User::TRIAL_DURATION_DAYS);
}
*/
public function handle(ActionFields $fields, Collection $models)
{
- $models->map->startTrial();
+ $models->map->startDiscover();
- return Action::message(sprintf("La période d'essai à bien été activée pour %d utilisteur(s)", $models->count()));
+ return Action::message(sprintf("La période de découverte à bien été activée pour %d utilisteur(s)", $models->count()));
}
/**
--- /dev/null
+<?php
+
+
+namespace App\Nova;
+
+
+use Laravel\Nova\Http\Requests\NovaRequest;
+
+class DiscoverUsers extends User
+{
+ public static $group = "Annuaire";
+
+ public static $type = \App\User::TYPE_DISCOVER;
+
+
+ public static function label()
+ {
+ return "Utilisateurs découverte";
+ }
+
+ public static function singularLabel()
+ {
+ return "Utilisateur (découverte)";
+ }
+
+
+
+}
{
public static $group = "Annuaire";
+ public static $type = \App\User::TYPE_PROSPECT;
+
public static function label()
{
return "Prospect";
}
- public static function indexQuery(NovaRequest $request, $query)
- {
- return $query->where('type', 1);
- }
-
}
class SpecialUsers extends User
{
public static $group = "Annuaire";
+ public static $type = \App\User::TYPE_SPECIAL;
public static function label()
return "Utilisateur (autre)";
}
- public static function indexQuery(NovaRequest $request, $query)
- {
- return $query->where('type', 2);
- }
+
}
}
- public static function indexQuery(NovaRequest $request, $query)
- {
- return $query->where('type', 0);
- }
public function filters(Request $request)
{
*/
public static $model = AppUser::class;
+ public static $type;
/**
Select::make('Type')->options([
AppUser::TYPE_SUBSCRIBER => 'Abonné',
AppUser::TYPE_PROSPECT => 'Prospect',
- AppUser::TYPE_SPECIAL => 'Autre'
- ])->hideFromIndex()->required(),
+ AppUser::TYPE_SPECIAL => 'Autre',
+ AppUser::TYPE_DISCOVER => 'Découverte',
+ ])->hideFromIndex()->required()->withMeta(['value' => $this->type ?? static::$type ?? AppUser::TYPE_SUBSCRIBER]),
Badge::make('Etat', fn() => AppUser::STATUSES[$this->status]['label'])
->map(Arr::pluck(AppUser::STATUSES, 'badge', 'label')),
];
}
+ public static function indexQuery(NovaRequest $request, $query)
+ {
+ return static::$type === null ?
+ $query :
+ $query->where('type', static::$type);
+ }
+
+
/**
* Get the cards available for the request.
*
return $user->routeWithToken('flowpaper.view', ['file' => $this->slug]);
}
+ /**
+ * @return string
+ * Returns a signed url for trial users
+ */
+ public function getSignedUrl(): string
+ {
+ return \URL::signedRoute('flowpaper.discover', ['file' => $this->slug]);
+ }
+
+ /**
+ * @param User $user
+ * @return string
+ */
+ public function getMailableUrl(User $user): string
+ {
+ return ($user->type === User::TYPE_DISCOVER) ?
+ $this->getSignedUrl() :
+ $this->getUrlWithToken($user);
+ }
use App\Nova\Metrics\FileAccess;
use App\Nova\Metrics\MailEvents;
use App\Nova\Metrics\MailEventsPartition;
+use App\Nova\Metrics\RegistrationCompletePartition;
use App\Nova\Metrics\TotalUsers;
use App\Nova\Metrics\UsersPartition;
use Illuminate\Support\Facades\Gate;
new TotalUsers,
new UsersPartition,
new FileAccess,
- new MailEvents('opened', 'Mails ouverts'),
+ new MailEvents('clicked', 'Mails cliqués'),
new MailEventsPartition,
+ new RegistrationCompletePartition
+
];
}
* @property string $position
* @property bool $orgIsSubscribed (is user has org subscribed)
* @property Carbon $trial_ends_at (is user is on trial)
+ * @property Carbon $discover_ends_at
* @property bool self_registered (if user used /register)
* @property string $employer (used if self registered)
* @property int $type
+ * @property bool $unsubscribed
* @property bool $reg_complete
+ *
* @property string $status
*/
class User extends Authenticatable implements MustVerifyEmail
'reg_complete' => 'bool',
'trial_ends_at' => 'datetime',
'active_until' => 'datetime',
+ 'discover_ends_at' => 'datetime',
'self_registered' => 'bool',
'early_access' => 'bool',
];
/**
* Trial duration in days
*/
- public const trialDurationDays = 14;
+ public const TRIAL_DURATION_DAYS = 14;
+ /**
+ * Discover duration in days
+ */
+ public const DISCOVER_DURATION_DAYS = 14;
/**
* Possible Statuses
'special' => [
'badge' => 'warning',
'label' => 'Trimestriel',
+ ],
+ 'discover' => [
+ 'badge' => 'info',
+ 'label' => 'Découverte',
+ ],
+ 'discover_expired' => [
+ 'badge' => 'warning',
+ 'label' => 'Découverte expiré',
+ ],
+ 'unsubscribed' => [
+ 'badge' => 'danger',
+ 'label' => 'Désabonné',
]
];
public const TYPE_SUBSCRIBER = 0;
public const TYPE_PROSPECT = 1;
public const TYPE_SPECIAL = 2;
-
+ public const TYPE_DISCOVER = 3;
/**
* @return array
*/
public function startTrial(): void
{
- $this->trial_ends_at = now()->addDays(self::trialDurationDays);
+ $this->trial_ends_at = now()->addDays(self::TRIAL_DURATION_DAYS);
+ $this->save();
+ }
+
+ /**
+ * Starts discover period
+ */
+ public function startDiscover(): void
+ {
+ $this->discover_ends_at = now()->addDays(self::DISCOVER_DURATION_DAYS);
+ $this->type = self::TYPE_DISCOVER;
$this->save();
}
$o->isSubscribed();
}
+ /**
+ * @return bool
+ */
+ public function isOnDiscovery(): bool
+ {
+ return $this->discover_ends_at !== null &&
+ $this->discover_ends_at->isFuture();
+ }
+
+
+
/**
* SCOPES
*/
+
+
/**
* @param Builder $builder
*/
- public function scopeRecievesEmails(Builder $builder): void
+ public function scopeReceivesEmails(Builder $builder): void
{
-// $builder->where('id', 1);
- $builder->hasActiveSubscription()->orWhere->isOnTrial();
+ $builder->where('unsubscribed', '0');
+ $builder->hasActiveSubscription()->orWhere->isOnTrial()->orWhere->isOnDiscovery();
}
/**
$builder->whereDate('trial_ends_at', '>', now());
}
+
+ /**
+ * @param Builder $builder
+ */
+ public function scopeIsOnDiscovery(Builder $builder): void
+ {
+ $builder->whereDate('discover_ends_at', '>', now());
+ }
+
+
+
+ /**
+ * @param Builder $builder
+ */
+ public function scopeHasActiveSubscription(Builder $builder): void
+ {
+ $builder->hasOrgSubscription()->orWhere->hasIndSubscription();
+ }
+
/**
* @param Builder $builder
*/
/**
* @param Builder $builder
*/
- public function scopeHasActiveSubscription(Builder $builder): void
+ public function scopeProspect(Builder $builder): void
{
- $builder->hasOrgSubscription()->orWhere->hasIndSubscription();
+ $builder->where('type', self::TYPE_PROSPECT);
}
/**
* @param Builder $builder
*/
- public function scopeProspect(Builder $builder): void
+ public function scopeRegisteredUser(Builder $builder): void
{
- $builder->where('type', self::TYPE_PROSPECT);
+ $builder->where('type', self::TYPE_SUBSCRIBER);
}
-
/**
* @param Builder $builder
*/
- public function scopeRegisteredUser(Builder $builder): void
+ public function scopeDiscoverUser(Builder $builder): void
{
- $builder->where('type', self::TYPE_SUBSCRIBER);
+ $builder->where('type', self::TYPE_DISCOVER);
}
/**
{
$id = 'inactive';
+ if($this->unsubscribed) {
+ return 'unsubscribed';
+ }
+
switch($this->type) {
case self::TYPE_SUBSCRIBER:
if($this->orgIsSubscribed) {
case self::TYPE_SPECIAL:
$id = 'special';
break;
+
+ case self::TYPE_DISCOVER:
+ if($this->isOnDiscovery()) {
+ $id = 'discover';
+ } else if ($this->discover_ends_at === null){
+ $id = 'inactive';
+ } else {
+ $id = 'discover_expired';
+ }
+
+ break;
}
--- /dev/null
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddDiscoverUntilColumnToUsersTable extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::table('users', function (Blueprint $table) {
+ $table->dateTime('discover_ends_at')->nullable();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('users', function (Blueprint $table) {
+ $table->dropColumn('discover_ends_at');
+ });
+ }
+}
--- /dev/null
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddUnsubscribeColumnToUsersTable extends Migration
+{
+ /**
+ * Run the migrations.
+ *
+ * @return void
+ */
+ public function up()
+ {
+ Schema::table('users', function (Blueprint $table) {
+ $table->boolean('unsubscribed')->default(0);
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::table('users', function (Blueprint $table) {
+ $table->dropColumn('unsubscribed');
+ });
+ }
+}
<div class="truncated">
{!! $article->getTruncatedContent() !!}
</div>
- <div class="alert alert-warning">
+ <div class="alert alert-warning mt-4">
Cet article est réservé aux abonnés ! Pour y accéder merci de vous connecter, ou
<a href="{{route('not-registered')}}" >cliquez ici pour découvrir nos formules d'abonnement.</a>
</div>
->get('/view/{file:slug}', 'FlowpaperController@view')
->name('flowpaper.view');
+ Route::get('/discover/{file:slug}', 'FlowpaperController@discover')->name('flowpaper.discover');
+
Route::get('edition/{file:slug}', 'FileController@show');